1use std::sync::Arc;
7
8use vortex_buffer::BufferString;
9use vortex_buffer::ByteBuffer;
10use vortex_error::VortexExpect;
11use vortex_error::VortexResult;
12use vortex_error::vortex_bail;
13use vortex_error::vortex_ensure_eq;
14use vortex_error::vortex_err;
15use vortex_error::vortex_panic;
16
17use crate::dtype::DType;
18use crate::dtype::DecimalDType;
19use crate::dtype::NativePType;
20use crate::dtype::Nullability;
21use crate::dtype::PType;
22use crate::dtype::UnionVariants;
23use crate::dtype::extension::ExtDType;
24use crate::dtype::extension::ExtDTypeRef;
25use crate::dtype::extension::ExtVTable;
26use crate::scalar::DecimalValue;
27use crate::scalar::PValue;
28use crate::scalar::Scalar;
29use crate::scalar::ScalarValue;
30use crate::scalar::UnionValue;
31
32impl Scalar {
34 pub fn bool(value: bool, nullability: Nullability) -> Self {
36 unsafe { Self::new_unchecked(DType::Bool(nullability), Some(ScalarValue::Bool(value))) }
38 }
39
40 pub fn primitive<T: NativePType + Into<PValue>>(value: T, nullability: Nullability) -> Self {
42 Self::primitive_value(value.into(), T::PTYPE, nullability)
43 }
44
45 pub fn primitive_value(value: PValue, ptype: PType, nullability: Nullability) -> Self {
50 if value.ptype() != ptype {
51 return Self::try_new(
52 DType::Primitive(ptype, nullability),
53 Some(ScalarValue::Primitive(value)),
54 )
55 .vortex_expect("unable to construct a primitive `Scalar`");
56 }
57
58 unsafe {
60 Self::new_unchecked(
61 DType::Primitive(ptype, nullability),
62 Some(ScalarValue::Primitive(value)),
63 )
64 }
65 }
66
67 pub fn decimal(
69 value: DecimalValue,
70 decimal_type: DecimalDType,
71 nullability: Nullability,
72 ) -> Self {
73 Self::try_new(
74 DType::Decimal(decimal_type, nullability),
75 Some(ScalarValue::Decimal(value)),
76 )
77 .vortex_expect("unable to construct a decimal `Scalar`")
78 }
79
80 pub fn utf8<B>(str: B, nullability: Nullability) -> Self
86 where
87 B: Into<BufferString>,
88 {
89 Self::try_utf8(str, nullability).unwrap()
90 }
91
92 pub fn try_utf8<B>(
98 str: B,
99 nullability: Nullability,
100 ) -> Result<Self, <B as TryInto<BufferString>>::Error>
101 where
102 B: TryInto<BufferString>,
103 {
104 let value = ScalarValue::Utf8(str.try_into()?);
105
106 Ok(unsafe { Self::new_unchecked(DType::Utf8(nullability), Some(value)) })
108 }
109
110 pub fn binary(buffer: impl Into<ByteBuffer>, nullability: Nullability) -> Self {
112 unsafe {
114 Self::new_unchecked(
115 DType::Binary(nullability),
116 Some(ScalarValue::Binary(buffer.into())),
117 )
118 }
119 }
120
121 pub fn list(
128 element_dtype: impl Into<Arc<DType>>,
129 children: Vec<Scalar>,
130 nullability: Nullability,
131 ) -> Self {
132 Self::create_list(element_dtype, children, nullability, ListKind::Variable)
133 }
134
135 pub fn list_empty(element_dtype: Arc<DType>, nullability: Nullability) -> Self {
137 Self::create_list(element_dtype, vec![], nullability, ListKind::Variable)
138 }
139
140 pub fn fixed_size_list(
147 element_dtype: impl Into<Arc<DType>>,
148 children: Vec<Scalar>,
149 nullability: Nullability,
150 ) -> Self {
151 Self::create_list(element_dtype, children, nullability, ListKind::FixedSize)
152 }
153
154 pub fn map(dtype: DType, entries: impl IntoIterator<Item = (Scalar, Scalar)>) -> Self {
160 Self::try_map(dtype, entries).vortex_expect("unable to construct a map `Scalar`")
161 }
162
163 pub fn try_map(
170 dtype: DType,
171 entries: impl IntoIterator<Item = (Scalar, Scalar)>,
172 ) -> VortexResult<Self> {
173 let map = dtype
174 .as_map_opt()
175 .ok_or_else(|| vortex_error::vortex_err!("Expected map dtype, found {dtype}"))?;
176 let key_dtype = map.key_dtype();
177 let value_dtype = map.value_dtype();
178
179 let entries = entries
180 .into_iter()
181 .enumerate()
182 .map(|(index, (key, value))| {
183 if key.dtype() != &key_dtype {
184 vortex_bail!(
185 "map entry {index} expected key dtype {key_dtype}, got {}",
186 key.dtype()
187 );
188 }
189 if value.dtype() != &value_dtype {
190 vortex_bail!(
191 "map entry {index} expected value dtype {value_dtype}, got {}",
192 value.dtype()
193 );
194 }
195
196 Ok(Some(ScalarValue::Tuple(vec![
197 key.into_value(),
198 value.into_value(),
199 ])))
200 })
201 .collect::<VortexResult<Vec<_>>>()?;
202
203 Self::try_new(dtype, Some(ScalarValue::Tuple(entries)))
204 }
205
206 fn create_list(
208 element_dtype: impl Into<Arc<DType>>,
209 children: Vec<Scalar>,
210 nullability: Nullability,
211 list_kind: ListKind,
212 ) -> Self {
213 let element_dtype = element_dtype.into();
214
215 let children: Vec<Option<ScalarValue>> = children
216 .into_iter()
217 .map(|child| {
218 if child.dtype() != &*element_dtype {
219 vortex_panic!(
220 "tried to create list of {} with values of type {}",
221 element_dtype,
222 child.dtype()
223 );
224 }
225 child.into_value()
226 })
227 .collect();
228 let size: u32 = children
229 .len()
230 .try_into()
231 .vortex_expect("tried to create a list that was too large");
232
233 let dtype = match list_kind {
234 ListKind::Variable => DType::List(element_dtype, nullability),
235 ListKind::FixedSize => DType::FixedSizeList(element_dtype, size, nullability),
236 };
237
238 Self::try_new(dtype, Some(ScalarValue::Tuple(children)))
239 .vortex_expect("unable to construct a list `Scalar`")
240 }
241
242 pub fn extension<V: ExtVTable + Default>(options: V::Metadata, storage_scalar: Scalar) -> Self {
244 let ext_dtype = ExtDType::<V>::try_new(options, storage_scalar.dtype().clone())
245 .vortex_expect("Failed to create extension dtype");
246
247 Self::extension_ref(ext_dtype.erased(), storage_scalar)
248 }
249
250 pub fn extension_ref(ext_dtype: ExtDTypeRef, storage_scalar: Scalar) -> Self {
256 assert_eq!(ext_dtype.storage_dtype(), storage_scalar.dtype());
257
258 Self::try_new(DType::Extension(ext_dtype), storage_scalar.into_value())
259 .vortex_expect("unable to construct an extension `Scalar`")
260 }
261
262 pub fn union(
274 variants: UnionVariants,
275 type_id: u8,
276 child: Scalar,
277 nullability: Nullability,
278 ) -> VortexResult<Self> {
279 let child_index = variants.tag_to_child_index(type_id).ok_or_else(|| {
280 vortex_err!(
281 "union type ID {type_id} is not present in {:?}",
282 variants.type_ids()
283 )
284 })?;
285
286 let expected_dtype = variants
287 .variant_by_index(child_index)
288 .vortex_expect("type ID resolved to a valid child index");
289
290 vortex_ensure_eq!(
291 child.dtype(),
292 &expected_dtype,
293 "union type ID {type_id} selects a different child dtype"
294 );
295
296 Self::try_new(
297 DType::Union(variants, nullability),
298 Some(ScalarValue::Union(UnionValue::new(
299 type_id,
300 child.into_value(),
301 ))),
302 )
303 }
304
305 pub fn variant(value: Scalar) -> Self {
311 Self::try_new(
312 DType::Variant(Nullability::NonNullable),
313 Some(ScalarValue::Variant(Box::new(value))),
314 )
315 .vortex_expect("unable to construct a variant `Scalar`")
316 }
317}
318
319enum ListKind {
321 Variable,
323 FixedSize,
325}