partiql_value/
boxed_variant.rs1use dyn_clone::DynClone;
2use dyn_hash::DynHash;
3use partiql_common::pretty::PrettyDoc;
4use std::any::Any;
5use std::borrow::Cow;
6use std::cmp::Ordering;
7use std::error::Error;
8
9use crate::datum::{Datum, DatumCategoryOwned, DatumCategoryRef, DatumLower};
10use crate::Value;
11use pretty::{DocAllocator, DocBuilder};
12use std::fmt::{Debug, Display};
13
14pub type BoxedVariantError = Box<dyn Error>;
15
16pub type BoxedVariantResult<T> = Result<T, BoxedVariantError>;
17pub type BoxedVariantValueIntoIterator =
18 Box<dyn Iterator<Item = BoxedVariantResult<DynBoxedVariant>>>;
19
20pub type BoxedVariantValueIter<'a> =
21 Box<dyn 'a + Iterator<Item = BoxedVariantResult<&'a DynBoxedVariant>>>;
22
23pub trait DynBoxedVariantTypeFactory {
24 fn to_dyn_type_tag(self) -> BoxedVariantTypeTag;
25}
26
27pub type BoxedVariantTypeTag = Box<dyn BoxedVariantType>;
28pub trait BoxedVariantType: Debug + DynClone {
29 fn construct(&self, bytes: Vec<u8>) -> BoxedVariantResult<DynBoxedVariant>;
30 fn name(&self) -> &'static str;
31
32 fn value_eq(&self, l: &DynBoxedVariant, r: &DynBoxedVariant) -> bool;
33
34 fn value_eq_param(
35 &self,
36 l: &DynBoxedVariant,
37 r: &DynBoxedVariant,
38 nulls_eq: bool,
39 nans_eq: bool,
40 ) -> bool;
41}
42
43dyn_clone::clone_trait_object!(BoxedVariantType);
44
45impl Eq for dyn BoxedVariantType {}
46impl PartialEq for dyn BoxedVariantType {
47 fn eq(&self, other: &Self) -> bool {
48 self.name() == other.name()
49 }
50}
51impl PartialOrd for dyn BoxedVariantType {
52 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
53 Some(self.cmp(other))
54 }
55}
56impl Ord for dyn BoxedVariantType {
57 fn cmp(&self, other: &Self) -> Ordering {
58 self.name().cmp(other.name())
59 }
60}
61
62impl<T> DynBoxedVariantTypeFactory for T
63where
64 T: BoxedVariantType + 'static,
65{
66 fn to_dyn_type_tag(self) -> BoxedVariantTypeTag {
67 Box::new(self)
68 }
69}
70
71pub type DynBoxedVariant = Box<dyn BoxedVariant>;
72#[cfg_attr(feature = "serde", typetag::serde)]
73pub trait BoxedVariant:
74 Display + Debug + DynHash + DynClone + Datum<Value> + DatumLower<Value>
75{
76 fn type_tag(&self) -> BoxedVariantTypeTag;
77
78 fn as_any(&self) -> &dyn Any;
79 fn into_dyn_iter(self: Box<Self>) -> BoxedVariantResult<BoxedVariantValueIntoIterator>;
80
81 fn category(&self) -> DatumCategoryRef<'_>;
82
83 fn into_category(self: Box<Self>) -> DatumCategoryOwned;
84}
85
86dyn_hash::hash_trait_object!(BoxedVariant);
87dyn_clone::clone_trait_object!(BoxedVariant);
88
89impl Eq for DynBoxedVariant {}
90impl PartialEq for DynBoxedVariant {
91 fn eq(&self, other: &Self) -> bool {
92 self.type_tag() == other.type_tag() && self.type_tag().value_eq(self, other)
93 }
94}
95impl PartialOrd for DynBoxedVariant {
96 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
97 Some(self.cmp(other))
98 }
99}
100impl Ord for DynBoxedVariant {
101 fn cmp(&self, other: &Self) -> Ordering {
102 let missing = |_| Cow::Owned(Value::Missing);
103 self.type_tag().cmp(&other.type_tag()).then_with(|| {
104 self.lower()
105 .unwrap_or_else(missing)
106 .cmp(&other.lower().unwrap_or_else(missing))
107 })
108 }
109}
110
111impl PrettyDoc for DynBoxedVariant {
112 fn pretty_doc<'b, D, A>(&'b self, arena: &'b D) -> DocBuilder<'b, D, A>
113 where
114 D: DocAllocator<'b, A>,
115 D::Doc: Clone,
116 A: Clone,
117 {
118 arena.text(format!("{self}"))
120 }
121}