vortex_array/scalar/
scalar_value.rs1use std::fmt::Display;
7use std::fmt::Formatter;
8
9use itertools::Itertools;
10use vortex_buffer::BufferString;
11use vortex_buffer::ByteBuffer;
12use vortex_error::VortexExpect;
13use vortex_error::vortex_panic;
14
15use crate::dtype::DType;
16use crate::scalar::DecimalValue;
17use crate::scalar::PValue;
18use crate::scalar::Scalar;
19use crate::scalar::UnionValue;
20
21#[derive(Debug, Clone, PartialEq, Eq, Hash)]
26pub enum ScalarValue {
27 Bool(bool),
29 Primitive(PValue),
31 Decimal(DecimalValue),
33 Utf8(BufferString),
35 Binary(ByteBuffer),
37 Tuple(Vec<Option<ScalarValue>>),
41 Union(UnionValue),
43 Variant(Box<Scalar>),
45}
46
47impl ScalarValue {
48 pub(super) fn zero_value(dtype: &DType) -> Self {
50 Self::try_zero_value(dtype)
51 .unwrap_or_else(|| vortex_panic!("{dtype} has no non-null zero value"))
52 }
53
54 pub(super) fn try_zero_value(dtype: &DType) -> Option<Self> {
56 Some(match dtype {
57 DType::Null => return None,
58 DType::Bool(_) => Self::Bool(false),
59 DType::Primitive(ptype, _) => Self::Primitive(PValue::zero(ptype)),
60 DType::Decimal(dt, ..) => Self::Decimal(DecimalValue::zero(dt)),
61 DType::Utf8(_) => Self::Utf8(BufferString::empty()),
62 DType::Binary(_) => Self::Binary(ByteBuffer::empty()),
63 DType::List(..) => Self::Tuple(vec![]),
64 DType::FixedSizeList(edt, size, _) => {
65 let elements = (0..*size)
66 .map(|_| Self::try_zero_value(edt).map(Some))
67 .collect::<Option<Vec<_>>>()?;
68 Self::Tuple(elements)
69 }
70 DType::Struct(fields, _) => {
71 let field_values = fields
72 .fields()
73 .map(|f| Self::try_zero_value(&f).map(Some))
74 .collect::<Option<Vec<_>>>()?;
75 Self::Tuple(field_values)
76 }
77 DType::Union(variants, _) => {
78 let child_dtype = variants
79 .variant_by_index(0)
80 .vortex_expect("union must have at least one variant");
81 let child_value = Self::try_zero_value(&child_dtype)?;
82
83 Self::Union(UnionValue::new(
84 variants.child_index_to_tag(0),
85 Some(child_value),
86 ))
87 }
88 DType::Variant(_) => Self::Variant(Box::new(Scalar::null(DType::Null))),
89 DType::Extension(ext_dtype) => {
90 Self::try_zero_value(ext_dtype.storage_dtype())?
94 }
95 })
96 }
97
98 pub(super) fn try_default_value(dtype: &DType) -> Option<Option<Self>> {
103 if dtype.is_nullable() {
104 return Some(None);
105 }
106
107 let value = match dtype {
108 DType::Null => return Some(None),
109 DType::Bool(_) => Self::Bool(false),
110 DType::Primitive(ptype, _) => Self::Primitive(PValue::zero(ptype)),
111 DType::Decimal(dt, ..) => Self::Decimal(DecimalValue::zero(dt)),
112 DType::Utf8(_) => Self::Utf8(BufferString::empty()),
113 DType::Binary(_) => Self::Binary(ByteBuffer::empty()),
114 DType::List(..) => Self::Tuple(vec![]),
115 DType::FixedSizeList(edt, size, _) => {
116 let elements = (0..*size)
117 .map(|_| Self::try_default_value(edt))
118 .collect::<Option<Vec<_>>>()?;
119 Self::Tuple(elements)
120 }
121 DType::Struct(fields, _) => {
122 let field_values = fields
123 .fields()
124 .map(|field| Self::try_default_value(&field))
125 .collect::<Option<Vec<_>>>()?;
126 Self::Tuple(field_values)
127 }
128 DType::Union(variants, _) => {
129 let child_dtype = variants
130 .variant_by_index(0)
131 .vortex_expect("union must have at least one variant");
132 let child_value = Self::try_default_value(&child_dtype)?;
133
134 Self::Union(UnionValue::new(variants.child_index_to_tag(0), child_value))
135 }
136 DType::Variant(_) => Self::Variant(Box::new(Scalar::null(DType::Null))),
137 DType::Extension(ext_dtype) => {
138 Self::try_default_value(ext_dtype.storage_dtype())??
142 }
143 };
144
145 Some(Some(value))
146 }
147}
148
149impl Display for ScalarValue {
150 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
151 match self {
152 ScalarValue::Bool(b) => write!(f, "{b}"),
153 ScalarValue::Primitive(p) => write!(f, "{p}"),
154 ScalarValue::Decimal(d) => write!(f, "{d}"),
155 ScalarValue::Utf8(s) => {
156 let bufstr = s.as_str();
157 let str_len = bufstr.chars().count();
158
159 if str_len > 10 {
160 let prefix = String::from_iter(bufstr.chars().take(5));
161 let suffix = String::from_iter(bufstr.chars().skip(str_len - 5));
162
163 write!(f, "\"{prefix}..{suffix}\"")
164 } else {
165 write!(f, "\"{bufstr}\"")
166 }
167 }
168 ScalarValue::Binary(b) => {
169 if b.len() > 10 {
170 write!(
171 f,
172 "{}..{}",
173 to_hex(&b[0..5]),
174 to_hex(&b[b.len() - 5..b.len()]),
175 )
176 } else {
177 write!(f, "{}", to_hex(b))
178 }
179 }
180 ScalarValue::Tuple(elements) => {
181 write!(f, "[")?;
182 for (i, element) in elements.iter().enumerate() {
183 if i > 0 {
184 write!(f, ", ")?;
185 }
186 match element {
187 None => write!(f, "null")?,
188 Some(e) => write!(f, "{}", e)?,
189 }
190 }
191 write!(f, "]")
192 }
193 ScalarValue::Union(value) => {
194 write!(f, "union@{}(", value.type_id())?;
195 match value.child_value() {
196 Some(value) => write!(f, "{value}"),
197 None => write!(f, "null"),
198 }?;
199 write!(f, ")")
200 }
201 ScalarValue::Variant(value) => write!(f, "{value}"),
202 }
203 }
204}
205
206fn to_hex(slice: &[u8]) -> String {
208 slice
209 .iter()
210 .format_with("", |f, b| b(&format_args!("{f:02x}")))
211 .to_string()
212}