tantivy_columnar/
value.rs

1use common::DateTime;
2
3use crate::InvalidData;
4
5#[derive(Copy, Clone, PartialEq, Debug)]
6pub enum NumericalValue {
7    I64(i64),
8    U64(u64),
9    F64(f64),
10}
11
12impl NumericalValue {
13    pub fn numerical_type(&self) -> NumericalType {
14        match self {
15            NumericalValue::I64(_) => NumericalType::I64,
16            NumericalValue::U64(_) => NumericalType::U64,
17            NumericalValue::F64(_) => NumericalType::F64,
18        }
19    }
20}
21
22impl From<u64> for NumericalValue {
23    fn from(val: u64) -> NumericalValue {
24        NumericalValue::U64(val)
25    }
26}
27
28impl From<i64> for NumericalValue {
29    fn from(val: i64) -> Self {
30        NumericalValue::I64(val)
31    }
32}
33
34impl From<f64> for NumericalValue {
35    fn from(val: f64) -> Self {
36        NumericalValue::F64(val)
37    }
38}
39
40#[derive(Clone, Copy, Debug, Default, Hash, Eq, PartialEq)]
41#[repr(u8)]
42pub enum NumericalType {
43    #[default]
44    I64 = 0,
45    U64 = 1,
46    F64 = 2,
47}
48
49impl NumericalType {
50    pub fn to_code(self) -> u8 {
51        self as u8
52    }
53
54    pub fn try_from_code(code: u8) -> Result<NumericalType, InvalidData> {
55        match code {
56            0 => Ok(NumericalType::I64),
57            1 => Ok(NumericalType::U64),
58            2 => Ok(NumericalType::F64),
59            _ => Err(InvalidData),
60        }
61    }
62}
63
64/// We voluntarily avoid using `Into` here to keep this
65/// implementation quirk as private as possible.
66///
67/// # Panics
68/// This coercion trait actually panics if it is used
69/// to convert a loose types to a stricter type.
70///
71/// The level is strictness is somewhat arbitrary.
72/// - i64
73/// - u64
74/// - f64.
75pub(crate) trait Coerce {
76    fn coerce(numerical_value: NumericalValue) -> Self;
77}
78
79impl Coerce for i64 {
80    fn coerce(value: NumericalValue) -> Self {
81        match value {
82            NumericalValue::I64(val) => val,
83            NumericalValue::U64(val) => val as i64,
84            NumericalValue::F64(_) => unreachable!(),
85        }
86    }
87}
88
89impl Coerce for u64 {
90    fn coerce(value: NumericalValue) -> Self {
91        match value {
92            NumericalValue::I64(val) => val as u64,
93            NumericalValue::U64(val) => val,
94            NumericalValue::F64(_) => unreachable!(),
95        }
96    }
97}
98
99impl Coerce for f64 {
100    fn coerce(value: NumericalValue) -> Self {
101        match value {
102            NumericalValue::I64(val) => val as f64,
103            NumericalValue::U64(val) => val as f64,
104            NumericalValue::F64(val) => val,
105        }
106    }
107}
108
109impl Coerce for DateTime {
110    fn coerce(value: NumericalValue) -> Self {
111        let timestamp_micros = i64::coerce(value);
112        DateTime::from_timestamp_nanos(timestamp_micros)
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use super::NumericalType;
119
120    #[test]
121    fn test_numerical_type_code() {
122        let mut num_numerical_type = 0;
123        for code in u8::MIN..=u8::MAX {
124            if let Ok(numerical_type) = NumericalType::try_from_code(code) {
125                assert_eq!(numerical_type.to_code(), code);
126                num_numerical_type += 1;
127            }
128        }
129        assert_eq!(num_numerical_type, 3);
130    }
131}