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 Vec<i32> {
24 fn type_info() -> SpgTypeInfo {
25 SpgTypeInfo::of(Kind::Text)
31 }
32 fn compatible(_ty: &SpgTypeInfo) -> bool {
33 true
34 }
35}
36
37impl<'q> Encode<'q, Spg> for Vec<i32> {
38 fn encode_by_ref(
39 &self,
40 buf: &mut Vec<SpgArgumentValue<'q>>,
41 ) -> Result<IsNull, BoxDynError> {
42 let mut s = String::from("{");
44 for (i, v) in self.iter().enumerate() {
45 if i > 0 {
46 s.push(',');
47 }
48 s.push_str(&v.to_string());
49 }
50 s.push('}');
51 buf.push(SpgArgumentValue {
52 value: EngineValue::Text(s),
53 type_info: Some(<Vec<i32> as Type<Spg>>::type_info()),
54 _phantom: core::marker::PhantomData,
55 });
56 Ok(IsNull::No)
57 }
58}
59
60impl<'r> Decode<'r, Spg> for Vec<i32> {
61 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
62 match value.engine() {
63 EngineValue::IntArray(items) => {
64 Ok(items.iter().filter_map(|o| o.clone()).collect())
65 }
66 EngineValue::BigIntArray(items) => Ok(items
68 .iter()
69 .filter_map(|o| o.clone().and_then(|n| i32::try_from(n).ok()))
70 .collect()),
71 other => Err(format!("cannot decode {other:?} as Vec<i32>").into()),
72 }
73 }
74}
75
76impl Type<Spg> for Vec<i64> {
79 fn type_info() -> SpgTypeInfo {
80 SpgTypeInfo::of(Kind::Text)
81 }
82 fn compatible(_ty: &SpgTypeInfo) -> bool {
83 true
84 }
85}
86
87impl<'q> Encode<'q, Spg> for Vec<i64> {
88 fn encode_by_ref(
89 &self,
90 buf: &mut Vec<SpgArgumentValue<'q>>,
91 ) -> Result<IsNull, BoxDynError> {
92 let mut s = String::from("{");
93 for (i, v) in self.iter().enumerate() {
94 if i > 0 {
95 s.push(',');
96 }
97 s.push_str(&v.to_string());
98 }
99 s.push('}');
100 buf.push(SpgArgumentValue {
101 value: EngineValue::Text(s),
102 type_info: Some(<Vec<i64> as Type<Spg>>::type_info()),
103 _phantom: core::marker::PhantomData,
104 });
105 Ok(IsNull::No)
106 }
107}
108
109impl<'r> Decode<'r, Spg> for Vec<i64> {
110 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
111 match value.engine() {
112 EngineValue::BigIntArray(items) => {
113 Ok(items.iter().filter_map(|o| o.clone()).collect())
114 }
115 EngineValue::IntArray(items) => Ok(items
116 .iter()
117 .filter_map(|o| o.clone().map(i64::from))
118 .collect()),
119 other => Err(format!("cannot decode {other:?} as Vec<i64>").into()),
120 }
121 }
122}
123
124impl Type<Spg> for Vec<String> {
127 fn type_info() -> SpgTypeInfo {
128 SpgTypeInfo::of(Kind::Text)
129 }
130 fn compatible(_ty: &SpgTypeInfo) -> bool {
131 true
132 }
133}
134
135impl<'q> Encode<'q, Spg> for Vec<String> {
136 fn encode_by_ref(
137 &self,
138 buf: &mut Vec<SpgArgumentValue<'q>>,
139 ) -> Result<IsNull, BoxDynError> {
140 let mut s = String::from("{");
143 for (i, v) in self.iter().enumerate() {
144 if i > 0 {
145 s.push(',');
146 }
147 s.push('"');
148 for ch in v.chars() {
149 if ch == '\\' || ch == '"' {
150 s.push('\\');
151 }
152 s.push(ch);
153 }
154 s.push('"');
155 }
156 s.push('}');
157 buf.push(SpgArgumentValue {
158 value: EngineValue::Text(s),
159 type_info: Some(<Vec<String> as Type<Spg>>::type_info()),
160 _phantom: core::marker::PhantomData,
161 });
162 Ok(IsNull::No)
163 }
164}
165
166impl<'r> Decode<'r, Spg> for Vec<String> {
167 fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
168 match value.engine() {
169 EngineValue::TextArray(items) => {
170 Ok(items.iter().filter_map(|o| o.clone()).collect())
171 }
172 other => Err(format!("cannot decode {other:?} as Vec<String>").into()),
173 }
174 }
175}