use crate::c_types::{CScalar, StrLenOrInd};
use crate::convert::{AsMutPtr, AsMutSQLPOINTER, IntoSQLPOINTER};
use crate::desc::AppDesc;
use crate::env::OdbcVersion;
use crate::handle::{RefSQLHDESC, RefUnsafeSQLHDESC, UnsafeSQLHDESC, SQLHDESC};
use crate::str::{OdbcChar, OdbcStr};
use crate::{
slice_len, Def, DriverDefined, Ident, OdbcDefined, Scalar, SQLCHAR, SQLINTEGER, SQLLEN,
SQLSMALLINT, SQLUINTEGER, SQLULEN, SQLUSMALLINT, SQLWCHAR,
};
use core::{cell::UnsafeCell, fmt::Debug, mem::MaybeUninit};
pub unsafe trait Attr<A: Ident> {
type DefinedBy: Def;
}
pub unsafe trait AttrGet<A: Ident>: Attr<A> + AsMutSQLPOINTER + AttrZeroAssert {}
pub unsafe trait AttrSet<A: Ident>: IntoSQLPOINTER + Sized {}
#[derive(Debug, Clone, Copy)]
pub enum Void {}
pub unsafe trait StrLen<T: Scalar> {
fn as_mut_ptr(&mut self) -> *mut T;
}
pub unsafe trait AttrLen<AD: Def, LEN: Scalar> {
type StrLen: StrLen<LEN>;
fn len(&self) -> LEN;
}
pub trait AttrZeroAssert {
fn assert_zeroed(&self) {}
}
unsafe impl<A: Ident, T: Scalar> Attr<A> for MaybeUninit<T>
where
T: Attr<A> + AttrGet<A>,
{
type DefinedBy = T::DefinedBy;
}
unsafe impl<A: Ident, T> Attr<A> for [MaybeUninit<T>]
where
[T]: Attr<A> + AttrGet<A>,
{
type DefinedBy = <[T] as Attr<A>>::DefinedBy;
}
unsafe impl<A: Ident> Attr<A> for OdbcStr<MaybeUninit<SQLCHAR>>
where
OdbcStr<SQLCHAR>: Attr<A> + AttrGet<A>,
{
type DefinedBy = <OdbcStr<SQLCHAR> as Attr<A>>::DefinedBy;
}
unsafe impl<A: Ident> Attr<A> for OdbcStr<MaybeUninit<SQLWCHAR>>
where
OdbcStr<SQLWCHAR>: Attr<A> + AttrGet<A>,
{
type DefinedBy = <OdbcStr<SQLWCHAR> as Attr<A>>::DefinedBy;
}
unsafe impl<A: Ident, T> Attr<A> for &[T]
where
[T]: Attr<A>,
{
type DefinedBy = <[T] as Attr<A>>::DefinedBy;
}
unsafe impl<A: Ident, CH: OdbcChar> Attr<A> for &OdbcStr<CH>
where
OdbcStr<CH>: Attr<A>,
{
type DefinedBy = <OdbcStr<CH> as Attr<A>>::DefinedBy;
}
unsafe impl<A: Ident, T: Scalar> AttrGet<A> for MaybeUninit<T>
where
T: AttrGet<A>,
Self: AsMutSQLPOINTER,
{
}
unsafe impl<A: Ident> AttrGet<A> for OdbcStr<MaybeUninit<SQLCHAR>> where OdbcStr<SQLCHAR>: AttrGet<A>
{}
unsafe impl<A: Ident> AttrGet<A> for OdbcStr<MaybeUninit<SQLWCHAR>> where
OdbcStr<SQLWCHAR>: AttrGet<A>
{
}
unsafe impl<A: Ident, T: Scalar> AttrSet<A> for MaybeUninit<T>
where
Self: IntoSQLPOINTER,
T: AttrSet<A>,
{
}
unsafe impl<AD: Def, T: Ident, LEN: Scalar> AttrLen<AD, LEN> for T
where
MaybeUninit<T>: AttrLen<AD, LEN>,
LEN: From<SQLSMALLINT>,
{
type StrLen = Void;
fn len(&self) -> LEN {
<MaybeUninit<_> as AttrLen<AD, LEN>>::len(unsafe { core::mem::transmute(self) })
}
}
unsafe impl<T: Ident, LEN: Scalar> AttrLen<OdbcDefined, LEN> for MaybeUninit<T>
where
LEN: From<SQLSMALLINT>,
{
type StrLen = Void;
fn len(&self) -> LEN {
LEN::from(0)
}
}
unsafe impl<T: Ident, LEN: Scalar> AttrLen<DriverDefined, LEN> for MaybeUninit<T>
where
LEN: From<T::Type>,
{
type StrLen = Void;
fn len(&self) -> LEN {
LEN::from(T::IDENTIFIER)
}
}
unsafe impl<AD: Def, CH: OdbcChar, LEN: Scalar> AttrLen<AD, LEN> for OdbcStr<CH>
where
LEN: TryFrom<usize>,
LEN::Error: Debug,
OdbcStr<MaybeUninit<CH>>: AttrLen<AD, LEN>,
{
type StrLen = <OdbcStr<MaybeUninit<CH>> as AttrLen<AD, LEN>>::StrLen;
fn len(&self) -> LEN {
<OdbcStr<MaybeUninit<CH>> as AttrLen<AD, LEN>>::len(unsafe { core::mem::transmute(self) })
}
}
unsafe impl<AD: Def, CH: OdbcChar, LEN: Scalar> AttrLen<AD, LEN> for OdbcStr<MaybeUninit<CH>>
where
LEN: TryFrom<usize> + core::ops::Mul<Output = LEN>,
LEN::Error: Debug,
{
type StrLen = LEN;
fn len(&self) -> LEN {
slice_len::<_, LEN>(self) * LEN::try_from(core::mem::size_of::<CH>()).unwrap()
}
}
unsafe impl<LEN: Scalar> AttrLen<OdbcDefined, LEN> for [MaybeUninit<SQLCHAR>]
where
LEN: TryFrom<usize>,
LEN::Error: Debug,
{
type StrLen = LEN;
fn len(&self) -> LEN {
slice_len(self)
}
}
unsafe impl<LEN: Scalar> AttrLen<DriverDefined, LEN> for [MaybeUninit<SQLCHAR>] {
type StrLen = LEN;
fn len(&self) -> LEN {
unimplemented!();
}
}
unsafe impl<AD: Def, LEN: Scalar> AttrLen<AD, LEN> for [SQLCHAR]
where
[MaybeUninit<SQLCHAR>]: AttrLen<AD, LEN>,
{
type StrLen = <[MaybeUninit<SQLCHAR>] as AttrLen<AD, LEN>>::StrLen;
fn len(&self) -> LEN {
<[MaybeUninit<SQLCHAR>] as AttrLen<AD, LEN>>::len(unsafe { core::mem::transmute(self) })
}
}
unsafe impl<AD: Def, T: Ident, LEN: Scalar> AttrLen<AD, LEN> for [T]
where
LEN: From<SQLSMALLINT>,
{
type StrLen = Void;
fn len(&self) -> LEN {
LEN::from(0)
}
}
unsafe impl<AD: Def, LEN: Scalar, CH: OdbcChar> AttrLen<AD, LEN> for &OdbcStr<CH>
where
OdbcStr<CH>: AttrLen<AD, LEN>,
{
type StrLen = <OdbcStr<CH> as AttrLen<AD, LEN>>::StrLen;
fn len(&self) -> LEN {
AttrLen::len(*self)
}
}
unsafe impl<AD: Def, LEN: Scalar, T> AttrLen<AD, LEN> for &[T]
where
[T]: AttrLen<AD, LEN>,
{
type StrLen = <[T] as AttrLen<AD, LEN>>::StrLen;
fn len(&self) -> LEN {
AttrLen::len(*self)
}
}
unsafe impl<AD: Def, T: CScalar> AttrLen<AD, SQLINTEGER> for UnsafeCell<T> {
type StrLen = Void;
fn len(&self) -> SQLINTEGER {
0
}
}
unsafe impl<AD: Def, T> AttrLen<AD, SQLINTEGER> for [UnsafeCell<T>] {
type StrLen = Void;
fn len(&self) -> SQLINTEGER {
0 }
}
unsafe impl<DT, LEN: Scalar, V: OdbcVersion> AttrLen<OdbcDefined, LEN>
for MaybeUninit<RefUnsafeSQLHDESC<'_, DT, V>>
where
LEN: From<SQLSMALLINT>,
{
type StrLen = Void;
fn len(&self) -> LEN {
LEN::from(0)
}
}
unsafe impl<DT, LEN: Scalar, V: OdbcVersion> AttrLen<DriverDefined, LEN>
for MaybeUninit<RefUnsafeSQLHDESC<'_, DT, V>>
where
LEN: From<SQLSMALLINT>,
{
type StrLen = Void;
fn len(&self) -> LEN {
LEN::from(crate::SQL_IS_POINTER)
}
}
unsafe impl<'conn, AD: Def, DT, LEN: Scalar, V: OdbcVersion> AttrLen<AD, LEN>
for MaybeUninit<RefSQLHDESC<'conn, DT, V>>
where
MaybeUninit<RefUnsafeSQLHDESC<'conn, DT, V>>: AttrLen<AD, LEN>,
LEN: From<SQLSMALLINT>,
{
type StrLen = <MaybeUninit<RefUnsafeSQLHDESC<'conn, DT, V>> as AttrLen<AD, LEN>>::StrLen;
fn len(&self) -> LEN {
unsafe { core::mem::transmute::<_, &MaybeUninit<RefUnsafeSQLHDESC<'conn, DT, V>>>(self) }
.len()
}
}
unsafe impl<LEN: Scalar, V: OdbcVersion> AttrLen<OdbcDefined, LEN>
for Option<&UnsafeSQLHDESC<'_, AppDesc<'_>, V>>
where
LEN: From<SQLSMALLINT>,
{
type StrLen = Void;
fn len(&self) -> LEN {
LEN::from(0)
}
}
unsafe impl<LEN: Scalar, V: OdbcVersion> AttrLen<DriverDefined, LEN>
for Option<&UnsafeSQLHDESC<'_, AppDesc<'_>, V>>
where
LEN: From<SQLSMALLINT>,
{
type StrLen = Void;
fn len(&self) -> LEN {
LEN::from(crate::SQL_IS_POINTER)
}
}
unsafe impl<'a, 'conn, 'buf, AD: Def, LEN: Scalar, V: OdbcVersion> AttrLen<AD, LEN>
for Option<&'a SQLHDESC<'conn, AppDesc<'buf>, V>>
where
Option<&'a UnsafeSQLHDESC<'conn, AppDesc<'buf>, V>>: AttrLen<AD, LEN>,
LEN: From<SQLSMALLINT>,
{
type StrLen = <Option<&'a UnsafeSQLHDESC<'conn, AppDesc<'buf>, V>> as AttrLen<AD, LEN>>::StrLen;
fn len(&self) -> LEN {
unsafe { core::mem::transmute::<_, Option<&UnsafeSQLHDESC<'conn, AppDesc<'buf>, V>>>(self) }
.len()
}
}
unsafe impl<T: Scalar> StrLen<T> for T
where
T: AsMutPtr<T>,
{
fn as_mut_ptr(&mut self) -> *mut T {
<Self as AsMutPtr<T>>::as_mut_ptr(self)
}
}
unsafe impl<T: Scalar> StrLen<T> for MaybeUninit<T>
where
Self: AsMutPtr<T>,
T: StrLen<T>,
{
fn as_mut_ptr(&mut self) -> *mut T {
<Self as AsMutPtr<T>>::as_mut_ptr(self)
}
}
impl<T> AttrZeroAssert for MaybeUninit<T> {
}
impl<T> AttrZeroAssert for [T] {}
impl<T> AttrZeroAssert for OdbcStr<T> {}
impl<T: CScalar> AttrZeroAssert for UnsafeCell<T> {
}
unsafe impl StrLen<SQLLEN> for MaybeUninit<StrLenOrInd> {
fn as_mut_ptr(&mut self) -> *mut SQLLEN {
self.as_mut_ptr().cast()
}
}
unsafe impl StrLen<SQLLEN> for UnsafeCell<StrLenOrInd> {
fn as_mut_ptr(&mut self) -> *mut SQLLEN {
self.get().cast()
}
}
unsafe impl<T: Scalar> StrLen<T> for Void {
fn as_mut_ptr(&mut self) -> *mut T {
core::ptr::null_mut()
}
}
unsafe impl<T: Scalar> StrLen<T> for MaybeUninit<Void> {
fn as_mut_ptr(&mut self) -> *mut T {
core::ptr::null_mut()
}
}
impl AttrZeroAssert for SQLSMALLINT {
fn assert_zeroed(&self) {
assert_eq!(0, *self);
}
}
impl AttrZeroAssert for SQLUSMALLINT {
fn assert_zeroed(&self) {
assert_eq!(0, *self);
}
}
impl AttrZeroAssert for SQLINTEGER {
fn assert_zeroed(&self) {
assert_eq!(0, *self);
}
}
impl AttrZeroAssert for SQLUINTEGER {
fn assert_zeroed(&self) {
assert_eq!(0, *self);
}
}
impl AttrZeroAssert for SQLLEN {
fn assert_zeroed(&self) {
assert_eq!(0, *self);
}
}
impl AttrZeroAssert for SQLULEN {
fn assert_zeroed(&self) {
assert_eq!(0, *self);
}
}