mssql_value_serializer/literals/
mod.rs

1#[cfg(feature = "bigdecimal")]
2mod bigdecimal;
3#[cfg(feature = "chrono")]
4mod chrono;
5#[cfg(feature = "num-bigint")]
6mod num_bigint;
7#[cfg(feature = "rust_decimal")]
8mod rust_decimal;
9#[cfg(feature = "time")]
10mod time;
11#[cfg(feature = "uuid")]
12mod uuid;
13
14use std::{
15    fmt::{self, Formatter, Write},
16    rc::Rc,
17    sync::Arc,
18};
19
20use crate::{
21    impl_dyn_wrapper, impl_dyn_wrapper_slice, SqlLiteralError, SqlServerLiteral,
22    SqlServerLiteralDynWrapper,
23};
24
25// ----- Booleans -----
26
27impl SqlServerLiteral for bool {
28    #[inline]
29    fn append_sql_literal(&self, out: &mut String) -> Result<(), SqlLiteralError> {
30        out.push(if *self { '1' } else { '0' });
31
32        Ok(())
33    }
34
35    #[inline]
36    fn append_sql_literal_fmt(&self, out: &mut Formatter<'_>) -> Result<(), SqlLiteralError> {
37        out.write_char(if *self { '1' } else { '0' }).unwrap();
38
39        Ok(())
40    }
41}
42
43impl_dyn_wrapper!(bool);
44
45// ----- Numbers -----
46
47macro_rules! impl_int {
48    ($($t:ty),* $(,)*) => {
49        $(
50            impl SqlServerLiteral for $t {
51                #[inline]
52                fn append_sql_literal(&self, out: &mut String) -> Result<(), SqlLiteralError> {
53                    write!(out, "{}", *self).unwrap();
54
55                    Ok(())
56                }
57
58                #[inline]
59                fn append_sql_literal_fmt(&self, out: &mut Formatter<'_>) -> Result<(), SqlLiteralError> {
60                    write!(out, "{}", *self).unwrap();
61
62                    Ok(())
63                }
64            }
65
66            impl_dyn_wrapper!($t);
67        )*
68    }
69}
70impl_int!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize);
71
72macro_rules! impl_float {
73    ($($t:ty),* $(,)?) => {
74        $(
75            impl SqlServerLiteral for $t {
76                #[inline]
77                fn append_sql_literal(&self, out: &mut String) -> Result<(), SqlLiteralError> {
78                    if !self.is_finite() {
79                        return Err(SqlLiteralError::FloatNotFinite);
80                    }
81
82                    write!(out, "{}", *self).unwrap();
83
84                    Ok(())
85                }
86
87                #[inline]
88                fn append_sql_literal_fmt(&self, out: &mut Formatter<'_>) -> Result<(), SqlLiteralError> {
89                    if !self.is_finite() {
90                        return Err(SqlLiteralError::FloatNotFinite);
91                    }
92
93                    write!(out, "{}", *self).unwrap();
94
95                    Ok(())
96                }
97            }
98
99            impl_dyn_wrapper!($t);
100        )*
101    }
102}
103impl_float!(f32, f64);
104
105// ----- Strings -----
106
107pub(crate) fn push_string_literal_char(ch: &char, out: &mut impl Write) -> fmt::Result {
108    out.write_char('\'')?;
109
110    if *ch == '\'' {
111        out.write_char('\'')?;
112    }
113
114    out.write_char(*ch)?;
115
116    out.write_char('\'')?;
117
118    Ok(())
119}
120
121fn push_nstring_literal_char(ch: &char, out: &mut impl Write) -> fmt::Result {
122    out.write_str("N'")?;
123
124    if *ch == '\'' {
125        out.write_char('\'')?;
126    }
127
128    out.write_char(*ch)?;
129
130    out.write_char('\'')?;
131
132    Ok(())
133}
134
135impl SqlServerLiteral for char {
136    #[inline]
137    fn append_sql_literal(&self, out: &mut String) -> Result<(), SqlLiteralError> {
138        push_nstring_literal_char(self, out).unwrap();
139
140        Ok(())
141    }
142
143    #[inline]
144    fn append_sql_literal_fmt(&self, out: &mut Formatter<'_>) -> Result<(), SqlLiteralError> {
145        push_nstring_literal_char(self, out).unwrap();
146
147        Ok(())
148    }
149}
150
151impl_dyn_wrapper!(char);
152
153pub(crate) fn push_string_literal(s: &str, out: &mut impl Write) -> fmt::Result {
154    out.write_char('\'')?;
155
156    for ch in s.chars() {
157        if ch == '\'' {
158            out.write_char('\'')?;
159        }
160
161        out.write_char(ch)?;
162    }
163
164    out.write_char('\'')?;
165
166    Ok(())
167}
168
169fn push_nstring_literal(s: &str, out: &mut impl Write) -> fmt::Result {
170    out.write_str("N'")?;
171
172    for ch in s.chars() {
173        if ch == '\'' {
174            out.write_char('\'')?;
175        }
176
177        out.write_char(ch)?;
178    }
179
180    out.write_char('\'')?;
181
182    Ok(())
183}
184
185macro_rules! impl_string {
186    ($($t:ty),* $(,)*) => {
187        $(
188            impl SqlServerLiteral for $t {
189                #[inline]
190                fn append_sql_literal(&self, out: &mut String) -> Result<(), SqlLiteralError> {
191                    push_nstring_literal(self, out).unwrap();
192
193                    Ok(())
194                }
195
196                #[inline]
197                fn append_sql_literal_fmt(&self, out: &mut Formatter<'_>) -> Result<(), SqlLiteralError> {
198                    push_nstring_literal(self, out).unwrap();
199
200                    Ok(())
201                }
202            }
203        )*
204    };
205}
206impl_string!(str, &str, String, Rc<String>, Arc<String>);
207impl_dyn_wrapper_slice!(str);
208impl_dyn_wrapper!(String, Rc<String>, Arc<String>);
209
210// ----- Blob -----
211
212fn push_hex_bytes(bytes: &[u8], out: &mut impl Write) -> fmt::Result {
213    if bytes.is_empty() {
214        return Err(fmt::Error);
215    }
216
217    out.write_str("0x")?;
218
219    for b in bytes {
220        write!(out, "{:02X}", b)?;
221    }
222
223    Ok(())
224}
225
226fn push_hex_bytes_to_string(bytes: &[u8], out: &mut String) -> fmt::Result {
227    if bytes.is_empty() {
228        return Err(fmt::Error);
229    }
230
231    out.push_str("0x");
232
233    let len = out.len();
234    let hex_len = bytes.len() * 2;
235
236    out.reserve(hex_len);
237
238    unsafe {
239        let v = out.as_mut_vec();
240
241        v.set_len(len + hex_len);
242
243        const_hex::encode_to_slice_upper(bytes, &mut v[len..]).unwrap(); // should not panic because we have calculated the length
244    }
245
246    Ok(())
247}
248
249macro_rules! impl_u8_array {
250    ($($t:ty),* $(,)*) => {
251        $(
252            impl SqlServerLiteral for $t {
253                #[inline]
254                fn append_sql_literal(&self, out: &mut String) -> Result<(), SqlLiteralError> {
255                    push_hex_bytes_to_string(self, out).unwrap();
256
257                    Ok(())
258                }
259
260                #[inline]
261                fn append_sql_literal_fmt(&self, out: &mut Formatter<'_>) -> Result<(), SqlLiteralError> {
262                    push_hex_bytes(self, out).unwrap();
263
264                    Ok(())
265                }
266            }
267        )*
268    };
269}
270impl_u8_array!([u8], &[u8], Vec<u8>);
271impl_dyn_wrapper_slice!([u8]);
272impl_dyn_wrapper!(Vec<u8>);
273
274// ----- NULL -----
275
276impl<T: SqlServerLiteral> SqlServerLiteral for Option<T> {
277    #[inline]
278    fn append_sql_literal(&self, out: &mut String) -> Result<(), SqlLiteralError> {
279        match self {
280            Some(v) => v.append_sql_literal(out),
281            None => {
282                out.push_str("NULL");
283
284                Ok(())
285            },
286        }
287    }
288
289    #[inline]
290    fn append_sql_literal_fmt(&self, out: &mut Formatter<'_>) -> Result<(), SqlLiteralError> {
291        match self {
292            Some(v) => v.append_sql_literal_fmt(out),
293            None => {
294                out.write_str("NULL").unwrap();
295
296                Ok(())
297            },
298        }
299    }
300}
301
302impl<T: SqlServerLiteral + 'static> From<Option<T>> for SqlServerLiteralDynWrapper<'_> {
303    #[inline]
304    fn from(value: Option<T>) -> Self {
305        Self::Owned(Box::new(value))
306    }
307}
308
309impl<'a, T: ?Sized> From<&'a Option<&'a T>> for SqlServerLiteralDynWrapper<'a>
310where
311    &'a T: SqlServerLiteral,
312{
313    #[inline]
314    fn from(value: &'a Option<&'a T>) -> Self {
315        Self::Borrowed(value)
316    }
317}