mssql_value_serializer/
wrappers.rs

1use std::{
2    borrow::Cow,
3    fmt::{self, Debug, Display, Formatter},
4    marker::PhantomData,
5    ops::Deref,
6};
7
8use crate::{SqlLiteralError, SqlServerLiteral, SqlServerLiteralForValueList};
9
10/// A wrapper type for any value implementing [`SqlServerLiteral`].
11///
12/// This type allows you to easily convert a value into one that implements both [`Display`] and [`serde::Serialize`], enabling SQL Server literal behavior.
13///
14/// # Examples
15///
16/// ```rust
17/// use mssql_value_serializer::SqlServerLiteralWrapper;
18///
19/// let needle = "Some text";
20///
21/// let mut sql = format!(
22///     "
23///         SELECT
24///             *
25///         FROM
26///             [TABLE]
27///         WHERE
28///             name = {value}
29///     ",
30///     value = SqlServerLiteralWrapper::new(needle)
31/// );
32///
33/// assert_eq!(
34///     "
35///         SELECT
36///             *
37///         FROM
38///             [TABLE]
39///         WHERE
40///             name = N'Some text'
41///     ",
42///     sql
43/// );
44/// ```
45#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
46pub struct SqlServerLiteralWrapper<T: SqlServerLiteral>(T);
47
48impl<T: SqlServerLiteral> SqlServerLiteralWrapper<T> {
49    #[inline]
50    pub const fn new(value: T) -> Self {
51        Self(value)
52    }
53
54    /// Consumes the wrapper and returns the inner value.
55    #[inline]
56    pub fn into_inner(self) -> T {
57        self.0
58    }
59}
60
61impl<T: SqlServerLiteral> Display for SqlServerLiteralWrapper<T> {
62    /// Formats the wrapped value as a SQL Server literal.
63    #[inline]
64    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
65        self.0.append_sql_literal_fmt(f).map_err(|_| fmt::Error)
66    }
67}
68
69impl<T: SqlServerLiteral> From<T> for SqlServerLiteralWrapper<T> {
70    #[inline]
71    fn from(value: T) -> Self {
72        Self::new(value)
73    }
74}
75
76impl<T: SqlServerLiteral> Deref for SqlServerLiteralWrapper<T> {
77    type Target = T;
78
79    #[inline]
80    fn deref(&self) -> &Self::Target {
81        &self.0
82    }
83}
84
85impl<T: SqlServerLiteral> SqlServerLiteral for SqlServerLiteralWrapper<T> {
86    #[inline]
87    fn append_sql_literal(&self, out: &mut String) -> Result<(), SqlLiteralError> {
88        self.0.append_sql_literal(out)
89    }
90
91    #[inline]
92    fn append_sql_literal_fmt(&self, out: &mut Formatter<'_>) -> Result<(), SqlLiteralError> {
93        self.0.append_sql_literal_fmt(out)
94    }
95}
96
97#[cfg(feature = "serde")]
98impl<T: SqlServerLiteral> serde::Serialize for SqlServerLiteralWrapper<T> {
99    #[inline]
100    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
101    where
102        S: serde::Serializer, {
103        let mut s = String::new();
104
105        self.0
106            .append_sql_literal(&mut s)
107            .map_err(|error| serde::ser::Error::custom(error.to_string()))?;
108
109        serializer.serialize_str(s.as_str())
110    }
111}
112
113/// A wrapper type that can hold either a borrowed or owned [`dyn SqlServerLiteral`] value.
114///
115/// This type allows generic code to handle both borrowed and owned SQL literal trait objects uniformly. It is primarily used when dynamically storing or formatting SQL literal values, without having to commit to a single ownership model.
116///
117/// # Examples
118///
119/// ```rust
120/// use mssql_value_serializer::{
121///     SqlServerLiteralDynWrapper, SqlServerLiteralForValueListWrapper,
122/// };
123///
124/// let s = String::from("Some text");
125///
126/// let mut values: Vec<SqlServerLiteralDynWrapper<'_>> = vec![
127///     SqlServerLiteralDynWrapper::from(1u8),
128///     SqlServerLiteralDynWrapper::from(2i8),
129///     SqlServerLiteralDynWrapper::from(&s),
130/// ];
131///
132/// let mut sql = format!(
133///     "
134///         SELECT
135///             *
136///         FROM
137///             [TABLE]
138///         WHERE
139///             name IN ({value})
140///     ",
141///     value = SqlServerLiteralForValueListWrapper::new(values)
142/// );
143///
144/// assert_eq!(
145///     "
146///         SELECT
147///             *
148///         FROM
149///             [TABLE]
150///         WHERE
151///             name IN (1, 2, N'Some text')
152///     ",
153///     sql
154/// );
155/// ```
156pub enum SqlServerLiteralDynWrapper<'a> {
157    Borrowed(&'a dyn SqlServerLiteral),
158    Owned(Box<dyn SqlServerLiteral>),
159}
160
161impl Debug for SqlServerLiteralDynWrapper<'_> {
162    /// Formats the wrapped value as a SQL Server literal.
163    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
164        struct SqlServerLiteralDynWrapperDebugFormatter<'a, T: SqlServerLiteral + ?Sized>(&'a T);
165
166        impl<'a, T: SqlServerLiteral + ?Sized> Debug for SqlServerLiteralDynWrapperDebugFormatter<'a, T> {
167            #[inline]
168            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
169                self.0.append_sql_literal_fmt(f).map_err(|_| fmt::Error)
170            }
171        }
172
173        let (name, r) = match self {
174            Self::Borrowed(v) => ("Borrowed", *v),
175            Self::Owned(v) => ("Owned", v.as_ref()),
176        };
177
178        let mut debug = f.debug_tuple(name);
179
180        debug.field(&SqlServerLiteralDynWrapperDebugFormatter(r));
181
182        debug.finish()
183    }
184}
185
186impl Display for SqlServerLiteralDynWrapper<'_> {
187    /// Formats the wrapped value as a SQL Server literal.
188    #[inline]
189    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
190        match self {
191            Self::Borrowed(v) => v.append_sql_literal_fmt(f).map_err(|_| fmt::Error),
192            Self::Owned(v) => v.append_sql_literal_fmt(f).map_err(|_| fmt::Error),
193        }
194    }
195}
196
197impl From<Box<dyn SqlServerLiteral>> for SqlServerLiteralDynWrapper<'_> {
198    #[inline]
199    fn from(value: Box<dyn SqlServerLiteral>) -> Self {
200        Self::Owned(value)
201    }
202}
203
204impl<'a> From<&'a dyn SqlServerLiteral> for SqlServerLiteralDynWrapper<'a> {
205    #[inline]
206    fn from(value: &'a dyn SqlServerLiteral) -> Self {
207        Self::Borrowed(value)
208    }
209}
210
211impl<'a, T: ?Sized + ToOwned + SqlServerLiteral> From<&'a Cow<'a, T>>
212    for SqlServerLiteralDynWrapper<'a>
213where
214    T::Owned: SqlServerLiteral,
215    &'a T: SqlServerLiteral,
216{
217    #[inline]
218    fn from(value: &'a Cow<'a, T>) -> Self {
219        match value {
220            Cow::Owned(v) => Self::Borrowed(v),
221            Cow::Borrowed(v) => Self::Borrowed(v),
222        }
223    }
224}
225
226macro_rules! impl_dyn_wrapper {
227    ($ty:ty) => {
228        impl From<$ty> for $crate::SqlServerLiteralDynWrapper<'_> {
229            #[inline]
230            fn from(value: $ty) -> Self {
231                Self::Owned(Box::new(value))
232            }
233        }
234
235        impl<'a> From<&'a $ty> for $crate::SqlServerLiteralDynWrapper<'a> {
236            #[inline]
237            fn from(value: &'a $ty) -> Self {
238                Self::Borrowed(value)
239            }
240        }
241
242        impl<'a> From<::std::borrow::Cow<'a, $ty>> for $crate::SqlServerLiteralDynWrapper<'a> {
243            #[inline]
244            fn from(value: ::std::borrow::Cow<'a, $ty>) -> Self {
245                match value {
246                    ::std::borrow::Cow::Owned(v) => Self::Owned(Box::new(v)),
247                    ::std::borrow::Cow::Borrowed(v) => Self::Borrowed(v),
248                }
249            }
250        }
251    };
252    ($($ty:ty),+ $(,)*) => {
253        $(
254            $crate::impl_dyn_wrapper!($ty);
255        )+
256    };
257}
258
259macro_rules! impl_dyn_wrapper_slice {
260    ($ty:ty) => {
261        impl<'a> From<&'static $ty> for $crate::SqlServerLiteralDynWrapper<'a> {
262            #[inline]
263            fn from(value: &'static $ty) -> Self {
264                Self::Owned(Box::new(value))
265            }
266        }
267
268        impl<'a> From<&'a &'a $ty> for $crate::SqlServerLiteralDynWrapper<'a> {
269            #[inline]
270            fn from(value: &'a &'a $ty) -> Self {
271                Self::Borrowed(value)
272            }
273        }
274
275        impl<'a> From<::std::borrow::Cow<'a, $ty>> for $crate::SqlServerLiteralDynWrapper<'a> {
276            #[inline]
277            fn from(value: ::std::borrow::Cow<'a, $ty>) -> Self {
278                // match value {
279                //     Cow::Owned(v) => Self::Owned(Box::new(v)),
280                //     Cow::Borrowed(v) => Self::Borrowed(v as &'a dyn SqlServerLiteral), // We can't use trait object like this. I don't know why.
281                // }
282
283                let value = value.into_owned();
284
285                Self::Owned(Box::new(value))
286            }
287        }
288    };
289    ($($ty:ty),+ $(,)*) => {
290        $(
291            $crate::impl_dyn_wrapper_slice!($ty);
292        )+
293    };
294}
295
296pub(crate) use impl_dyn_wrapper;
297pub(crate) use impl_dyn_wrapper_slice;
298
299impl<'a> Deref for SqlServerLiteralDynWrapper<'a> {
300    type Target = dyn SqlServerLiteral + 'a;
301
302    #[inline]
303    fn deref(&self) -> &Self::Target {
304        match self {
305            Self::Owned(v) => v.as_ref(),
306            Self::Borrowed(v) => *v,
307        }
308    }
309}
310
311impl<'a> SqlServerLiteral for SqlServerLiteralDynWrapper<'a> {
312    #[inline]
313    fn append_sql_literal(&self, out: &mut String) -> Result<(), SqlLiteralError> {
314        self.deref().append_sql_literal(out)
315    }
316
317    #[inline]
318    fn append_sql_literal_fmt(&self, out: &mut Formatter<'_>) -> Result<(), SqlLiteralError> {
319        self.deref().append_sql_literal_fmt(out)
320    }
321}
322
323#[cfg(feature = "serde")]
324impl<'a> serde::Serialize for SqlServerLiteralDynWrapper<'a> {
325    #[inline]
326    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
327    where
328        S: serde::Serializer, {
329        let mut s = String::new();
330
331        self.deref()
332            .append_sql_literal(&mut s)
333            .map_err(|error| serde::ser::Error::custom(error.to_string()))?;
334
335        serializer.serialize_str(s.as_str())
336    }
337}
338
339struct SqlServerLiteralForValueListWrapperDebugFormatter<
340    'a,
341    T: SqlServerLiteralForValueList + ?Sized,
342>(&'a T);
343
344impl<'a, T: SqlServerLiteralForValueList + ?Sized> Debug
345    for SqlServerLiteralForValueListWrapperDebugFormatter<'a, T>
346{
347    #[inline]
348    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
349        self.0.append_sql_literal_for_value_list_fmt(f).map_err(|_| fmt::Error)
350    }
351}
352
353/// A wrapper type for any value implementing [`SqlServerLiteralForValueList`].
354///
355/// This type allows you to easily convert a value into one that implements both [`Display`] and [`serde::Serialize`], enabling it to exhibit SQL Server literal value list behavior.
356///
357/// # Examples
358///
359/// ```rust
360/// use mssql_value_serializer::{SqlServerLiteral, SqlServerLiteralForValueListWrapper};
361///
362/// let needles: &[&str] = &["Some text", "Foo", "Bar"];
363///
364/// let mut sql = format!(
365///     "
366///         SELECT
367///             *
368///         FROM
369///             [TABLE]
370///         WHERE
371///             name IN ({value})
372///     ",
373///     value = SqlServerLiteralForValueListWrapper::new(needles)
374/// );
375///
376/// assert_eq!(
377///     "
378///         SELECT
379///             *
380///         FROM
381///             [TABLE]
382///         WHERE
383///             name IN (N'Some text', N'Foo', N'Bar')
384///     ",
385///     sql
386/// );
387pub struct SqlServerLiteralForValueListWrapper<T: SqlServerLiteralForValueList>(T);
388
389impl<T: SqlServerLiteralForValueList> SqlServerLiteralForValueListWrapper<T> {
390    #[inline]
391    pub const fn new(value: T) -> Self {
392        Self(value)
393    }
394
395    /// Consumes the wrapper and returns the inner value.
396    #[inline]
397    pub fn into_inner(self) -> T {
398        self.0
399    }
400}
401
402impl<T: SqlServerLiteralForValueList> Debug for SqlServerLiteralForValueListWrapper<T> {
403    #[inline]
404    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
405        let mut debug = f.debug_tuple("SqlServerLiteralForValueListWrapper");
406
407        debug.field(&SqlServerLiteralForValueListWrapperDebugFormatter(self));
408
409        debug.finish()
410    }
411}
412
413impl<T: SqlServerLiteralForValueList> Display for SqlServerLiteralForValueListWrapper<T> {
414    /// Formats the wrapped value as a SQL Server literal.
415    #[inline]
416    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
417        self.0.append_sql_literal_for_value_list_fmt(f).map_err(|_| fmt::Error)
418    }
419}
420
421impl<T: SqlServerLiteralForValueList> From<T> for SqlServerLiteralForValueListWrapper<T> {
422    #[inline]
423    fn from(value: T) -> Self {
424        Self::new(value)
425    }
426}
427
428impl<T: SqlServerLiteralForValueList> Deref for SqlServerLiteralForValueListWrapper<T> {
429    type Target = T;
430
431    #[inline]
432    fn deref(&self) -> &Self::Target {
433        &self.0
434    }
435}
436
437impl<T: SqlServerLiteralForValueList> SqlServerLiteralForValueList
438    for SqlServerLiteralForValueListWrapper<T>
439{
440    #[inline]
441    fn append_sql_literal_for_value_list(&self, out: &mut String) -> Result<(), SqlLiteralError> {
442        self.0.append_sql_literal_for_value_list(out)
443    }
444
445    #[inline]
446    fn append_sql_literal_for_value_list_fmt(
447        &self,
448        out: &mut Formatter<'_>,
449    ) -> Result<(), SqlLiteralError> {
450        self.0.append_sql_literal_for_value_list_fmt(out)
451    }
452}
453
454#[cfg(feature = "serde")]
455impl<T: SqlServerLiteralForValueList> serde::Serialize for SqlServerLiteralForValueListWrapper<T> {
456    #[inline]
457    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
458    where
459        S: serde::Serializer, {
460        let mut s = String::new();
461
462        self.0
463            .append_sql_literal_for_value_list(&mut s)
464            .map_err(|error| serde::ser::Error::custom(error.to_string()))?;
465
466        serializer.serialize_str(s.as_str())
467    }
468}
469
470/// A wrapper type for string values.
471///
472/// This type allows you to easily convert a value into one that implements both [`Display`] and [`serde::Serialize`], enabling SQL Server literal formatting for character strings (CHAR/VARCHAR) rather than Unicode character strings (NCHAR/NVARCHAR).
473///
474/// # Examples
475///
476/// ```rust
477/// use mssql_value_serializer::SqlServerCharWrapper;
478///
479/// let needle = "Some text";
480///
481/// let mut sql = format!(
482///     "
483///         SELECT
484///             *
485///         FROM
486///             [TABLE]
487///         WHERE
488///             name = {value}
489///     ",
490///     value = SqlServerCharWrapper::new(needle)
491/// );
492///
493/// assert_eq!(
494///     "
495///         SELECT
496///             *
497///         FROM
498///             [TABLE]
499///         WHERE
500///             name = 'Some text'
501///     ",
502///     sql
503/// );
504/// ```
505#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
506pub struct SqlServerCharWrapper<'a, T>(T, PhantomData<&'a ()>);
507
508impl<'a, T> SqlServerCharWrapper<'a, T> {
509    #[inline]
510    pub const fn new(value: T) -> Self {
511        Self(value, PhantomData)
512    }
513
514    /// Consumes the wrapper and returns the inner value.
515    #[inline]
516    pub fn into_inner(self) -> T {
517        self.0
518    }
519}
520
521impl<'a, T> Display for SqlServerCharWrapper<'a, T>
522where
523    SqlServerCharWrapper<'a, T>: SqlServerLiteral,
524{
525    /// Formats the wrapped value as a SQL Server character string literal.
526    #[inline]
527    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
528        self.append_sql_literal_fmt(f).map_err(|_| fmt::Error)
529    }
530}
531
532#[cfg(feature = "serde")]
533impl<'a, T> serde::Serialize for SqlServerCharWrapper<'a, T>
534where
535    SqlServerCharWrapper<'a, T>: SqlServerLiteral,
536{
537    #[inline]
538    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
539    where
540        S: serde::Serializer, {
541        let mut s = String::new();
542
543        self.append_sql_literal(&mut s)
544            .map_err(|error| serde::ser::Error::custom(error.to_string()))?;
545
546        serializer.serialize_str(s.as_str())
547    }
548}
549
550impl From<char> for SqlServerCharWrapper<'_, char> {
551    #[inline]
552    fn from(value: char) -> Self {
553        Self::new(value)
554    }
555}
556
557impl Deref for SqlServerCharWrapper<'_, char> {
558    type Target = char;
559
560    #[inline]
561    fn deref(&self) -> &Self::Target {
562        &self.0
563    }
564}
565
566impl SqlServerLiteral for SqlServerCharWrapper<'_, char> {
567    #[inline]
568    fn append_sql_literal(&self, out: &mut String) -> Result<(), SqlLiteralError> {
569        crate::push_string_literal_char(&self.0, out).unwrap();
570
571        Ok(())
572    }
573
574    #[inline]
575    fn append_sql_literal_fmt(&self, out: &mut Formatter<'_>) -> Result<(), SqlLiteralError> {
576        crate::push_string_literal_char(&self.0, out).unwrap();
577
578        Ok(())
579    }
580}
581
582macro_rules! impl_char_wrapper {
583    ($($ty:ty),+ $(,)*) => {
584        $(
585            impl<'a> From<$ty> for SqlServerCharWrapper<'a, $ty> {
586                #[inline]
587                fn from(value: $ty) -> Self {
588                    Self::new(value)
589                }
590            }
591
592            impl<'a> Deref for SqlServerCharWrapper<'a, $ty> {
593                type Target = str;
594
595                #[inline]
596                fn deref(&self) -> &Self::Target {
597                    &self.0
598                }
599            }
600
601            impl<'a> SqlServerLiteral for SqlServerCharWrapper<'a, $ty> {
602                #[inline]
603                fn append_sql_literal(&self, out: &mut String) -> Result<(), SqlLiteralError> {
604                    $crate::push_string_literal(&self.0, out).unwrap();
605
606                    Ok(())
607                }
608
609                #[inline]
610                fn append_sql_literal_fmt(&self, out: &mut Formatter<'_>) -> Result<(), SqlLiteralError> {
611                    $crate::push_string_literal(&self.0, out).unwrap();
612
613                    Ok(())
614                }
615            }
616        )+
617    };
618}
619impl_char_wrapper!(&'a str, String, Cow<'a, str>);