sea_query/value/
with_array.rs

1use super::*;
2use crate::RcOrArc;
3
4macro_rules! impl_value_vec {
5    ($($ty:ty => $vari:ident)*) => {
6        $(
7            impl crate::sealed::Sealed for $ty {}
8
9            impl ArrayValue for $ty {
10                fn array_type() -> ArrayType {
11                    ArrayType::$vari
12                }
13
14                fn into_array(iter: impl IntoIterator<Item = Option<Self>>) -> Array {
15                    let boxed = Box::from_iter(iter);
16                    Array::$vari(boxed)
17                }
18            }
19
20            impl ArrayElement for $ty
21            {
22                type ArrayValueType = $ty;
23
24                fn into_array_value(self) -> Self::ArrayValueType {
25                    self
26                }
27
28                fn try_from_value(v: Value) -> Result<Vec<Option<Self>>, ValueTypeErr> {
29                    match v {
30                        Value::Array(Array::$vari(inner)) => Ok(inner.into_vec()),
31                        _ => Err(ValueTypeErr)
32                    }
33                }
34            }
35       )*
36    }
37}
38
39impl_value_vec! {
40    bool => Bool
41    i8 => TinyInt
42    i16 => SmallInt
43    i32 => Int
44    i64 => BigInt
45    u16 => SmallUnsigned
46    u32 => Unsigned
47    u64 => BigUnsigned
48    f32 => Float
49    f64 => Double
50    std::string::String => String
51    char => Char
52    Vec<u8> => Bytes
53}
54
55// Impls for u8
56// because Vec<u8> is already defined as Bytes
57impl crate::sealed::Sealed for u8 {}
58
59impl ArrayValue for u8 {
60    fn array_type() -> ArrayType {
61        ArrayType::TinyUnsigned
62    }
63
64    fn into_array(iter: impl IntoIterator<Item = Option<Self>>) -> Array {
65        let boxed = Box::from_iter(iter);
66        Array::TinyUnsigned(boxed)
67    }
68}
69
70impl From<Vec<u8>> for Array {
71    fn from(x: Vec<u8>) -> Array {
72        let values: Box<[Option<_>]> = x.into_iter().map(Some).collect();
73
74        Array::TinyUnsigned(values)
75    }
76}
77
78impl From<Vec<Option<u8>>> for Array {
79    fn from(x: Vec<Option<u8>>) -> Array {
80        Array::TinyUnsigned(x.into_boxed_slice())
81    }
82}
83
84impl From<Box<[u8]>> for Array {
85    fn from(x: Box<[u8]>) -> Array {
86        let values: Box<[Option<_>]> = x.into_iter().map(Some).collect();
87
88        Array::TinyUnsigned(values)
89    }
90}
91
92impl From<Box<[Option<u8>]>> for Array {
93    fn from(x: Box<[Option<u8>]>) -> Array {
94        Array::TinyUnsigned(x)
95    }
96}
97
98impl From<Vec<Option<u8>>> for Value {
99    fn from(x: Vec<Option<u8>>) -> Value {
100        Value::Array(Array::TinyUnsigned(x.into_boxed_slice()))
101    }
102}
103
104impl ValueType for Vec<Option<u8>> {
105    fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
106        match v {
107            Value::Array(Array::TinyUnsigned(inner)) => Ok(inner.into_vec()),
108            _ => Err(ValueTypeErr),
109        }
110    }
111
112    fn type_name() -> String {
113        stringify!(Vec<u8>).to_owned()
114    }
115
116    fn array_type() -> ArrayType {
117        <u8 as ArrayValue>::array_type()
118    }
119
120    fn column_type() -> ColumnType {
121        use ColumnType::*;
122        Array(RcOrArc::new(<u8>::column_type()))
123    }
124}
125
126#[cfg(feature = "with-json")]
127impl_value_vec! {
128    serde_json::Value => Json
129}
130
131impl From<(Arc<str>, Vec<Option<Arc<Enum>>>)> for Value {
132    fn from(x: (Arc<str>, Vec<Option<Arc<Enum>>>)) -> Value {
133        Value::Array(Array::Enum(Box::new((x.0, x.1.into_boxed_slice()))))
134    }
135}
136
137#[cfg(feature = "with-chrono")]
138impl_value_vec! {
139    NaiveDate => ChronoDate
140    NaiveTime => ChronoTime
141    NaiveDateTime => ChronoDateTime
142    chrono::DateTime<chrono::Utc> => ChronoDateTimeUtc
143    chrono::DateTime<chrono::Local> => ChronoDateTimeLocal
144    chrono::DateTime<chrono::FixedOffset> => ChronoDateTimeWithTimeZone
145}
146
147#[cfg(feature = "with-time")]
148impl_value_vec! {
149    time::Date => TimeDate
150    time::Time => TimeTime
151    PrimitiveDateTime => TimeDateTime
152    OffsetDateTime => TimeDateTimeWithTimeZone
153}
154
155#[cfg(feature = "with-jiff")]
156impl_value_vec! {
157    jiff::civil::Date => JiffDate
158    jiff::civil::Time => JiffTime
159    jiff::civil::DateTime => JiffDateTime
160    jiff::Timestamp => JiffTimestamp
161    jiff::Zoned => JiffZoned
162}
163
164#[cfg(feature = "with-rust_decimal")]
165impl_value_vec! {
166    rust_decimal::Decimal => Decimal
167}
168
169#[cfg(feature = "with-bigdecimal")]
170impl_value_vec! {
171    bigdecimal::BigDecimal => BigDecimal
172}
173
174#[cfg(feature = "with-uuid")]
175impl_value_vec! {
176    uuid::Uuid => Uuid
177}
178
179// uuid::fmt::* types use UUID arrays
180macro_rules! impl_uuid_fmt_pg_array_element {
181    ($ty:ty, $method:ident) => {
182        #[cfg(feature = "with-uuid")]
183        impl ArrayElement for $ty {
184            type ArrayValueType = Uuid;
185
186            fn into_array_value(self) -> Self::ArrayValueType {
187                self.into_uuid()
188            }
189
190            fn try_from_value(v: Value) -> Result<Vec<Option<Self>>, ValueTypeErr> {
191                match v {
192                    Value::Array(Array::Uuid(inner)) => Ok(inner
193                        .into_vec()
194                        .into_iter()
195                        .map(|opt| opt.map(Self::from))
196                        .collect()),
197                    Value::Array(Array::Null(_)) => Ok(vec![]),
198                    _ => Err(ValueTypeErr),
199                }
200            }
201        }
202    };
203}
204
205impl_uuid_fmt_pg_array_element!(uuid::fmt::Braced, braced);
206impl_uuid_fmt_pg_array_element!(uuid::fmt::Hyphenated, hyphenated);
207impl_uuid_fmt_pg_array_element!(uuid::fmt::Simple, simple);
208impl_uuid_fmt_pg_array_element!(uuid::fmt::Urn, urn);
209
210#[cfg(feature = "with-ipnetwork")]
211impl_value_vec! {
212    IpNetwork => IpNetwork
213}
214
215#[cfg(feature = "with-mac_address")]
216impl_value_vec! {
217    MacAddress => MacAddress
218}
219
220impl<T> Nullable for Vec<T>
221where
222    T: ArrayElement,
223{
224    fn null() -> Value {
225        Value::Array(Array::Null(T::ArrayValueType::array_type()))
226    }
227}
228
229impl<T> Nullable for Vec<Option<T>>
230where
231    T: ArrayElement,
232{
233    fn null() -> Value {
234        Value::Array(Array::Null(T::ArrayValueType::array_type()))
235    }
236}
237
238impl Value {
239    pub fn is_array(&self) -> bool {
240        matches!(self, Self::Array(_))
241    }
242
243    pub fn as_ref_array(&self) -> Option<&Array> {
244        match self {
245            Self::Array(v) if !v.is_null() => Some(v),
246            Self::Array(_) => None,
247            _ => panic!("not Value::Array"),
248        }
249    }
250}