sea_query/value/
with_array.rs1use 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
55impl 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
179macro_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}