gel_protocol/
value.rs

1/*!
2Contains the [Value] enum.
3*/
4pub 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    /// Create a new sparse object from key-value pairs
119    ///
120    /// Note: this method has two limitations:
121    /// 1. Shape created uses `AtMostOne` cardinality for all the elements.
122    /// 2. There are no extra shape elements
123    ///
124    /// Both of these are irrelevant when serializing the object.
125    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    /// Create an empty sparse object
143    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}