1pub use crate::codec::EnumValue;
5use crate::codec::{
6 InputObjectShape, InputShapeElement, NamedTupleShape, ObjectShape, SQLRowShape,
7};
8use crate::common::Cardinality;
9use crate::model::{BigInt, ConfigMemory, Decimal, Range, Uuid};
10use crate::model::{DateDuration, Json, RelativeDuration};
11use crate::model::{Datetime, Duration, LocalDate, LocalDatetime, LocalTime};
12
13#[derive(Clone, Debug, PartialEq)]
14pub enum Value {
15 Nothing,
16 Uuid(Uuid),
17 Str(String),
18 Bytes(bytes::Bytes),
19 Int16(i16),
20 Int32(i32),
21 Int64(i64),
22 Float32(f32),
23 Float64(f64),
24 BigInt(BigInt),
25 ConfigMemory(ConfigMemory),
26 Decimal(Decimal),
27 Bool(bool),
28 Datetime(Datetime),
29 LocalDatetime(LocalDatetime),
30 LocalDate(LocalDate),
31 LocalTime(LocalTime),
32 Duration(Duration),
33 RelativeDuration(RelativeDuration),
34 DateDuration(DateDuration),
35 Json(Json),
36 Set(Vec<Value>),
37 Object {
38 shape: ObjectShape,
39 fields: Vec<Option<Value>>,
40 },
41 SparseObject(SparseObject),
42 Tuple(Vec<Value>),
43 NamedTuple {
44 shape: NamedTupleShape,
45 fields: Vec<Value>,
46 },
47 SQLRow {
48 shape: SQLRowShape,
49 fields: Vec<Option<Value>>,
50 },
51 Array(Vec<Value>),
52 Vector(Vec<f32>),
53 Enum(EnumValue),
54 Range(Range<Box<Value>>),
55 PostGisGeometry(bytes::Bytes),
56 PostGisGeography(bytes::Bytes),
57 PostGisBox2d(bytes::Bytes),
58 PostGisBox3d(bytes::Bytes),
59}
60
61#[derive(Clone, Debug)]
62pub struct SparseObject {
63 pub(crate) shape: InputObjectShape,
64 pub(crate) fields: Vec<Option<Option<Value>>>,
65}
66
67impl Value {
68 pub fn kind(&self) -> &'static str {
69 use Value::*;
70 match self {
71 Array(..) => "array",
72 BigInt(..) => "bigint",
73 Bool(..) => "bool",
74 Bytes(..) => "bytes",
75 ConfigMemory(..) => "cfg::memory",
76 DateDuration(..) => "cal::date_duration",
77 Datetime(..) => "datetime",
78 Decimal(..) => "decimal",
79 Duration(..) => "duration",
80 Enum(..) => "enum",
81 Float32(..) => "float32",
82 Float64(..) => "float64",
83 Int16(..) => "int16",
84 Int32(..) => "int32",
85 Int64(..) => "int64",
86 Json(..) => "json",
87 LocalDate(..) => "cal::local_date",
88 LocalDatetime(..) => "cal::local_datetime",
89 LocalTime(..) => "cal::local_time",
90 NamedTuple { .. } => "named_tuple",
91 Nothing => "nothing",
92 Object { .. } => "object",
93 Range { .. } => "range",
94 RelativeDuration(..) => "cal::relative_duration",
95 Set(..) => "set",
96 SparseObject { .. } => "sparse_object",
97 Str(..) => "str",
98 Tuple(..) => "tuple",
99 Uuid(..) => "uuid",
100 Vector(..) => "ext::pgvector::vector",
101 PostGisGeometry(..) => "ext::postgis::geometry",
102 PostGisGeography(..) => "ext::postgis::geography",
103 PostGisBox2d(..) => "ext::postgis::box2d",
104 PostGisBox3d(..) => "ext::postgis::box3d",
105 SQLRow { .. } => "sql_row",
106 }
107 }
108 pub fn empty_tuple() -> Value {
109 Value::Tuple(Vec::new())
110 }
111
112 pub fn try_from_uuid(input: &str) -> Result<Self, uuid::Error> {
113 Ok(Self::Uuid(Uuid::parse_str(input)?))
114 }
115}
116
117impl SparseObject {
118 pub fn from_pairs<N: ToString, V: Into<Option<Value>>>(
126 iter: impl IntoIterator<Item = (N, V)>,
127 ) -> SparseObject {
128 let mut elements = Vec::new();
129 let mut fields = Vec::new();
130 for (key, val) in iter.into_iter() {
131 elements.push(InputShapeElement {
132 cardinality: Some(Cardinality::AtMostOne),
133 name: key.to_string(),
134 });
135 fields.push(Some(val.into()));
136 }
137 SparseObject {
138 shape: InputObjectShape::new(elements),
139 fields,
140 }
141 }
142 pub fn empty() -> SparseObject {
144 SparseObject {
145 shape: InputObjectShape::new(Vec::new()),
146 fields: Vec::new(),
147 }
148 }
149 pub fn pairs(&self) -> impl Iterator<Item = (&str, Option<&Value>)> {
150 self.shape
151 .0
152 .elements
153 .iter()
154 .zip(&self.fields)
155 .filter_map(|(el, opt)| opt.as_ref().map(|opt| (&*el.name, opt.as_ref())))
156 }
157}
158
159impl PartialEq for SparseObject {
160 fn eq(&self, other: &SparseObject) -> bool {
161 let mut num = 0;
162 let o = &other.shape.0.elements;
163 for (el, value) in self.shape.0.elements.iter().zip(&self.fields) {
164 if let Some(value) = value {
165 num += 1;
166 if let Some(pos) = o.iter().position(|e| e.name == el.name) {
167 if other.fields[pos].as_ref() != Some(value) {
168 return false;
169 }
170 }
171 }
172 }
173 let other_num = other.fields.iter().filter(|e| e.is_some()).count();
174 num == other_num
175 }
176}
177
178impl From<String> for Value {
179 fn from(s: String) -> Value {
180 Value::Str(s)
181 }
182}
183
184impl From<&str> for Value {
185 fn from(s: &str) -> Value {
186 Value::Str(s.to_string())
187 }
188}
189
190impl From<bool> for Value {
191 fn from(b: bool) -> Value {
192 Value::Bool(b)
193 }
194}
195
196impl From<i16> for Value {
197 fn from(s: i16) -> Value {
198 Value::Int16(s)
199 }
200}
201
202impl From<i32> for Value {
203 fn from(s: i32) -> Value {
204 Value::Int32(s)
205 }
206}
207
208impl From<i64> for Value {
209 fn from(s: i64) -> Value {
210 Value::Int64(s)
211 }
212}
213
214impl From<f32> for Value {
215 fn from(num: f32) -> Value {
216 Value::Float32(num)
217 }
218}
219
220impl From<f64> for Value {
221 fn from(num: f64) -> Value {
222 Value::Float64(num)
223 }
224}
225
226impl From<BigInt> for Value {
227 fn from(model: BigInt) -> Value {
228 Value::BigInt(model)
229 }
230}
231
232impl From<Decimal> for Value {
233 fn from(v: Decimal) -> Value {
234 Value::Decimal(v)
235 }
236}
237
238impl From<Uuid> for Value {
239 fn from(v: Uuid) -> Value {
240 Value::Uuid(v)
241 }
242}
243
244impl From<Json> for Value {
245 fn from(v: Json) -> Value {
246 Value::Json(v)
247 }
248}
249
250impl From<Duration> for Value {
251 fn from(v: Duration) -> Value {
252 Value::Duration(v)
253 }
254}
255
256impl From<Datetime> for Value {
257 fn from(v: Datetime) -> Value {
258 Value::Datetime(v)
259 }
260}
261
262impl From<LocalDate> for Value {
263 fn from(v: LocalDate) -> Value {
264 Value::LocalDate(v)
265 }
266}
267
268impl From<LocalDatetime> for Value {
269 fn from(v: LocalDatetime) -> Value {
270 Value::LocalDatetime(v)
271 }
272}