1use crate::c_types::{CScalar, StrLenOrInd};
2use crate::convert::{AsMutPtr, AsMutSQLPOINTER, IntoSQLPOINTER};
3use crate::desc::AppDesc;
4use crate::env::OdbcVersion;
5use crate::handle::{RefSQLHDESC, RefUnsafeSQLHDESC, UnsafeSQLHDESC, SQLHDESC};
6use crate::str::{OdbcChar, OdbcStr};
7use crate::{
8 slice_len, Def, DriverDefined, Ident, OdbcDefined, Scalar, SQLCHAR, SQLINTEGER, SQLLEN,
9 SQLSMALLINT, SQLUINTEGER, SQLULEN, SQLUSMALLINT, SQLWCHAR,
10};
11use core::{cell::UnsafeCell, fmt::Debug, mem::MaybeUninit};
12
13pub unsafe trait Attr<A: Ident> {
14 type DefinedBy: Def;
15}
16pub unsafe trait AttrGet<A: Ident>: Attr<A> + AsMutSQLPOINTER + AttrZeroAssert {}
17pub unsafe trait AttrSet<A: Ident>: IntoSQLPOINTER + Sized {}
18
19#[derive(Debug, Clone, Copy)]
22pub enum Void {}
23
24pub unsafe trait StrLen<T: Scalar> {
26 fn as_mut_ptr(&mut self) -> *mut T;
27}
28
29pub unsafe trait AttrLen<AD: Def, LEN: Scalar> {
34 type StrLen: StrLen<LEN>;
37
38 fn len(&self) -> LEN;
39}
40
41pub trait AttrZeroAssert {
42 fn assert_zeroed(&self) {}
43}
44
45unsafe impl<A: Ident, T: Scalar> Attr<A> for MaybeUninit<T>
56where
57 T: Attr<A> + AttrGet<A>,
58{
59 type DefinedBy = T::DefinedBy;
60}
61unsafe impl<A: Ident, T> Attr<A> for [MaybeUninit<T>]
62where
63 [T]: Attr<A> + AttrGet<A>,
64{
65 type DefinedBy = <[T] as Attr<A>>::DefinedBy;
66}
67unsafe impl<A: Ident> Attr<A> for OdbcStr<MaybeUninit<SQLCHAR>>
68where
69 OdbcStr<SQLCHAR>: Attr<A> + AttrGet<A>,
70{
71 type DefinedBy = <OdbcStr<SQLCHAR> as Attr<A>>::DefinedBy;
72}
73unsafe impl<A: Ident> Attr<A> for OdbcStr<MaybeUninit<SQLWCHAR>>
74where
75 OdbcStr<SQLWCHAR>: Attr<A> + AttrGet<A>,
76{
77 type DefinedBy = <OdbcStr<SQLWCHAR> as Attr<A>>::DefinedBy;
78}
79unsafe impl<A: Ident, T> Attr<A> for &[T]
80where
81 [T]: Attr<A>,
82{
83 type DefinedBy = <[T] as Attr<A>>::DefinedBy;
84}
85unsafe impl<A: Ident, CH: OdbcChar> Attr<A> for &OdbcStr<CH>
86where
87 OdbcStr<CH>: Attr<A>,
88{
89 type DefinedBy = <OdbcStr<CH> as Attr<A>>::DefinedBy;
90}
91
92unsafe impl<A: Ident, T: Scalar> AttrGet<A> for MaybeUninit<T>
93where
94 T: AttrGet<A>,
95 Self: AsMutSQLPOINTER,
96{
97}
98unsafe impl<A: Ident> AttrGet<A> for OdbcStr<MaybeUninit<SQLCHAR>> where OdbcStr<SQLCHAR>: AttrGet<A>
99{}
100unsafe impl<A: Ident> AttrGet<A> for OdbcStr<MaybeUninit<SQLWCHAR>> where
101 OdbcStr<SQLWCHAR>: AttrGet<A>
102{
103}
104
105unsafe impl<A: Ident, T: Scalar> AttrSet<A> for MaybeUninit<T>
106where
107 Self: IntoSQLPOINTER,
108 T: AttrSet<A>,
109{
110}
111
112unsafe impl<AD: Def, T: Ident, LEN: Scalar> AttrLen<AD, LEN> for T
113where
114 MaybeUninit<T>: AttrLen<AD, LEN>,
115 LEN: From<SQLSMALLINT>,
116{
117 type StrLen = Void;
118
119 fn len(&self) -> LEN {
120 <MaybeUninit<_> as AttrLen<AD, LEN>>::len(unsafe { core::mem::transmute(self) })
122 }
123}
124unsafe impl<T: Ident, LEN: Scalar> AttrLen<OdbcDefined, LEN> for MaybeUninit<T>
125where
126 LEN: From<SQLSMALLINT>,
127{
128 type StrLen = Void;
129
130 fn len(&self) -> LEN {
131 LEN::from(0)
132 }
133}
134unsafe impl<T: Ident, LEN: Scalar> AttrLen<DriverDefined, LEN> for MaybeUninit<T>
135where
136 LEN: From<T::Type>,
137{
138 type StrLen = Void;
139
140 fn len(&self) -> LEN {
141 LEN::from(T::IDENTIFIER)
142 }
143}
144unsafe impl<AD: Def, CH: OdbcChar, LEN: Scalar> AttrLen<AD, LEN> for OdbcStr<CH>
145where
146 LEN: TryFrom<usize>,
147 LEN::Error: Debug,
148 OdbcStr<MaybeUninit<CH>>: AttrLen<AD, LEN>,
149{
150 type StrLen = <OdbcStr<MaybeUninit<CH>> as AttrLen<AD, LEN>>::StrLen;
151
152 fn len(&self) -> LEN {
153 <OdbcStr<MaybeUninit<CH>> as AttrLen<AD, LEN>>::len(unsafe { core::mem::transmute(self) })
155 }
156}
157unsafe impl<AD: Def, CH: OdbcChar, LEN: Scalar> AttrLen<AD, LEN> for OdbcStr<MaybeUninit<CH>>
158where
159 LEN: TryFrom<usize> + core::ops::Mul<Output = LEN>,
160 LEN::Error: Debug,
161{
162 type StrLen = LEN;
163
164 fn len(&self) -> LEN {
165 slice_len::<_, LEN>(self) * LEN::try_from(core::mem::size_of::<CH>()).unwrap()
167 }
168}
169unsafe impl<LEN: Scalar> AttrLen<OdbcDefined, LEN> for [MaybeUninit<SQLCHAR>]
173where
174 LEN: TryFrom<usize>,
175 LEN::Error: Debug,
176{
177 type StrLen = LEN;
178
179 fn len(&self) -> LEN {
180 slice_len(self)
181 }
182}
183unsafe impl<LEN: Scalar> AttrLen<DriverDefined, LEN> for [MaybeUninit<SQLCHAR>] {
187 type StrLen = LEN;
188
189 fn len(&self) -> LEN {
190 unimplemented!();
192 }
193}
194unsafe impl<AD: Def, LEN: Scalar> AttrLen<AD, LEN> for [SQLCHAR]
195where
196 [MaybeUninit<SQLCHAR>]: AttrLen<AD, LEN>,
197{
198 type StrLen = <[MaybeUninit<SQLCHAR>] as AttrLen<AD, LEN>>::StrLen;
199
200 fn len(&self) -> LEN {
201 <[MaybeUninit<SQLCHAR>] as AttrLen<AD, LEN>>::len(unsafe { core::mem::transmute(self) })
203 }
204}
205unsafe impl<AD: Def, T: Ident, LEN: Scalar> AttrLen<AD, LEN> for [T]
206where
207 LEN: From<SQLSMALLINT>,
208{
209 type StrLen = Void;
210
211 fn len(&self) -> LEN {
212 LEN::from(0)
213 }
214}
215unsafe impl<AD: Def, LEN: Scalar, CH: OdbcChar> AttrLen<AD, LEN> for &OdbcStr<CH>
216where
217 OdbcStr<CH>: AttrLen<AD, LEN>,
218{
219 type StrLen = <OdbcStr<CH> as AttrLen<AD, LEN>>::StrLen;
220
221 fn len(&self) -> LEN {
222 AttrLen::len(*self)
223 }
224}
225unsafe impl<AD: Def, LEN: Scalar, T> AttrLen<AD, LEN> for &[T]
226where
227 [T]: AttrLen<AD, LEN>,
228{
229 type StrLen = <[T] as AttrLen<AD, LEN>>::StrLen;
230
231 fn len(&self) -> LEN {
232 AttrLen::len(*self)
233 }
234}
235unsafe impl<AD: Def, T: CScalar> AttrLen<AD, SQLINTEGER> for UnsafeCell<T> {
237 type StrLen = Void;
238
239 fn len(&self) -> SQLINTEGER {
240 0
241 }
242}
243unsafe impl<AD: Def, T> AttrLen<AD, SQLINTEGER> for [UnsafeCell<T>] {
245 type StrLen = Void;
246
247 fn len(&self) -> SQLINTEGER {
248 0 }
250}
251unsafe impl<DT, LEN: Scalar, V: OdbcVersion> AttrLen<OdbcDefined, LEN>
252 for MaybeUninit<RefUnsafeSQLHDESC<'_, DT, V>>
253where
254 LEN: From<SQLSMALLINT>,
255{
256 type StrLen = Void;
257
258 fn len(&self) -> LEN {
259 LEN::from(0)
260 }
261}
262unsafe impl<DT, LEN: Scalar, V: OdbcVersion> AttrLen<DriverDefined, LEN>
263 for MaybeUninit<RefUnsafeSQLHDESC<'_, DT, V>>
264where
265 LEN: From<SQLSMALLINT>,
266{
267 type StrLen = Void;
268
269 fn len(&self) -> LEN {
270 LEN::from(crate::SQL_IS_POINTER)
271 }
272}
273unsafe impl<'conn, AD: Def, DT, LEN: Scalar, V: OdbcVersion> AttrLen<AD, LEN>
274 for MaybeUninit<RefSQLHDESC<'conn, DT, V>>
275where
276 MaybeUninit<RefUnsafeSQLHDESC<'conn, DT, V>>: AttrLen<AD, LEN>,
277 LEN: From<SQLSMALLINT>,
278{
279 type StrLen = <MaybeUninit<RefUnsafeSQLHDESC<'conn, DT, V>> as AttrLen<AD, LEN>>::StrLen;
280
281 fn len(&self) -> LEN {
282 unsafe { core::mem::transmute::<_, &MaybeUninit<RefUnsafeSQLHDESC<'conn, DT, V>>>(self) }
284 .len()
285 }
286}
287unsafe impl<LEN: Scalar, V: OdbcVersion> AttrLen<OdbcDefined, LEN>
288 for Option<&UnsafeSQLHDESC<'_, AppDesc<'_>, V>>
289where
290 LEN: From<SQLSMALLINT>,
291{
292 type StrLen = Void;
293
294 fn len(&self) -> LEN {
295 LEN::from(0)
296 }
297}
298unsafe impl<LEN: Scalar, V: OdbcVersion> AttrLen<DriverDefined, LEN>
299 for Option<&UnsafeSQLHDESC<'_, AppDesc<'_>, V>>
300where
301 LEN: From<SQLSMALLINT>,
302{
303 type StrLen = Void;
304
305 fn len(&self) -> LEN {
306 LEN::from(crate::SQL_IS_POINTER)
307 }
308}
309unsafe impl<'a, 'conn, 'buf, AD: Def, LEN: Scalar, V: OdbcVersion> AttrLen<AD, LEN>
310 for Option<&'a SQLHDESC<'conn, AppDesc<'buf>, V>>
311where
312 Option<&'a UnsafeSQLHDESC<'conn, AppDesc<'buf>, V>>: AttrLen<AD, LEN>,
313 LEN: From<SQLSMALLINT>,
314{
315 type StrLen = <Option<&'a UnsafeSQLHDESC<'conn, AppDesc<'buf>, V>> as AttrLen<AD, LEN>>::StrLen;
316
317 fn len(&self) -> LEN {
318 unsafe { core::mem::transmute::<_, Option<&UnsafeSQLHDESC<'conn, AppDesc<'buf>, V>>>(self) }
320 .len()
321 }
322}
323
324unsafe impl<T: Scalar> StrLen<T> for T
325where
326 T: AsMutPtr<T>,
327{
328 fn as_mut_ptr(&mut self) -> *mut T {
329 <Self as AsMutPtr<T>>::as_mut_ptr(self)
330 }
331}
332unsafe impl<T: Scalar> StrLen<T> for MaybeUninit<T>
333where
334 Self: AsMutPtr<T>,
335 T: StrLen<T>,
336{
337 fn as_mut_ptr(&mut self) -> *mut T {
338 <Self as AsMutPtr<T>>::as_mut_ptr(self)
339 }
340}
341
342impl<T> AttrZeroAssert for MaybeUninit<T> {
343 }
345impl<T> AttrZeroAssert for [T] {}
346impl<T> AttrZeroAssert for OdbcStr<T> {}
347impl<T: CScalar> AttrZeroAssert for UnsafeCell<T> {
348 }
350
351unsafe impl StrLen<SQLLEN> for MaybeUninit<StrLenOrInd> {
357 fn as_mut_ptr(&mut self) -> *mut SQLLEN {
358 self.as_mut_ptr().cast()
359 }
360}
361unsafe impl StrLen<SQLLEN> for UnsafeCell<StrLenOrInd> {
362 fn as_mut_ptr(&mut self) -> *mut SQLLEN {
363 self.get().cast()
364 }
365}
366unsafe impl<T: Scalar> StrLen<T> for Void {
367 fn as_mut_ptr(&mut self) -> *mut T {
368 core::ptr::null_mut()
370 }
371}
372unsafe impl<T: Scalar> StrLen<T> for MaybeUninit<Void> {
373 fn as_mut_ptr(&mut self) -> *mut T {
374 core::ptr::null_mut()
376 }
377}
378
379impl AttrZeroAssert for SQLSMALLINT {
380 fn assert_zeroed(&self) {
381 assert_eq!(0, *self);
383 }
384}
385impl AttrZeroAssert for SQLUSMALLINT {
386 fn assert_zeroed(&self) {
387 assert_eq!(0, *self);
389 }
390}
391impl AttrZeroAssert for SQLINTEGER {
392 fn assert_zeroed(&self) {
393 assert_eq!(0, *self);
395 }
396}
397impl AttrZeroAssert for SQLUINTEGER {
398 fn assert_zeroed(&self) {
399 assert_eq!(0, *self);
401 }
402}
403impl AttrZeroAssert for SQLLEN {
404 fn assert_zeroed(&self) {
405 assert_eq!(0, *self);
407 }
408}
409impl AttrZeroAssert for SQLULEN {
410 fn assert_zeroed(&self) {
411 assert_eq!(0, *self);
413 }
414}