Skip to main content

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