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)]
109pub enum VariantError {
110 #[error("Latent Type Error for Boxed Document {0}")]
111 LatentTypeError(BoxedVariantError, BoxedVariantTypeTag),
112}
113
114pub type VariantResult<T> = Result<T, VariantError>;
115
116impl Unparsed {
117 fn parse(self) -> VariantResult<DynBoxedVariant> {
118 let Self { contents, type_tag } = self;
119 match type_tag.construct(contents) {
120 Ok(doc) => Ok(doc),
121 Err(err) => Err(VariantError::LatentTypeError(err, type_tag.clone())),
122 }
123 }
124}
125
126#[allow(dead_code)]
127pub struct VariantIter<'a>(BoxedVariantValueIter<'a>);
128
129impl IntoIterator for Variant {
130 type Item = BoxedVariantResult<Variant>;
131 type IntoIter = VariantIntoIterator;
132
133 fn into_iter(self) -> VariantIntoIterator {
134 let iter = self.variant.into_dyn_iter().expect("into_dyn_iter");
135 VariantIntoIterator(iter)
136 }
137}
138
139pub struct VariantIntoIterator(BoxedVariantValueIntoIterator);
140
141impl Iterator for VariantIntoIterator {
142 type Item = BoxedVariantResult<Variant>;
143
144 #[inline]
145 fn next(&mut self) -> Option<Self::Item> {
146 self.0.next().map(|res| res.map(Variant::from))
147 }
148
149 #[inline]
150 fn size_hint(&self) -> (usize, Option<usize>) {
151 self.0.size_hint()
152 }
153}
154
155impl Datum<Value> for Variant {
156 delegate! {
157 to self.variant {
158 fn is_null(&self) -> bool;
159 fn is_missing(&self) -> bool;
160 fn is_absent(&self) -> bool;
161 fn is_present(&self) -> bool;
162 fn is_sequence(&self) -> bool;
163 fn is_ordered(&self) -> bool;
164 }
165 }
166}
167
168impl PartialOrd<Self> for Variant {
169 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
170 Some(self.cmp(other))
171 }
172}
173
174impl Ord for Variant {
175 fn cmp(&self, other: &Self) -> Ordering {
176 let l = &self.variant;
177 let r = &other.variant;
178 l.type_tag().cmp(&r.type_tag()).then_with(|| l.cmp(r))
179 }
180}
181
182impl PartialEq<Self> for Variant {
183 fn eq(&self, other: &Self) -> bool {
184 let lty = self.variant.type_tag();
185 let rty = other.variant.type_tag();
186 lty.eq(&rty) && self.variant.eq(&other.variant)
187 }
188}
189
190impl Eq for Variant {}
191
192impl Hash for Variant {
193 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
194 self.variant.type_tag().name().hash(state);
195 self.variant.hash(state);
196 }
197}
198
199impl<const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
200 for EqualityValue<'_, NULLS_EQUAL, NAN_EQUAL, Variant>
201{
202 #[inline(always)]
203 fn eq(&self, other: &Self) -> Value {
204 let l = &self.0.variant;
205 let r = &other.0.variant;
206 let lty = l.type_tag();
207 let rty = r.type_tag();
208
209 let res = lty == rty && lty.value_eq_param(l, r, NULLS_EQUAL, NAN_EQUAL);
210 Value::Boolean(res)
211 }
212
213 #[inline(always)]
214 fn eqg(&self, rhs: &Self) -> Value {
215 let wrap = EqualityValue::<'_, true, { NAN_EQUAL }, _>;
216 NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
217 }
218}
219
220impl PrettyDoc for Variant {
221 fn pretty_doc<'b, D, A>(&'b self, arena: &'b D) -> DocBuilder<'b, D, A>
222 where
223 D: DocAllocator<'b, A>,
224 D::Doc: Clone,
225 A: Clone,
226 {
227 let doc = self.variant.pretty_doc(arena);
228
229 pretty_surrounded_doc(doc, "`", "`", arena)
230 }
235}
236
237impl Comparable for Variant {
238 fn is_comparable_to(&self, rhs: &Self) -> bool {
239 self.variant.type_tag().name() == rhs.variant.type_tag().name()
240 }
241}
242
243impl<const NULLS_FIRST: bool> Ord for NullSortedValue<'_, NULLS_FIRST, Variant> {
244 fn cmp(&self, other: &Self) -> Ordering {
245 let wrap = NullSortedValue::<{ NULLS_FIRST }, _>;
246
247 let l = self.0.lower().expect("lower");
248 let l = wrap(l.as_ref());
249 let r = other.0.lower().expect("lower");
250 let r = wrap(r.as_ref());
251
252 l.cmp(&r)
253 }
254}