sqlx_core_oldapi/
encode.rs

1//! Provides [`Encode`] for encoding values for the database.
2
3use std::mem;
4
5use crate::database::{Database, HasArguments};
6
7/// The return type of [Encode::encode].
8pub enum IsNull {
9    /// The value is null; no data was written.
10    Yes,
11
12    /// The value is not null.
13    ///
14    /// This does not mean that data was written.
15    No,
16}
17
18/// Encode a single value to be sent to the database.
19pub trait Encode<'q, DB: Database> {
20    /// Writes the value of `self` into `buf` in the expected format for the database.
21    #[must_use]
22    fn encode(self, buf: &mut <DB as HasArguments<'q>>::ArgumentBuffer) -> IsNull
23    where
24        Self: Sized,
25    {
26        self.encode_by_ref(buf)
27    }
28
29    /// Writes the value of `self` into `buf` without moving `self`.
30    ///
31    /// Where possible, make use of `encode` instead as it can take advantage of re-using
32    /// memory.
33    #[must_use]
34    fn encode_by_ref(&self, buf: &mut <DB as HasArguments<'q>>::ArgumentBuffer) -> IsNull;
35
36    fn produces(&self) -> Option<DB::TypeInfo> {
37        // `produces` is inherently a hook to allow database drivers to produce value-dependent
38        // type information; if the driver doesn't need this, it can leave this as `None`
39        None
40    }
41
42    #[inline]
43    fn size_hint(&self) -> usize {
44        mem::size_of_val(self)
45    }
46}
47
48impl<'q, T, DB: Database> Encode<'q, DB> for &'_ T
49where
50    T: Encode<'q, DB>,
51{
52    #[inline]
53    fn encode(self, buf: &mut <DB as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
54        <T as Encode<DB>>::encode_by_ref(self, buf)
55    }
56
57    #[inline]
58    fn encode_by_ref(&self, buf: &mut <DB as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
59        <&T as Encode<DB>>::encode(self, buf)
60    }
61
62    #[inline]
63    fn produces(&self) -> Option<DB::TypeInfo> {
64        (**self).produces()
65    }
66
67    #[inline]
68    fn size_hint(&self) -> usize {
69        (**self).size_hint()
70    }
71}
72
73#[allow(unused_macros)]
74macro_rules! impl_encode_for_option {
75    ($DB:ident) => {
76        impl<'q, T> crate::encode::Encode<'q, $DB> for Option<T>
77        where
78            T: crate::encode::Encode<'q, $DB> + crate::types::Type<$DB> + 'q,
79        {
80            #[inline]
81            fn produces(&self) -> Option<<$DB as crate::database::Database>::TypeInfo> {
82                if let Some(v) = self {
83                    v.produces()
84                } else {
85                    T::type_info().into()
86                }
87            }
88
89            #[inline]
90            fn encode(
91                self,
92                buf: &mut <$DB as crate::database::HasArguments<'q>>::ArgumentBuffer,
93            ) -> crate::encode::IsNull {
94                if let Some(v) = self {
95                    v.encode(buf)
96                } else {
97                    crate::encode::IsNull::Yes
98                }
99            }
100
101            #[inline]
102            fn encode_by_ref(
103                &self,
104                buf: &mut <$DB as crate::database::HasArguments<'q>>::ArgumentBuffer,
105            ) -> crate::encode::IsNull {
106                if let Some(v) = self {
107                    v.encode_by_ref(buf)
108                } else {
109                    crate::encode::IsNull::Yes
110                }
111            }
112
113            #[inline]
114            fn size_hint(&self) -> usize {
115                self.as_ref().map_or(0, crate::encode::Encode::size_hint)
116            }
117        }
118    };
119}