vortex_vector/decimal/
scalar.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_dtype::{DecimalTypeUpcast, NativeDecimalType, PrecisionScale, i256};
5use vortex_error::VortexExpect;
6
7use crate::decimal::DVectorMut;
8use crate::{Scalar, ScalarOps, VectorMut, VectorMutOps};
9
10/// Represents a decimal scalar value.
11#[derive(Debug)]
12pub enum DecimalScalar {
13    /// 8-bit decimal scalar.
14    I8(DScalar<i8>),
15    /// 16-bit decimal scalar.
16    I16(DScalar<i16>),
17    /// 32-bit decimal scalar.
18    I32(DScalar<i32>),
19    /// 64-bit decimal scalar.
20    I64(DScalar<i64>),
21    /// 128-bit decimal scalar.
22    I128(DScalar<i128>),
23    /// 256-bit decimal scalar.
24    I256(DScalar<i256>),
25}
26
27impl ScalarOps for DecimalScalar {
28    fn is_valid(&self) -> bool {
29        match self {
30            DecimalScalar::I8(v) => v.is_valid(),
31            DecimalScalar::I16(v) => v.is_valid(),
32            DecimalScalar::I32(v) => v.is_valid(),
33            DecimalScalar::I64(v) => v.is_valid(),
34            DecimalScalar::I128(v) => v.is_valid(),
35            DecimalScalar::I256(v) => v.is_valid(),
36        }
37    }
38
39    fn repeat(&self, n: usize) -> VectorMut {
40        match self {
41            DecimalScalar::I8(v) => v.repeat(n),
42            DecimalScalar::I16(v) => v.repeat(n),
43            DecimalScalar::I32(v) => v.repeat(n),
44            DecimalScalar::I64(v) => v.repeat(n),
45            DecimalScalar::I128(v) => v.repeat(n),
46            DecimalScalar::I256(v) => v.repeat(n),
47        }
48    }
49}
50
51impl From<DecimalScalar> for Scalar {
52    fn from(val: DecimalScalar) -> Self {
53        Scalar::Decimal(val)
54    }
55}
56
57/// Represents a decimal scalar value with a specific native decimal type.
58#[derive(Clone, Debug, PartialEq, Eq, Hash)]
59pub struct DScalar<D> {
60    ps: PrecisionScale<D>,
61    value: Option<D>,
62}
63
64impl<D: NativeDecimalType> DScalar<D> {
65    /// Creates a new decimal scalar with the given precision/scale and value.
66    ///
67    /// Returns `None` if the value is not valid for the given precision/scale.
68    pub fn maybe_new(ps: PrecisionScale<D>, value: Option<D>) -> Option<Self> {
69        Some(match value {
70            None => Self { ps, value: None },
71            Some(v) => {
72                if !ps.is_valid(v) {
73                    return None;
74                }
75                Self { ps, value: Some(v) }
76            }
77        })
78    }
79
80    /// Creates a new decimal scalar with the given precision/scale and value without validation.
81    ///
82    /// # Safety
83    ///
84    /// The caller must ensure that the value is valid for the given precision/scale.
85    pub unsafe fn new_unchecked(ps: PrecisionScale<D>, value: Option<D>) -> Self {
86        Self { ps, value }
87    }
88}
89
90impl<D: NativeDecimalType> ScalarOps for DScalar<D> {
91    fn is_valid(&self) -> bool {
92        self.value.is_some()
93    }
94
95    fn repeat(&self, n: usize) -> VectorMut {
96        let mut vec = DVectorMut::with_capacity(self.ps, n);
97        match &self.value {
98            None => vec.append_nulls(n),
99            Some(v) => vec.try_append_n(*v, n).vortex_expect("known to fit"),
100        }
101        vec.into()
102    }
103}
104
105impl<D: NativeDecimalType> From<DScalar<D>> for Scalar {
106    fn from(value: DScalar<D>) -> Self {
107        Scalar::Decimal(D::upcast(value))
108    }
109}
110
111impl<D: NativeDecimalType> From<DScalar<D>> for DecimalScalar {
112    fn from(value: DScalar<D>) -> Self {
113        D::upcast(value)
114    }
115}
116
117impl DecimalTypeUpcast for DecimalScalar {
118    type Input<T: NativeDecimalType> = DScalar<T>;
119
120    fn from_i8(input: Self::Input<i8>) -> Self {
121        DecimalScalar::I8(input)
122    }
123
124    fn from_i16(input: Self::Input<i16>) -> Self {
125        DecimalScalar::I16(input)
126    }
127
128    fn from_i32(input: Self::Input<i32>) -> Self {
129        DecimalScalar::I32(input)
130    }
131
132    fn from_i64(input: Self::Input<i64>) -> Self {
133        DecimalScalar::I64(input)
134    }
135
136    fn from_i128(input: Self::Input<i128>) -> Self {
137        DecimalScalar::I128(input)
138    }
139
140    fn from_i256(input: Self::Input<i256>) -> Self {
141        DecimalScalar::I256(input)
142    }
143}