sea_query/value/
with_array.rs1use super::ArrayElement;
2use super::*;
3use crate::RcOrArc;
4
5pub trait NotU8 {}
9
10impl NotU8 for bool {}
11impl NotU8 for i8 {}
12impl NotU8 for i16 {}
13impl NotU8 for i32 {}
14impl NotU8 for i64 {}
15impl NotU8 for u16 {}
16impl NotU8 for u32 {}
17impl NotU8 for u64 {}
18impl NotU8 for f32 {}
19impl NotU8 for f64 {}
20impl NotU8 for char {}
21impl NotU8 for String {}
22impl NotU8 for Vec<u8> {}
23
24impl<T: NotU8> NotU8 for Option<T> {}
25
26#[cfg(feature = "with-json")]
27impl NotU8 for Json {}
28
29#[cfg(feature = "with-chrono")]
30impl NotU8 for NaiveDate {}
31
32#[cfg(feature = "with-chrono")]
33impl NotU8 for NaiveTime {}
34
35#[cfg(feature = "with-chrono")]
36impl NotU8 for NaiveDateTime {}
37
38#[cfg(feature = "with-chrono")]
39impl<Tz> NotU8 for chrono::DateTime<Tz> where Tz: chrono::TimeZone {}
40
41#[cfg(feature = "with-time")]
42impl NotU8 for time::Date {}
43
44#[cfg(feature = "with-time")]
45impl NotU8 for time::Time {}
46
47#[cfg(feature = "with-time")]
48impl NotU8 for PrimitiveDateTime {}
49
50#[cfg(feature = "with-time")]
51impl NotU8 for OffsetDateTime {}
52
53#[cfg(feature = "with-jiff")]
54impl NotU8 for jiff::civil::Date {}
55
56#[cfg(feature = "with-jiff")]
57impl NotU8 for jiff::civil::Time {}
58
59#[cfg(feature = "with-jiff")]
60impl NotU8 for jiff::civil::DateTime {}
61
62#[cfg(feature = "with-jiff")]
63impl NotU8 for jiff::Timestamp {}
64
65#[cfg(feature = "with-jiff")]
66impl NotU8 for jiff::Zoned {}
67
68#[cfg(feature = "with-rust_decimal")]
69impl NotU8 for rust_decimal::Decimal {}
70
71#[cfg(feature = "with-bigdecimal")]
72impl NotU8 for bigdecimal::BigDecimal {}
73
74#[cfg(feature = "with-uuid")]
75impl NotU8 for Uuid {}
76
77#[cfg(feature = "with-uuid")]
78impl NotU8 for uuid::fmt::Braced {}
79
80#[cfg(feature = "with-uuid")]
81impl NotU8 for uuid::fmt::Hyphenated {}
82
83#[cfg(feature = "with-uuid")]
84impl NotU8 for uuid::fmt::Simple {}
85
86#[cfg(feature = "with-uuid")]
87impl NotU8 for uuid::fmt::Urn {}
88
89#[cfg(feature = "with-ipnetwork")]
90impl NotU8 for IpNetwork {}
91
92#[cfg(feature = "with-mac_address")]
93impl NotU8 for MacAddress {}
94
95macro_rules! impl_value_vec {
96 ($($ty:ty => $vari:ident)*) => {
97 $(
98 impl From<Vec<$ty>> for Array {
99 fn from(x: Vec<$ty>) -> Array {
100 let values: Vec<Option<_>> = x
101 .into_iter()
102 .map(Some)
103 .collect();
104
105 Array::$vari(values.into_boxed_slice())
106 }
107 }
108
109
110 impl From<Vec<Option<$ty>>> for Array {
111 fn from(x: Vec<Option<$ty>>) -> Array {
112 Array::$vari(x.into_boxed_slice())
113 }
114 }
115
116 impl<const N: usize> From<[$ty; N]> for Array {
117 fn from(x: [$ty; N]) -> Array {
118 let vec: Vec<_> = x.into_iter().collect();
119 vec.into()
120 }
121 }
122
123 impl From<Vec<$ty>> for Value {
124 fn from(x: Vec<$ty>) -> Value {
125 let values: Vec<Option<_>> = x
126 .into_iter()
127 .map(Some)
128 .collect();
129
130 Value::Array(
131 Array::$vari(values.into_boxed_slice())
132 )
133 }
134 }
135
136 impl From<Vec<Option<$ty>>> for Value {
137 fn from(x: Vec<Option<$ty>>) -> Value {
138 Value::Array(Array::$vari(x.into()))
139 }
140 }
141
142 impl ValueType for Vec<Option<$ty>>
143 {
144 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
145 match v {
146 Value::Array(Array::$vari(inner)) => {
147 Ok(inner.into_vec())
148 }
149 _ => Err(ValueTypeErr),
150 }
151 }
152
153 fn type_name() -> String {
154 stringify!(Vec<$ty>).to_owned()
155 }
156
157 fn array_type() -> ArrayType {
158 <$ty>::array_type()
159 }
160
161 fn column_type() -> ColumnType {
162 use ColumnType::*;
163 Array(RcOrArc::new(<$ty>::column_type()))
164 }
165 }
166
167
168 impl ValueType for Vec<$ty> {
169 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
170 match v {
171 Value::Array(Array::$vari(inner)) => {
172 inner.into_vec()
173 .into_iter()
174 .map(|opt| Option::ok_or(opt,ValueTypeErr))
176 .collect()
177 }
178 _ => Err(ValueTypeErr),
179 }
180 }
181
182 fn type_name() -> String {
183 format!("Vec<{}>", stringify!($ty))
184 }
185
186 fn array_type() -> ArrayType {
187 <$ty>::array_type()
188 }
189
190 fn column_type() -> ColumnType {
191 ColumnType::Array(RcOrArc::new(<$ty>::column_type()))
192 }
193 }
194 )*
195 }
196}
197
198impl_value_vec! {
199 bool => Bool
200 i8 => TinyInt
201 i16 => SmallInt
202 i32 => Int
203 i64 => BigInt
204 u16 => SmallUnsigned
205 u32 => Unsigned
206 u64 => BigUnsigned
207 f32 => Float
208 f64 => Double
209 std::string::String => String
210 char => Char
211 Vec<u8> => Bytes
212}
213
214impl From<Vec<u8>> for Array {
217 fn from(x: Vec<u8>) -> Array {
218 let values: Vec<Option<_>> = x.into_iter().map(Some).collect();
219
220 Array::TinyUnsigned(values.into_boxed_slice())
221 }
222}
223
224impl From<Vec<Option<u8>>> for Array {
225 fn from(x: Vec<Option<u8>>) -> Array {
226 Array::TinyUnsigned(x.into_boxed_slice())
227 }
228}
229
230impl From<Vec<Option<u8>>> for Value {
231 fn from(x: Vec<Option<u8>>) -> Value {
232 Value::Array(Array::TinyUnsigned(x.into_boxed_slice()))
233 }
234}
235
236impl ValueType for Vec<Option<u8>> {
237 fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
238 match v {
239 Value::Array(Array::TinyUnsigned(inner)) => Ok(inner.into_vec()),
240 _ => Err(ValueTypeErr),
241 }
242 }
243
244 fn type_name() -> String {
245 stringify!(Vec<u8>).to_owned()
246 }
247
248 fn array_type() -> ArrayType {
249 <u8>::array_type()
250 }
251
252 fn column_type() -> ColumnType {
253 use ColumnType::*;
254 Array(RcOrArc::new(<u8>::column_type()))
255 }
256}
257
258#[cfg(feature = "with-json")]
259impl_value_vec! {
260 serde_json::Value => Json
261}
262
263impl From<(Arc<str>, Vec<Option<Arc<Enum>>>)> for Value {
264 fn from(x: (Arc<str>, Vec<Option<Arc<Enum>>>)) -> Value {
265 Value::Array(Array::Enum(Box::new((x.0, x.1.into_boxed_slice()))))
266 }
267}
268
269#[cfg(feature = "with-chrono")]
270impl_value_vec! {
271 NaiveDate => ChronoDate
272 NaiveTime => ChronoTime
273 NaiveDateTime => ChronoDateTime
274 chrono::DateTime<chrono::Utc> => ChronoDateTimeUtc
275 chrono::DateTime<chrono::Local> => ChronoDateTimeLocal
276 chrono::DateTime<chrono::FixedOffset> => ChronoDateTimeWithTimeZone
277}
278
279#[cfg(feature = "with-time")]
280impl_value_vec! {
281 time::Date => TimeDate
282 time::Time => TimeTime
283 PrimitiveDateTime => TimeDateTime
284 OffsetDateTime => TimeDateTimeWithTimeZone
285}
286
287#[cfg(feature = "with-jiff")]
288impl_value_vec! {
289 jiff::civil::Date => JiffDate
290 jiff::civil::Time => JiffTime
291 jiff::civil::DateTime => JiffDateTime
292 jiff::Timestamp => JiffTimestamp
293 jiff::Zoned => JiffZoned
294}
295
296#[cfg(feature = "with-rust_decimal")]
297impl_value_vec! {
298 rust_decimal::Decimal => Decimal
299}
300
301#[cfg(feature = "with-bigdecimal")]
302impl_value_vec! {
303 bigdecimal::BigDecimal => BigDecimal
304}
305
306#[cfg(feature = "with-uuid")]
307impl_value_vec! {
308 uuid::Uuid => Uuid
309}
310
311macro_rules! impl_uuid_fmt_pg_array_element {
313 ($ty:ty, $method:ident) => {
314 #[cfg(feature = "with-uuid")]
315 impl ArrayElement for $ty {
316 type ArrayValueType = Uuid;
317
318 fn into_array_value(self) -> Self::ArrayValueType {
319 self.into_uuid()
320 }
321
322 fn try_from_value(v: Value) -> Result<Vec<Option<Self>>, ValueTypeErr> {
323 match v {
324 Value::Array(Array::Uuid(inner)) => Ok(inner
325 .into_vec()
326 .into_iter()
327 .map(|opt| opt.map(Self::from))
328 .collect()),
329 Value::Array(Array::Null(_)) => Ok(vec![]),
330 _ => Err(ValueTypeErr),
331 }
332 }
333 }
334 };
335}
336
337impl_uuid_fmt_pg_array_element!(uuid::fmt::Braced, braced);
338impl_uuid_fmt_pg_array_element!(uuid::fmt::Hyphenated, hyphenated);
339impl_uuid_fmt_pg_array_element!(uuid::fmt::Simple, simple);
340impl_uuid_fmt_pg_array_element!(uuid::fmt::Urn, urn);
341
342#[cfg(feature = "with-ipnetwork")]
343impl_value_vec! {
344 IpNetwork => IpNetwork
345}
346
347#[cfg(feature = "with-mac_address")]
348impl_value_vec! {
349 MacAddress => MacAddress
350}
351
352impl<T> Nullable for Vec<T>
353where
354 T: Into<Value> + NotU8 + ValueType,
355{
356 fn null() -> Value {
357 Value::Array(Array::Null(T::array_type()))
358 }
359}
360
361impl Value {
362 pub fn is_array(&self) -> bool {
363 matches!(self, Self::Array(_))
364 }
365
366 pub fn as_ref_array(&self) -> Option<&Array> {
367 match self {
368 Self::Array(v) if !v.is_null() => Some(v),
369 Self::Array(_) => None,
370 _ => panic!("not Value::Array"),
371 }
372 }
373}