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::Map(..) => Self::Tuple(vec![]),
65 DType::FixedSizeList(edt, size, _) => {
66 let elements = (0..*size)
67 .map(|_| Self::try_zero_value(edt).map(Some))
68 .collect::<Option<Vec<_>>>()?;
69 Self::Tuple(elements)
70 }
71 DType::Struct(fields, _) => {
72 let field_values = fields
73 .fields()
74 .map(|f| Self::try_zero_value(&f).map(Some))
75 .collect::<Option<Vec<_>>>()?;
76 Self::Tuple(field_values)
77 }
78 DType::Union(variants, _) => {
79 let child_dtype = variants
80 .variant_by_index(0)
81 .vortex_expect("union must have at least one variant");
82 let child_value = Self::try_zero_value(&child_dtype)?;
83
84 Self::Union(UnionValue::new(
85 variants.child_index_to_tag(0),
86 Some(child_value),
87 ))
88 }
89 DType::Variant(_) => Self::Variant(Box::new(Scalar::null(DType::Null))),
90 DType::Extension(ext_dtype) => {
91 Self::try_zero_value(ext_dtype.storage_dtype())?
95 }
96 })
97 }
98
99 pub(super) fn try_default_value(dtype: &DType) -> Option<Option<Self>> {
104 if dtype.is_nullable() {
105 return Some(None);
106 }
107
108 let value = match dtype {
109 DType::Null => return Some(None),
110 DType::Bool(_) => Self::Bool(false),
111 DType::Primitive(ptype, _) => Self::Primitive(PValue::zero(ptype)),
112 DType::Decimal(dt, ..) => Self::Decimal(DecimalValue::zero(dt)),
113 DType::Utf8(_) => Self::Utf8(BufferString::empty()),
114 DType::Binary(_) => Self::Binary(ByteBuffer::empty()),
115 DType::List(..) => Self::Tuple(vec![]),
116 DType::Map(..) => Self::Tuple(vec![]),
117 DType::FixedSizeList(edt, size, _) => {
118 let elements = (0..*size)
119 .map(|_| Self::try_default_value(edt))
120 .collect::<Option<Vec<_>>>()?;
121 Self::Tuple(elements)
122 }
123 DType::Struct(fields, _) => {
124 let field_values = fields
125 .fields()
126 .map(|field| Self::try_default_value(&field))
127 .collect::<Option<Vec<_>>>()?;
128 Self::Tuple(field_values)
129 }
130 DType::Union(variants, _) => {
131 let child_dtype = variants
132 .variant_by_index(0)
133 .vortex_expect("union must have at least one variant");
134 let child_value = Self::try_default_value(&child_dtype)?;
135
136 Self::Union(UnionValue::new(variants.child_index_to_tag(0), child_value))
137 }
138 DType::Variant(_) => Self::Variant(Box::new(Scalar::null(DType::Null))),
139 DType::Extension(ext_dtype) => {
140 Self::try_default_value(ext_dtype.storage_dtype())??
144 }
145 };
146
147 Some(Some(value))
148 }
149}
150
151impl Display for ScalarValue {
152 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
153 match self {
154 ScalarValue::Bool(b) => write!(f, "{b}"),
155 ScalarValue::Primitive(p) => write!(f, "{p}"),
156 ScalarValue::Decimal(d) => write!(f, "{d}"),
157 ScalarValue::Utf8(s) => {
158 let bufstr = s.as_str();
159 let str_len = bufstr.chars().count();
160
161 if str_len > 10 {
162 let prefix = String::from_iter(bufstr.chars().take(5));
163 let suffix = String::from_iter(bufstr.chars().skip(str_len - 5));
164
165 write!(f, "\"{prefix}..{suffix}\"")
166 } else {
167 write!(f, "\"{bufstr}\"")
168 }
169 }
170 ScalarValue::Binary(b) => {
171 if b.len() > 10 {
172 write!(
173 f,
174 "{}..{}",
175 to_hex(&b[0..5]),
176 to_hex(&b[b.len() - 5..b.len()]),
177 )
178 } else {
179 write!(f, "{}", to_hex(b))
180 }
181 }
182 ScalarValue::Tuple(elements) => {
183 write!(f, "[")?;
184 for (i, element) in elements.iter().enumerate() {
185 if i > 0 {
186 write!(f, ", ")?;
187 }
188 match element {
189 None => write!(f, "null")?,
190 Some(e) => write!(f, "{}", e)?,
191 }
192 }
193 write!(f, "]")
194 }
195 ScalarValue::Union(value) => {
196 write!(f, "union@{}(", value.type_id())?;
197 match value.child_value() {
198 Some(value) => write!(f, "{value}"),
199 None => write!(f, "null"),
200 }?;
201 write!(f, ")")
202 }
203 ScalarValue::Variant(value) => write!(f, "{value}"),
204 }
205 }
206}
207
208fn to_hex(slice: &[u8]) -> String {
210 slice
211 .iter()
212 .format_with("", |f, b| b(&format_args!("{f:02x}")))
213 .to_string()
214}