Skip to main content

sea_query/value/
postgres_array.rs

1use super::*;
2use crate::RcOrArc;
3
4// We only implement conversion from Vec<T> to Array when T is not u8.
5// This is because for u8's case, there is already conversion to Byte defined above.
6// TODO When negative trait becomes a stable feature, following code can be much shorter.
7pub trait NotU8 {}
8
9impl NotU8 for bool {}
10impl NotU8 for i8 {}
11impl NotU8 for i16 {}
12impl NotU8 for i32 {}
13impl NotU8 for i64 {}
14impl NotU8 for u16 {}
15impl NotU8 for u32 {}
16impl NotU8 for u64 {}
17impl NotU8 for f32 {}
18impl NotU8 for f64 {}
19impl NotU8 for char {}
20impl NotU8 for String {}
21impl NotU8 for Vec<u8> {}
22
23#[cfg(feature = "with-json")]
24impl NotU8 for Json {}
25
26#[cfg(feature = "with-chrono")]
27impl NotU8 for NaiveDate {}
28
29#[cfg(feature = "with-chrono")]
30impl NotU8 for NaiveTime {}
31
32#[cfg(feature = "with-chrono")]
33impl NotU8 for NaiveDateTime {}
34
35#[cfg(feature = "with-chrono")]
36impl<Tz> NotU8 for DateTime<Tz> where Tz: chrono::TimeZone {}
37
38#[cfg(feature = "with-time")]
39impl NotU8 for time::Date {}
40
41#[cfg(feature = "with-time")]
42impl NotU8 for time::Time {}
43
44#[cfg(feature = "with-time")]
45impl NotU8 for PrimitiveDateTime {}
46
47#[cfg(feature = "with-time")]
48impl NotU8 for OffsetDateTime {}
49
50#[cfg(feature = "with-jiff")]
51impl NotU8 for jiff::civil::Date {}
52
53#[cfg(feature = "with-jiff")]
54impl NotU8 for jiff::civil::Time {}
55
56#[cfg(feature = "with-jiff")]
57impl NotU8 for jiff::civil::DateTime {}
58
59#[cfg(feature = "with-jiff")]
60impl NotU8 for jiff::Timestamp {}
61
62#[cfg(feature = "with-rust_decimal")]
63impl NotU8 for Decimal {}
64
65#[cfg(feature = "with-bigdecimal")]
66impl NotU8 for BigDecimal {}
67
68#[cfg(feature = "with-uuid")]
69impl NotU8 for Uuid {}
70
71#[cfg(feature = "with-uuid")]
72impl NotU8 for uuid::fmt::Braced {}
73
74#[cfg(feature = "with-uuid")]
75impl NotU8 for uuid::fmt::Hyphenated {}
76
77#[cfg(feature = "with-uuid")]
78impl NotU8 for uuid::fmt::Simple {}
79
80#[cfg(feature = "with-uuid")]
81impl NotU8 for uuid::fmt::Urn {}
82
83#[cfg(feature = "with-ipnetwork")]
84impl NotU8 for IpNetwork {}
85
86#[cfg(feature = "with-mac_address")]
87impl NotU8 for MacAddress {}
88
89/// If this blanket impl is causing trouble, please open an issue
90impl<T> NotU8 for &T where T: NotU8 {}
91
92impl<T> From<Vec<T>> for Value
93where
94    T: Into<Value> + NotU8 + ValueType,
95{
96    fn from(x: Vec<T>) -> Value {
97        Value::Array(
98            T::array_type(),
99            Some(Box::new(x.into_iter().map(|e| e.into()).collect())),
100        )
101    }
102}
103
104impl<T> Nullable for Vec<T>
105where
106    T: Into<Value> + NotU8 + ValueType,
107{
108    fn null() -> Value {
109        Value::Array(T::array_type(), None)
110    }
111}
112
113impl<T> ValueType for Vec<T>
114where
115    T: NotU8 + ValueType,
116{
117    fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
118        match v {
119            Value::Array(ty, Some(v)) if T::array_type() == ty => v
120                .into_iter()
121                .map(|e| {
122                    if e.is_some() {
123                        Ok(e.unwrap())
124                    } else {
125                        Err(ValueTypeErr)
126                    }
127                })
128                .collect(),
129            _ => Err(ValueTypeErr),
130        }
131    }
132
133    fn type_name() -> String {
134        stringify!(Vec<T>).to_owned()
135    }
136
137    fn array_type() -> ArrayType {
138        T::array_type()
139    }
140
141    fn column_type() -> ColumnType {
142        use ColumnType::*;
143        Array(RcOrArc::new(T::column_type()))
144    }
145}
146
147impl<T> ValueType for Vec<Option<T>>
148where
149    T: NotU8 + ValueType,
150{
151    fn try_from(v: Value) -> Result<Self, ValueTypeErr> {
152        match v {
153            Value::Array(ty, Some(v)) if T::array_type() == ty => v
154                .into_iter()
155                .map(|e| {
156                    if e.is_some() {
157                        T::try_from(e).map(Some)
158                    } else {
159                        Ok(None)
160                    }
161                })
162                .collect(),
163            _ => Err(ValueTypeErr),
164        }
165    }
166
167    fn type_name() -> String {
168        stringify!(Vec<Option<T>>).to_owned()
169    }
170
171    fn array_type() -> ArrayType {
172        T::array_type()
173    }
174
175    fn column_type() -> ColumnType {
176        use ColumnType::*;
177        Array(RcOrArc::new(T::column_type()))
178    }
179}
180
181impl Value {
182    pub fn is_array(&self) -> bool {
183        matches!(self, Self::Array(_, _))
184    }
185
186    pub fn as_ref_array(&self) -> Option<&Vec<Value>> {
187        match self {
188            Self::Array(_, v) => v.as_ref().map(|v| v.as_ref()),
189            _ => panic!("not Value::Array"),
190        }
191    }
192}