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 }
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}