vortex_array/scalar/
scalar_value.rs1use std::cmp::Ordering;
7use std::fmt::Display;
8use std::fmt::Formatter;
9
10use itertools::Itertools;
11use vortex_buffer::BufferString;
12use vortex_buffer::ByteBuffer;
13use vortex_dtype::DType;
14use vortex_error::vortex_panic;
15
16use crate::scalar::DecimalValue;
17use crate::scalar::PValue;
19
20#[derive(Debug, Clone, PartialEq, Eq, Hash)]
25pub enum ScalarValue {
26 Bool(bool),
28 Primitive(PValue),
30 Decimal(DecimalValue),
32 Utf8(BufferString),
34 Binary(ByteBuffer),
36 List(Vec<Option<ScalarValue>>),
38 }
44
45impl ScalarValue {
46 pub fn zero_value(dtype: &DType) -> Self {
67 match dtype {
68 DType::Null => vortex_panic!("Null dtype has no zero value"),
69 DType::Bool(_) => Self::Bool(false),
70 DType::Primitive(ptype, _) => Self::Primitive(PValue::zero(ptype)),
71 DType::Decimal(dt, ..) => Self::Decimal(DecimalValue::zero(dt)),
72 DType::Utf8(_) => Self::Utf8(BufferString::empty()),
73 DType::Binary(_) => Self::Binary(ByteBuffer::empty()),
74 DType::List(..) => Self::List(vec![]),
75 DType::FixedSizeList(edt, size, _) => {
76 let elements = (0..*size).map(|_| Some(Self::zero_value(edt))).collect();
77 Self::List(elements)
78 }
79 DType::Struct(fields, _) => {
80 let field_values = fields
81 .fields()
82 .map(|f| Some(Self::zero_value(&f)))
83 .collect();
84 Self::List(field_values)
85 }
86 DType::Extension(ext_dtype) => Self::zero_value(ext_dtype.storage_dtype()), }
88 }
89
90 pub fn default_value(dtype: &DType) -> Option<Self> {
97 if dtype.is_nullable() {
98 return None;
99 }
100
101 Some(match dtype {
102 DType::Null => vortex_panic!("Null dtype has no zero value"),
103 DType::Bool(_) => Self::Bool(false),
104 DType::Primitive(ptype, _) => Self::Primitive(PValue::zero(ptype)),
105 DType::Decimal(dt, ..) => Self::Decimal(DecimalValue::zero(dt)),
106 DType::Utf8(_) => Self::Utf8(BufferString::empty()),
107 DType::Binary(_) => Self::Binary(ByteBuffer::empty()),
108 DType::List(..) => Self::List(vec![]),
109 DType::FixedSizeList(edt, size, _) => {
110 let elements = (0..*size).map(|_| Self::default_value(edt)).collect();
111 Self::List(elements)
112 }
113 DType::Struct(fields, _) => {
114 let field_values = fields.fields().map(|f| Self::default_value(&f)).collect();
115 Self::List(field_values)
116 }
117 DType::Extension(ext_dtype) => Self::default_value(ext_dtype.storage_dtype())?, })
119 }
120}
121
122impl PartialOrd for ScalarValue {
123 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
124 match (self, other) {
125 (ScalarValue::Bool(a), ScalarValue::Bool(b)) => a.partial_cmp(b),
126 (ScalarValue::Primitive(a), ScalarValue::Primitive(b)) => a.partial_cmp(b),
127 (ScalarValue::Decimal(a), ScalarValue::Decimal(b)) => a.partial_cmp(b),
128 (ScalarValue::Utf8(a), ScalarValue::Utf8(b)) => a.partial_cmp(b),
129 (ScalarValue::Binary(a), ScalarValue::Binary(b)) => a.partial_cmp(b),
130 (ScalarValue::List(a), ScalarValue::List(b)) => a.partial_cmp(b),
131 _ => None,
133 }
134 }
135}
136
137impl Display for ScalarValue {
138 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
139 match self {
140 ScalarValue::Bool(b) => write!(f, "{}", b),
141 ScalarValue::Primitive(p) => write!(f, "{}", p),
142 ScalarValue::Decimal(d) => write!(f, "{}", d),
143 ScalarValue::Utf8(s) => {
144 let bufstr = s.as_str();
145 let str_len = bufstr.chars().count();
146
147 if str_len > 10 {
148 let prefix = String::from_iter(bufstr.chars().take(5));
149 let suffix = String::from_iter(bufstr.chars().skip(str_len - 5));
150
151 write!(f, "\"{prefix}..{suffix}\"")
152 } else {
153 write!(f, "\"{bufstr}\"")
154 }
155 }
156 ScalarValue::Binary(b) => {
157 if b.len() > 10 {
158 write!(
159 f,
160 "{}..{}",
161 to_hex(&b[0..5]),
162 to_hex(&b[b.len() - 5..b.len()]),
163 )
164 } else {
165 write!(f, "{}", to_hex(b))
166 }
167 }
168 ScalarValue::List(elements) => {
169 write!(f, "[")?;
170 for (i, element) in elements.iter().enumerate() {
171 if i > 0 {
172 write!(f, ", ")?;
173 }
174 match element {
175 None => write!(f, "null")?,
176 Some(e) => write!(f, "{}", e)?,
177 }
178 }
179 write!(f, "]")
180 } }
183 }
184}
185
186fn to_hex(slice: &[u8]) -> String {
188 slice
189 .iter()
190 .format_with("", |f, b| b(&format_args!("{f:02x}")))
191 .to_string()
192}