Skip to main content

partiql_value/
variant.rs

1use crate::boxed_variant::{
2    BoxedVariant, BoxedVariantError, BoxedVariantResult, BoxedVariantTypeTag,
3    BoxedVariantValueIntoIterator, BoxedVariantValueIter, DynBoxedVariant,
4};
5use crate::datum::{
6    Datum, DatumCategory, DatumCategoryOwned, DatumCategoryRef, DatumLower, DatumLowerResult,
7    DatumValue,
8};
9
10use crate::{Comparable, EqualityValue, NullSortedValue, NullableEq, Value};
11use delegate::delegate;
12use partiql_common::pretty::{pretty_surrounded_doc, PrettyDoc};
13use pretty::{DocAllocator, DocBuilder};
14#[cfg(feature = "serde")]
15use serde::{Deserialize, Serialize};
16
17use std::borrow::Cow;
18use std::cmp::Ordering;
19use std::fmt::Debug;
20use std::hash::Hash;
21
22use thiserror::Error;
23
24#[derive(Clone, Debug)]
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26pub struct Variant {
27    variant: DynBoxedVariant,
28}
29
30impl Variant {
31    pub fn new<B: Into<Vec<u8>>>(
32        contents: B,
33        type_tag: BoxedVariantTypeTag,
34    ) -> BoxedVariantResult<Self> {
35        let variant = Unparsed::new(contents, type_tag)?.parse()?;
36        Ok(Self { variant })
37    }
38
39    pub fn type_tag(&self) -> BoxedVariantTypeTag {
40        self.variant.type_tag()
41    }
42
43    pub fn dyn_variant(&self) -> &DynBoxedVariant {
44        &self.variant
45    }
46}
47
48impl<T> From<T> for Variant
49where
50    T: BoxedVariant + 'static,
51{
52    fn from(variant: T) -> Self {
53        let variant = Box::new(variant) as DynBoxedVariant;
54        Self { variant }
55    }
56}
57
58impl From<DynBoxedVariant> for Variant {
59    fn from(variant: DynBoxedVariant) -> Self {
60        Self { variant }
61    }
62}
63
64impl DatumValue<Value> for Variant {}
65
66impl DatumLower<Value> for Variant {
67    fn into_lower(self) -> DatumLowerResult<Value> {
68        self.variant.into_lower_boxed()
69    }
70
71    fn into_lower_boxed(self: Box<Self>) -> DatumLowerResult<Value> {
72        self.into_lower()
73    }
74
75    fn lower(&self) -> DatumLowerResult<Cow<'_, Value>> {
76        self.variant.lower()
77    }
78}
79
80impl<'a> DatumCategory<'a> for Variant {
81    fn category(&'a self) -> DatumCategoryRef<'a> {
82        self.variant.category()
83    }
84
85    fn into_category(self) -> DatumCategoryOwned {
86        self.variant.into_category()
87    }
88}
89
90#[derive(Debug, Clone)]
91pub struct Unparsed {
92    contents: Vec<u8>,
93    type_tag: BoxedVariantTypeTag,
94}
95
96impl Unparsed {
97    pub fn new<B: Into<Vec<u8>>>(
98        contents: B,
99        type_tag: BoxedVariantTypeTag,
100    ) -> BoxedVariantResult<Self> {
101        Ok(Unparsed {
102            contents: contents.into(),
103            type_tag,
104        })
105    }
106}
107
108#[derive(Error, Debug)]
109#[non_exhaustive]
110pub enum VariantError {
111    #[error("Latent Type Error for Boxed Document {0}")]
112    LatentTypeError(BoxedVariantError, BoxedVariantTypeTag),
113}
114
115pub type VariantResult<T> = Result<T, VariantError>;
116
117impl Unparsed {
118    fn parse(self) -> VariantResult<DynBoxedVariant> {
119        let Self { contents, type_tag } = self;
120        match type_tag.construct(contents) {
121            Ok(doc) => Ok(doc),
122            Err(err) => Err(VariantError::LatentTypeError(err, type_tag.clone())),
123        }
124    }
125}
126
127#[allow(dead_code)]
128pub struct VariantIter<'a>(BoxedVariantValueIter<'a>);
129
130impl IntoIterator for Variant {
131    type Item = BoxedVariantResult<Variant>;
132    type IntoIter = VariantIntoIterator;
133
134    fn into_iter(self) -> VariantIntoIterator {
135        let iter = self.variant.into_dyn_iter().expect("into_dyn_iter");
136        VariantIntoIterator(iter)
137    }
138}
139
140pub struct VariantIntoIterator(BoxedVariantValueIntoIterator);
141
142impl Iterator for VariantIntoIterator {
143    type Item = BoxedVariantResult<Variant>;
144
145    #[inline]
146    fn next(&mut self) -> Option<Self::Item> {
147        self.0.next().map(|res| res.map(Variant::from))
148    }
149
150    #[inline]
151    fn size_hint(&self) -> (usize, Option<usize>) {
152        self.0.size_hint()
153    }
154}
155
156impl Datum<Value> for Variant {
157    delegate! {
158        to self.variant {
159            fn is_null(&self) -> bool;
160            fn is_missing(&self) -> bool;
161            fn is_absent(&self) -> bool;
162            fn is_present(&self) -> bool;
163            fn is_sequence(&self) -> bool;
164            fn is_ordered(&self) -> bool;
165        }
166    }
167}
168
169impl PartialOrd<Self> for Variant {
170    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
171        Some(self.cmp(other))
172    }
173}
174
175impl Ord for Variant {
176    fn cmp(&self, other: &Self) -> Ordering {
177        let l = &self.variant;
178        let r = &other.variant;
179        l.type_tag().cmp(&r.type_tag()).then_with(|| l.cmp(r))
180    }
181}
182
183impl PartialEq<Self> for Variant {
184    fn eq(&self, other: &Self) -> bool {
185        let lty = self.variant.type_tag();
186        let rty = other.variant.type_tag();
187        lty.eq(&rty) && self.variant.eq(&other.variant)
188    }
189}
190
191impl Eq for Variant {}
192
193impl Hash for Variant {
194    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
195        self.variant.type_tag().name().hash(state);
196        self.variant.hash(state);
197    }
198}
199
200impl<const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
201    for EqualityValue<'_, NULLS_EQUAL, NAN_EQUAL, Variant>
202{
203    #[inline(always)]
204    fn eq(&self, other: &Self) -> Value {
205        let l = &self.0.variant;
206        let r = &other.0.variant;
207        let lty = l.type_tag();
208        let rty = r.type_tag();
209
210        let res = lty == rty && lty.value_eq_param(l, r, NULLS_EQUAL, NAN_EQUAL);
211        Value::Boolean(res)
212    }
213
214    #[inline(always)]
215    fn eqg(&self, rhs: &Self) -> Value {
216        let wrap = EqualityValue::<'_, true, { NAN_EQUAL }, _>;
217        NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
218    }
219}
220
221impl PrettyDoc for Variant {
222    fn pretty_doc<'b, D, A>(&'b self, arena: &'b D) -> DocBuilder<'b, D, A>
223    where
224        D: DocAllocator<'b, A>,
225        D::Doc: Clone,
226        A: Clone,
227    {
228        let doc = self.variant.pretty_doc(arena);
229
230        pretty_surrounded_doc(doc, "`", "`", arena)
231        // TODO eventually support suffixing quoted documents with `::<type>`
232        //let ty = self.variant.type_tag().name();
233        //.append(arena.text("::"))
234        //.append(arena.text(ty))
235    }
236}
237
238impl Comparable for Variant {
239    fn is_comparable_to(&self, rhs: &Self) -> bool {
240        self.variant.type_tag().name() == rhs.variant.type_tag().name()
241    }
242}
243
244impl<const NULLS_FIRST: bool> Ord for NullSortedValue<'_, NULLS_FIRST, Variant> {
245    fn cmp(&self, other: &Self) -> Ordering {
246        let wrap = NullSortedValue::<{ NULLS_FIRST }, _>;
247
248        let l = self.0.lower().expect("lower");
249        let l = wrap(l.as_ref());
250        let r = other.0.lower().expect("lower");
251        let r = wrap(r.as_ref());
252
253        l.cmp(&r)
254    }
255}