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