1use sqlx_core::decode::Decode;
10use sqlx_core::encode::{Encode, IsNull};
11use sqlx_core::error::BoxDynError;
12use sqlx_core::types::Type;
13
14use spg_embedded::Value as EngineValue;
15
16use crate::arguments::SpgArgumentValue;
17use crate::database::Spg;
18use crate::type_info::{Kind, SpgTypeInfo};
19use crate::value::SpgValueRef;
20
21impl Type<Spg> for [i32] {
28 fn type_info() -> SpgTypeInfo {
29 SpgTypeInfo::of(Kind::Text)
35 }
36 fn compatible(_ty: &SpgTypeInfo) -> bool {
37 true
38 }
39}
40
41impl Type<Spg> for Vec<i32> {
42 fn type_info() -> SpgTypeInfo {
43 <[i32] as Type<Spg>>::type_info()
44 }
45 fn compatible(_ty: &SpgTypeInfo) -> bool {
46 true
47 }
48}
49
50impl<'q> Encode<'q, Spg> for [i32] {
51 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
52 buf.push(SpgArgumentValue {
57 value: EngineValue::IntArray(self.iter().map(|v| Some(*v)).collect()),
58 type_info: Some(<[i32] as Type<Spg>>::type_info()),
59 _phantom: core::marker::PhantomData,
60 });
61 Ok(IsNull::No)
62 }
63}
64
65impl<'q> Encode<'q, Spg> for Vec<i32> {
66 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
67 self.as_slice().encode_by_ref(buf)
68 }
69}
70
71impl<'q> Encode<'q, Spg> for &'q [i32] {
74 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
75 (**self).encode_by_ref(buf)
76 }
77}
78
79impl<'r> Decode<'r, Spg> for Vec<i32> {
80 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
81 match value.engine() {
82 EngineValue::IntArray(items) => Ok(items.iter().filter_map(|o| *o).collect()),
83 EngineValue::BigIntArray(items) => Ok(items
85 .iter()
86 .filter_map(|o| (*o).and_then(|n| i32::try_from(n).ok()))
87 .collect()),
88 other => Err(format!("cannot decode {other:?} as Vec<i32>").into()),
89 }
90 }
91}
92
93impl Type<Spg> for [i64] {
96 fn type_info() -> SpgTypeInfo {
97 SpgTypeInfo::of(Kind::Text)
98 }
99 fn compatible(_ty: &SpgTypeInfo) -> bool {
100 true
101 }
102}
103
104impl Type<Spg> for Vec<i64> {
105 fn type_info() -> SpgTypeInfo {
106 <[i64] as Type<Spg>>::type_info()
107 }
108 fn compatible(_ty: &SpgTypeInfo) -> bool {
109 true
110 }
111}
112
113impl<'q> Encode<'q, Spg> for [i64] {
114 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
115 buf.push(SpgArgumentValue {
116 value: EngineValue::BigIntArray(self.iter().map(|v| Some(*v)).collect()),
117 type_info: Some(<[i64] as Type<Spg>>::type_info()),
118 _phantom: core::marker::PhantomData,
119 });
120 Ok(IsNull::No)
121 }
122}
123
124impl<'q> Encode<'q, Spg> for Vec<i64> {
125 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
126 self.as_slice().encode_by_ref(buf)
127 }
128}
129
130impl<'q> Encode<'q, Spg> for &'q [i64] {
133 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
134 (**self).encode_by_ref(buf)
135 }
136}
137
138impl<'r> Decode<'r, Spg> for Vec<i64> {
139 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
140 match value.engine() {
141 EngineValue::BigIntArray(items) => Ok(items.iter().filter_map(|o| *o).collect()),
142 EngineValue::IntArray(items) => {
143 Ok(items.iter().filter_map(|o| (*o).map(i64::from)).collect())
144 }
145 other => Err(format!("cannot decode {other:?} as Vec<i64>").into()),
146 }
147 }
148}
149
150impl Type<Spg> for [String] {
153 fn type_info() -> SpgTypeInfo {
154 SpgTypeInfo::of(Kind::Text)
155 }
156 fn compatible(_ty: &SpgTypeInfo) -> bool {
157 true
158 }
159}
160
161impl Type<Spg> for Vec<String> {
162 fn type_info() -> SpgTypeInfo {
163 <[String] as Type<Spg>>::type_info()
164 }
165 fn compatible(_ty: &SpgTypeInfo) -> bool {
166 true
167 }
168}
169
170fn encode_text_array<'q, S: AsRef<str>>(
173 items: impl Iterator<Item = S>,
174 buf: &mut Vec<SpgArgumentValue<'q>>,
175) -> Result<IsNull, BoxDynError> {
176 buf.push(SpgArgumentValue {
177 value: EngineValue::TextArray(items.map(|v| Some(v.as_ref().to_string())).collect()),
178 type_info: Some(<[String] as Type<Spg>>::type_info()),
179 _phantom: core::marker::PhantomData,
180 });
181 Ok(IsNull::No)
182}
183
184impl<'q> Encode<'q, Spg> for [String] {
185 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
186 encode_text_array(self.iter(), buf)
187 }
188}
189
190impl<'q> Encode<'q, Spg> for Vec<String> {
191 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
192 self.as_slice().encode_by_ref(buf)
193 }
194}
195
196impl<'q> Encode<'q, Spg> for &'q [String] {
199 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
200 (**self).encode_by_ref(buf)
201 }
202}
203
204impl Type<Spg> for [&str] {
207 fn type_info() -> SpgTypeInfo {
208 SpgTypeInfo::of(Kind::Text)
209 }
210 fn compatible(_ty: &SpgTypeInfo) -> bool {
211 true
212 }
213}
214
215impl Type<Spg> for Vec<&str> {
216 fn type_info() -> SpgTypeInfo {
217 <[&str] as Type<Spg>>::type_info()
218 }
219 fn compatible(_ty: &SpgTypeInfo) -> bool {
220 true
221 }
222}
223
224impl<'q> Encode<'q, Spg> for [&str] {
225 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
226 encode_text_array(self.iter(), buf)
227 }
228}
229
230impl<'q> Encode<'q, Spg> for Vec<&str> {
231 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
232 self.as_slice().encode_by_ref(buf)
233 }
234}
235
236impl<'q> Encode<'q, Spg> for &'q [&str] {
239 fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
240 (**self).encode_by_ref(buf)
241 }
242}
243
244impl<'r> Decode<'r, Spg> for Vec<String> {
245 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
246 match value.engine() {
247 EngineValue::TextArray(items) => Ok(items.iter().filter_map(|o| o.clone()).collect()),
248 other => Err(format!("cannot decode {other:?} as Vec<String>").into()),
249 }
250 }
251}