partiql_value/
datum.rs

1use crate::{
2    Bag, BagIntoIterator, BindingsName, Graph, List, ListIntoIterator, PairsIntoIter, PairsIter,
3    Tuple, Value,
4};
5use std::borrow::Cow;
6use std::collections::HashMap;
7use std::error::Error;
8
9use std::fmt::Debug;
10
11pub type DatumLowerError = Box<dyn Error>;
12pub type DatumLowerResult<T> = Result<T, DatumLowerError>;
13
14pub trait Datum<D>
15where
16    D: Datum<D>,
17{
18    /// Returns true if and only if Value is to be interpreted as `NULL`
19    #[must_use]
20    fn is_null(&self) -> bool;
21
22    /// Returns true if and only if Value is to be interpreted as `MISSING`
23    #[must_use]
24    fn is_missing(&self) -> bool;
25
26    #[inline]
27    /// Returns true if and only if Value is null or missing
28    #[must_use]
29    fn is_absent(&self) -> bool {
30        self.is_null() || self.is_missing()
31    }
32
33    #[inline]
34    /// Returns true if Value is neither null nor missing
35    #[must_use]
36    fn is_present(&self) -> bool {
37        !self.is_absent()
38    }
39
40    #[must_use]
41    fn is_sequence(&self) -> bool;
42
43    #[must_use]
44    fn is_ordered(&self) -> bool;
45}
46
47pub trait DatumValue<D: Datum<D>>: Datum<D> + Clone + Debug {}
48
49pub trait DatumLower<D: DatumValue<D>>: Datum<D> + Debug {
50    fn into_lower(self) -> DatumLowerResult<D>;
51
52    fn into_lower_boxed(self: Box<Self>) -> DatumLowerResult<D>;
53    fn lower(&self) -> DatumLowerResult<Cow<'_, D>>;
54}
55
56pub trait DatumCategory<'a> {
57    fn category(&'a self) -> DatumCategoryRef<'a>;
58    fn into_category(self) -> DatumCategoryOwned;
59}
60
61#[derive(Debug)]
62pub enum DatumCategoryRef<'a> {
63    Null,
64    Missing,
65    Tuple(DatumTupleRef<'a>),
66    Sequence(DatumSeqRef<'a>),
67    Scalar(DatumValueRef<'a>),
68    Graph(DatumGraphRef<'a>),
69}
70
71#[derive(Debug)]
72pub enum DatumCategoryOwned {
73    Null,
74    Missing,
75    Tuple(DatumTupleOwned),
76    Sequence(DatumSeqOwned),
77    Scalar(DatumValueOwned),
78    Graph(DatumGraphOwned),
79}
80
81#[derive(Debug)]
82pub enum DatumTupleRef<'a> {
83    /// A Tuple with no bindings
84    Empty,
85    /// Holds a reference to a [`Tuple`]
86    Tuple(&'a Tuple),
87    /// Holds a reference to a [`RefTupleView`]
88    Dynamic(&'a dyn RefTupleView<'a, Value>),
89    /// Holds a reference to a value which is not a tuple, but has been coerced (e.g., for `9`: `{'_1': 9}`)
90    CoercedValue(usize, &'a Value),
91    /// A reference to a value stored under a single key
92    SingleKey(Cow<'a, str>, &'a Value),
93    /// A reference to a value stored under a single key
94    Bindings(&'a HashMap<Cow<'a, str>, &'a Value>),
95}
96
97#[derive(Debug)]
98pub enum DatumSeqRef<'a> {
99    List(&'a List),
100    Bag(&'a Bag),
101    Dynamic(&'a dyn RefSequenceView<'a, Value>),
102}
103
104#[derive(Debug)]
105pub enum DatumValueRef<'a> {
106    Value(&'a Value),
107    Dynamic(&'a dyn DatumLower<Value>),
108}
109
110#[derive(Debug)]
111pub enum DatumGraphRef<'a> {
112    Graph(&'a Graph),
113}
114
115#[derive(Debug)]
116pub enum DatumTupleOwned {
117    Tuple(Box<Tuple>),
118    Dynamic(Box<dyn OwnedTupleView<Value>>),
119}
120
121#[derive(Debug)]
122pub enum DatumSeqOwned {
123    List(Box<List>),
124    Bag(Box<Bag>),
125    Dynamic(Box<dyn OwnedSequenceView<Value>>),
126}
127
128#[derive(Debug)]
129pub enum DatumValueOwned {
130    Value(Value),
131}
132
133#[derive(Debug)]
134pub enum DatumGraphOwned {
135    Graph(Box<Graph>),
136}
137
138impl<'a> DatumCategory<'a> for Value {
139    fn category(&'a self) -> DatumCategoryRef<'a> {
140        match self {
141            Value::Null => DatumCategoryRef::Null,
142            Value::Missing => DatumCategoryRef::Missing,
143            Value::List(list) => DatumCategoryRef::Sequence(DatumSeqRef::List(list)),
144            Value::Bag(bag) => DatumCategoryRef::Sequence(DatumSeqRef::Bag(bag)),
145            Value::Tuple(tuple) => DatumCategoryRef::Tuple(DatumTupleRef::Tuple(tuple.as_ref())),
146            Value::Variant(doc) => doc.category(),
147            Value::Graph(graph) => DatumCategoryRef::Graph(DatumGraphRef::Graph(graph.as_ref())),
148            val => DatumCategoryRef::Scalar(DatumValueRef::Value(val)),
149        }
150    }
151
152    fn into_category(self) -> DatumCategoryOwned {
153        match self {
154            Value::Null => DatumCategoryOwned::Null,
155            Value::Missing => DatumCategoryOwned::Missing,
156            Value::List(list) => DatumCategoryOwned::Sequence(DatumSeqOwned::List(list)),
157            Value::Bag(bag) => DatumCategoryOwned::Sequence(DatumSeqOwned::Bag(bag)),
158            Value::Tuple(tuple) => DatumCategoryOwned::Tuple(DatumTupleOwned::Tuple(tuple)),
159            Value::Variant(doc) => doc.into_category(),
160            Value::Graph(graph) => DatumCategoryOwned::Graph(DatumGraphOwned::Graph(graph)),
161            val => DatumCategoryOwned::Scalar(DatumValueOwned::Value(val)),
162        }
163    }
164}
165
166pub struct RefFieldView<'a, DV: DatumValue<DV>> {
167    pub name: Option<&'a str>,
168    pub value: Cow<'a, DV>,
169}
170
171pub trait TupleDatum {
172    fn len(&self) -> usize;
173    fn is_empty(&self) -> bool {
174        self.len() == 0
175    }
176}
177
178pub trait RefTupleView<'a, DV: DatumValue<DV>>: TupleDatum + Debug {
179    fn get_val(&self, k: &BindingsName<'_>) -> Option<Cow<'a, DV>>;
180    fn tuple_fields_iter(&'a self) -> Box<dyn Iterator<Item = RefFieldView<'a, DV>> + 'a>;
181}
182
183pub struct OwnedFieldView<D: Datum<D>> {
184    pub name: String,
185    pub value: D,
186}
187
188pub trait OwnedTupleView<D: Datum<D>>: TupleDatum + Debug {
189    fn take_val(self, k: &BindingsName<'_>) -> Option<D>;
190    fn take_val_boxed(self: Box<Self>, k: &BindingsName<'_>) -> Option<D>;
191    fn into_iter_boxed(self: Box<Self>) -> Box<dyn Iterator<Item = OwnedFieldView<D>>>;
192}
193
194pub trait SequenceDatum {
195    fn is_ordered(&self) -> bool;
196    fn len(&self) -> usize;
197    fn is_empty(&self) -> bool {
198        self.len() == 0
199    }
200}
201
202pub trait RefSequenceView<'a, DV: DatumValue<DV>>: SequenceDatum + Debug {
203    fn get_val(&self, k: i64) -> Option<Cow<'a, DV>>;
204    fn into_iter(self) -> Box<dyn Iterator<Item = Cow<'a, DV>> + 'a>;
205}
206
207pub trait OwnedSequenceView<D: Datum<D>>: SequenceDatum + Debug {
208    fn take_val(self, k: i64) -> Option<D>;
209    fn take_val_boxed(self: Box<Self>, k: i64) -> Option<D>;
210    fn into_iter_boxed(self: Box<Self>) -> Box<dyn Iterator<Item = D>>;
211}
212
213impl TupleDatum for DatumTupleRef<'_> {
214    fn len(&self) -> usize {
215        match self {
216            DatumTupleRef::Tuple(tuple) => tuple.len(),
217            DatumTupleRef::Dynamic(dynamic) => dynamic.len(),
218            DatumTupleRef::Empty => 0,
219            DatumTupleRef::CoercedValue(_, _) => 1,
220            DatumTupleRef::SingleKey(_, _) => 1,
221            DatumTupleRef::Bindings(map) => map.len(),
222        }
223    }
224}
225
226impl<'a> RefTupleView<'a, Value> for DatumTupleRef<'a> {
227    fn get_val(&self, k: &BindingsName<'_>) -> Option<Cow<'a, Value>> {
228        match self {
229            DatumTupleRef::Tuple(tuple) => Tuple::get(tuple, k).map(Cow::Borrowed),
230            DatumTupleRef::Dynamic(dynamic) => dynamic.get_val(k),
231            DatumTupleRef::Empty => None,
232            DatumTupleRef::CoercedValue(idx, v) => {
233                if k.matcher().matches(&format!("_{idx}")) {
234                    Some(Cow::Borrowed(v))
235                } else {
236                    None
237                }
238            }
239            DatumTupleRef::SingleKey(key, v) => {
240                if k.matcher().matches(key.as_ref()) {
241                    Some(Cow::Borrowed(v))
242                } else {
243                    None
244                }
245            }
246            DatumTupleRef::Bindings(map) => {
247                let m = k.matcher();
248                map.iter()
249                    .find_map(|(k, &v)| m.matches(k).then_some(Cow::Borrowed(v)))
250            }
251        }
252    }
253
254    fn tuple_fields_iter(&'a self) -> Box<dyn Iterator<Item = RefFieldView<'a, Value>> + 'a> {
255        Box::new(IntoIterator::into_iter(self))
256    }
257}
258
259impl<'a> IntoIterator for &'a DatumTupleRef<'a> {
260    type Item = RefFieldView<'a, Value>;
261    type IntoIter = DatumTupleRefIterator<'a>;
262
263    fn into_iter(self) -> Self::IntoIter {
264        match self {
265            DatumTupleRef::Tuple(t) => DatumTupleRefIterator::Tuple(t.pairs()),
266            DatumTupleRef::Empty => DatumTupleRefIterator::Empty,
267            DatumTupleRef::Dynamic(d) => DatumTupleRefIterator::Dynamic(d.tuple_fields_iter()),
268            DatumTupleRef::CoercedValue(idx, value) => {
269                DatumTupleRefIterator::CoercedValue(Some((*idx, value)))
270            }
271            DatumTupleRef::SingleKey(key, value) => {
272                DatumTupleRefIterator::SingleKey(Some((key.as_ref(), value)))
273            }
274            DatumTupleRef::Bindings(m) => {
275                DatumTupleRefIterator::Dynamic(Box::new(m.iter().map(|(k, &v)| RefFieldView {
276                    name: Some(k.as_ref()),
277                    value: Cow::Borrowed(v),
278                })))
279            }
280        }
281    }
282}
283
284pub enum DatumTupleRefIterator<'a> {
285    Empty,
286    Tuple(PairsIter<'a>),
287    Dynamic(Box<dyn Iterator<Item = RefFieldView<'a, Value>> + 'a>),
288    CoercedValue(Option<(usize, &'a Value)>),
289    SingleKey(Option<(&'a str, &'a Value)>),
290}
291
292impl<'a> Iterator for DatumTupleRefIterator<'a> {
293    type Item = RefFieldView<'a, Value>;
294
295    fn next(&mut self) -> Option<Self::Item> {
296        match self {
297            DatumTupleRefIterator::Tuple(t) => t.next().map(|(name, value)| RefFieldView {
298                name: Some(name),
299                value: Cow::Borrowed(value),
300            }),
301            DatumTupleRefIterator::Empty => None,
302            DatumTupleRefIterator::CoercedValue(payload) => {
303                payload.take().map(|(_, value)| RefFieldView {
304                    name: None,
305                    value: Cow::Borrowed(value),
306                })
307            }
308            DatumTupleRefIterator::Dynamic(d) => d.next(),
309            DatumTupleRefIterator::SingleKey(payload) => {
310                payload.take().map(|(key, value)| RefFieldView {
311                    name: Some(key),
312                    value: Cow::Borrowed(value),
313                })
314            }
315        }
316    }
317}
318
319impl TupleDatum for DatumTupleOwned {
320    fn len(&self) -> usize {
321        match self {
322            DatumTupleOwned::Tuple(tuple) => tuple.len(),
323            DatumTupleOwned::Dynamic(dynamic) => dynamic.len(),
324        }
325    }
326}
327
328impl OwnedTupleView<Value> for DatumTupleOwned {
329    fn take_val(self, k: &BindingsName<'_>) -> Option<Value> {
330        match self {
331            DatumTupleOwned::Tuple(tuple) => Tuple::take_val(*tuple, k),
332            DatumTupleOwned::Dynamic(dynamic) => dynamic.take_val_boxed(k),
333        }
334    }
335
336    fn take_val_boxed(self: Box<Self>, k: &BindingsName<'_>) -> Option<Value> {
337        (*self).take_val(k)
338    }
339
340    fn into_iter_boxed(self: Box<Self>) -> Box<dyn Iterator<Item = OwnedFieldView<Value>>> {
341        Box::new((*self).into_iter())
342    }
343}
344
345impl SequenceDatum for DatumSeqRef<'_> {
346    fn is_ordered(&self) -> bool {
347        match self {
348            DatumSeqRef::List(_) => true,
349            DatumSeqRef::Bag(_) => false,
350            DatumSeqRef::Dynamic(boxed) => boxed.is_ordered(),
351        }
352    }
353
354    fn len(&self) -> usize {
355        match self {
356            DatumSeqRef::List(l) => l.len(),
357            DatumSeqRef::Bag(b) => b.len(),
358            DatumSeqRef::Dynamic(boxed) => boxed.len(),
359        }
360    }
361}
362
363impl<'a> RefSequenceView<'a, Value> for DatumSeqRef<'a> {
364    fn get_val(&self, k: i64) -> Option<Cow<'a, Value>> {
365        match self {
366            DatumSeqRef::List(l) => List::get(l, k).map(Cow::Borrowed),
367            DatumSeqRef::Bag(_) => None,
368            DatumSeqRef::Dynamic(boxed) => boxed.get_val(k),
369        }
370    }
371
372    fn into_iter(self) -> Box<dyn Iterator<Item = Cow<'a, Value>> + 'a> {
373        match self {
374            DatumSeqRef::List(l) => Box::new(l.iter().map(Cow::Borrowed)),
375            DatumSeqRef::Bag(b) => Box::new(b.iter().map(Cow::Borrowed)),
376            DatumSeqRef::Dynamic(_boxed) => todo!("&dyn RefSequenceView into_iter"),
377        }
378    }
379}
380
381impl SequenceDatum for DatumSeqOwned {
382    fn is_ordered(&self) -> bool {
383        match self {
384            DatumSeqOwned::List(_) => true,
385            DatumSeqOwned::Bag(_) => false,
386            DatumSeqOwned::Dynamic(boxed) => boxed.is_ordered(),
387        }
388    }
389
390    fn len(&self) -> usize {
391        match self {
392            DatumSeqOwned::List(l) => l.len(),
393            DatumSeqOwned::Bag(b) => b.len(),
394            DatumSeqOwned::Dynamic(boxed) => boxed.len(),
395        }
396    }
397}
398
399impl OwnedSequenceView<Value> for DatumSeqOwned {
400    fn take_val(self, k: i64) -> Option<Value> {
401        match self {
402            DatumSeqOwned::List(l) => l.take_val(k),
403            DatumSeqOwned::Bag(_) => None,
404            DatumSeqOwned::Dynamic(boxed) => boxed.take_val_boxed(k),
405        }
406    }
407
408    fn take_val_boxed(self: Box<Self>, k: i64) -> Option<Value> {
409        self.take_val(k)
410    }
411
412    fn into_iter_boxed(self: Box<Self>) -> Box<dyn Iterator<Item = Value>> {
413        Box::new((*self).into_iter())
414    }
415}
416
417impl IntoIterator for DatumTupleOwned {
418    type Item = OwnedFieldView<Value>;
419    type IntoIter = DatumTupleOwnedIterator;
420
421    fn into_iter(self) -> Self::IntoIter {
422        match self {
423            DatumTupleOwned::Tuple(t) => DatumTupleOwnedIterator::Tuple(t.into_pairs()),
424            DatumTupleOwned::Dynamic(d) => DatumTupleOwnedIterator::Dynamic(d.into_iter_boxed()),
425        }
426    }
427}
428
429pub enum DatumTupleOwnedIterator {
430    Tuple(PairsIntoIter),
431    Dynamic(Box<dyn Iterator<Item = OwnedFieldView<Value>>>),
432}
433
434impl Iterator for DatumTupleOwnedIterator {
435    type Item = OwnedFieldView<Value>;
436
437    fn next(&mut self) -> Option<Self::Item> {
438        match self {
439            DatumTupleOwnedIterator::Tuple(t) => {
440                t.next().map(|(name, value)| OwnedFieldView { name, value })
441            }
442            DatumTupleOwnedIterator::Dynamic(d) => d.next(),
443        }
444    }
445}
446
447impl IntoIterator for DatumSeqOwned {
448    type Item = Value;
449    type IntoIter = DatumSeqOwnedIterator;
450
451    fn into_iter(self) -> Self::IntoIter {
452        match self {
453            DatumSeqOwned::List(l) => DatumSeqOwnedIterator::List(l.into_iter()),
454            DatumSeqOwned::Bag(b) => DatumSeqOwnedIterator::Bag(b.into_iter()),
455            DatumSeqOwned::Dynamic(d) => DatumSeqOwnedIterator::Dynamic(d.into_iter_boxed()),
456        }
457    }
458}
459
460pub enum DatumSeqOwnedIterator {
461    List(ListIntoIterator),
462    Bag(BagIntoIterator),
463    Dynamic(Box<dyn Iterator<Item = Value>>),
464}
465
466impl Iterator for DatumSeqOwnedIterator {
467    type Item = Value;
468
469    fn next(&mut self) -> Option<Self::Item> {
470        match self {
471            DatumSeqOwnedIterator::List(l) => l.next(),
472            DatumSeqOwnedIterator::Bag(b) => b.next(),
473            DatumSeqOwnedIterator::Dynamic(d) => d.next(),
474        }
475    }
476}
477
478impl Datum<Value> for DatumValueRef<'_> {
479    #[inline]
480    fn is_null(&self) -> bool {
481        match self {
482            DatumValueRef::Value(v) => v.is_null(),
483            DatumValueRef::Dynamic(d) => d.is_null(),
484        }
485    }
486
487    #[inline]
488    fn is_missing(&self) -> bool {
489        match self {
490            DatumValueRef::Value(v) => v.is_missing(),
491            DatumValueRef::Dynamic(d) => d.is_missing(),
492        }
493    }
494
495    #[inline]
496    fn is_sequence(&self) -> bool {
497        match self {
498            DatumValueRef::Value(v) => v.is_sequence(),
499            DatumValueRef::Dynamic(d) => d.is_sequence(),
500        }
501    }
502
503    #[inline]
504    fn is_ordered(&self) -> bool {
505        match self {
506            DatumValueRef::Value(v) => v.is_ordered(),
507            DatumValueRef::Dynamic(d) => d.is_ordered(),
508        }
509    }
510}
511
512impl Datum<Value> for DatumValueOwned {
513    #[inline]
514    fn is_null(&self) -> bool {
515        match self {
516            DatumValueOwned::Value(v) => v.is_null(),
517        }
518    }
519
520    #[inline]
521    fn is_missing(&self) -> bool {
522        match self {
523            DatumValueOwned::Value(v) => v.is_missing(),
524        }
525    }
526
527    #[inline]
528    fn is_sequence(&self) -> bool {
529        match self {
530            DatumValueOwned::Value(v) => v.is_sequence(),
531        }
532    }
533
534    #[inline]
535    fn is_ordered(&self) -> bool {
536        match self {
537            DatumValueOwned::Value(v) => v.is_ordered(),
538        }
539    }
540}
541
542impl DatumLower<Value> for DatumValueOwned {
543    #[inline]
544    fn into_lower(self) -> DatumLowerResult<Value> {
545        match self {
546            DatumValueOwned::Value(v) => v.into_lower(),
547        }
548    }
549
550    #[inline]
551    fn into_lower_boxed(self: Box<Self>) -> DatumLowerResult<Value> {
552        match *self {
553            DatumValueOwned::Value(v) => v.into_lower(),
554        }
555    }
556
557    #[inline]
558    fn lower(&self) -> DatumLowerResult<Cow<'_, Value>> {
559        match self {
560            DatumValueOwned::Value(v) => v.lower(),
561        }
562    }
563}