rs_odbc/
str.rs

1use core::{
2    cell::UnsafeCell,
3    mem::MaybeUninit,
4    ops::{Deref, DerefMut},
5};
6
7use crate::{
8    env::OdbcVersion,
9    handle::{RefSQLHDESC, RefUnsafeSQLHDESC, UnsafeSQLHDESC, SQLHDESC},
10    Ident, SQLCHAR, SQLWCHAR,
11};
12
13pub trait OdbcChar {}
14
15#[repr(transparent)]
16#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
17pub struct OdbcStr<T>([T]);
18
19pub trait Ansi {}
20pub trait Unicode {}
21
22impl OdbcChar for SQLCHAR {}
23impl OdbcChar for SQLWCHAR {}
24
25impl<T> Deref for OdbcStr<T> {
26    type Target = [T];
27
28    fn deref(&self) -> &Self::Target {
29        &self.0
30    }
31}
32impl<T> DerefMut for OdbcStr<T> {
33    fn deref_mut(&mut self) -> &mut Self::Target {
34        &mut self.0
35    }
36}
37impl AsRef<OdbcStr<SQLCHAR>> for str {
38    fn as_ref(&self) -> &OdbcStr<SQLCHAR> {
39        self.as_bytes().as_ref()
40    }
41}
42impl AsMut<OdbcStr<SQLCHAR>> for str {
43    fn as_mut(&mut self) -> &mut OdbcStr<SQLCHAR> {
44        unsafe { self.as_bytes_mut().as_mut() }
45    }
46}
47impl AsRef<OdbcStr<SQLCHAR>> for [SQLCHAR] {
48    fn as_ref(&self) -> &OdbcStr<SQLCHAR> {
49        unsafe { &*(self as *const [SQLCHAR] as *const OdbcStr<SQLCHAR>) }
50    }
51}
52impl AsMut<OdbcStr<SQLCHAR>> for [SQLCHAR] {
53    fn as_mut(&mut self) -> &mut OdbcStr<SQLCHAR> {
54        unsafe { &mut *(self as *mut [SQLCHAR] as *mut OdbcStr<SQLCHAR>) }
55    }
56}
57impl AsRef<OdbcStr<SQLWCHAR>> for [SQLWCHAR] {
58    fn as_ref(&self) -> &OdbcStr<SQLWCHAR> {
59        unsafe { &*(self as *const [SQLWCHAR] as *const OdbcStr<SQLWCHAR>) }
60    }
61}
62impl AsMut<OdbcStr<SQLWCHAR>> for [SQLWCHAR] {
63    fn as_mut(&mut self) -> &mut OdbcStr<SQLWCHAR> {
64        unsafe { &mut *(self as *mut [SQLWCHAR] as *mut OdbcStr<SQLWCHAR>) }
65    }
66}
67impl AsRef<OdbcStr<UnsafeCell<SQLCHAR>>> for UnsafeCell<str> {
68    fn as_ref(&self) -> &OdbcStr<UnsafeCell<SQLCHAR>> {
69        // FIXME: Relies on the implicit assumption that str is transmutable into [u8]
70        // SAFETY: Types are transparent
71        unsafe { core::mem::transmute(self) }
72    }
73}
74impl AsRef<OdbcStr<UnsafeCell<SQLCHAR>>> for UnsafeCell<[SQLCHAR]> {
75    fn as_ref(&self) -> &OdbcStr<UnsafeCell<SQLCHAR>> {
76        // SAFETY: Types are transparent
77        unsafe { core::mem::transmute(self) }
78    }
79}
80impl AsRef<OdbcStr<UnsafeCell<SQLWCHAR>>> for UnsafeCell<[SQLWCHAR]> {
81    fn as_ref(&self) -> &OdbcStr<UnsafeCell<SQLWCHAR>> {
82        // SAFETY: Types are transparent
83        unsafe { core::mem::transmute(self) }
84    }
85}
86impl AsMut<OdbcStr<MaybeUninit<SQLCHAR>>> for [MaybeUninit<SQLCHAR>]
87where
88    [SQLCHAR]: AsMut<OdbcStr<SQLCHAR>>,
89{
90    fn as_mut(&mut self) -> &mut OdbcStr<MaybeUninit<SQLCHAR>> {
91        unsafe { &mut *(self as *mut [MaybeUninit<SQLCHAR>] as *mut OdbcStr<MaybeUninit<SQLCHAR>>) }
92    }
93}
94impl AsMut<OdbcStr<MaybeUninit<SQLWCHAR>>> for [MaybeUninit<SQLWCHAR>]
95where
96    [SQLWCHAR]: AsMut<OdbcStr<SQLWCHAR>>,
97{
98    fn as_mut(&mut self) -> &mut OdbcStr<MaybeUninit<SQLWCHAR>> {
99        unsafe {
100            &mut *(self as *mut [MaybeUninit<SQLWCHAR>] as *mut OdbcStr<MaybeUninit<SQLWCHAR>>)
101        }
102    }
103}
104
105impl<T: Ident> Ansi for T {} // TODO: This coincidentally implements it for SQLWCHAR as well. May not be a problem?
106impl<T: Ident> Unicode for T {} // TODO: This coincidentally implements it for SQLWCHAR as well. May not be a problem?
107
108impl<T: Ident> Ansi for MaybeUninit<T> where T: Ansi {}
109impl<T: Ident> Unicode for MaybeUninit<T> where T: Unicode {}
110
111impl Ansi for OdbcStr<SQLCHAR> {}
112impl Unicode for OdbcStr<SQLWCHAR> {}
113
114impl Ansi for OdbcStr<MaybeUninit<SQLCHAR>> {}
115impl Unicode for OdbcStr<MaybeUninit<SQLWCHAR>> {}
116
117impl<CH: OdbcChar> Ansi for &OdbcStr<CH> where OdbcStr<CH>: Ansi {}
118impl<CH: OdbcChar> Unicode for &OdbcStr<CH> where OdbcStr<CH>: Unicode {}
119
120impl<DT, V: OdbcVersion> Ansi for MaybeUninit<RefSQLHDESC<'_, DT, V>> {}
121impl<DT, V: OdbcVersion> Unicode for MaybeUninit<RefSQLHDESC<'_, DT, V>> {}
122
123impl<DT, V: OdbcVersion> Ansi for MaybeUninit<RefUnsafeSQLHDESC<'_, DT, V>> {}
124impl<DT, V: OdbcVersion> Unicode for MaybeUninit<RefUnsafeSQLHDESC<'_, DT, V>> {}
125
126impl<DT, V: OdbcVersion> Ansi for Option<&SQLHDESC<'_, DT, V>> {}
127impl<DT, V: OdbcVersion> Unicode for Option<&SQLHDESC<'_, DT, V>> {}
128
129impl<DT, V: OdbcVersion> Ansi for Option<&UnsafeSQLHDESC<'_, DT, V>> {}
130impl<DT, V: OdbcVersion> Unicode for Option<&UnsafeSQLHDESC<'_, DT, V>> {}