vortex_array/arrays/primitive/
native_value.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use std::cmp::Ordering;
5
6use vortex_dtype::{NativePType, half};
7
8/// NativeValue serves as a wrapper type to allow us to implement Hash, Eq and other traits on all primitive types.
9///
10/// Rust does not define Hash/Eq for any of the float types due to the presence of
11/// NaN and +/- 0. We don't care about storing multiple NaNs or zeros in our dictionaries,
12/// so we define simple bit-wise Hash/Eq for the Value-wrapped versions of these types.
13#[repr(transparent)]
14#[derive(Copy, Clone, Debug)]
15pub struct NativeValue<T>(pub T);
16
17impl<T: NativePType> PartialEq<NativeValue<T>> for NativeValue<T> {
18    fn eq(&self, other: &NativeValue<T>) -> bool {
19        self.0.is_eq(other.0)
20    }
21}
22
23impl<T: NativePType> Eq for NativeValue<T> {}
24
25macro_rules! prim_value {
26    ($typ:ty) => {
27        impl core::hash::Hash for NativeValue<$typ> {
28            fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
29                self.0.hash(state);
30            }
31        }
32    };
33}
34
35impl<T: NativePType> PartialOrd<NativeValue<T>> for NativeValue<T> {
36    fn partial_cmp(&self, other: &NativeValue<T>) -> Option<Ordering> {
37        Some(self.0.total_compare(other.0))
38    }
39}
40
41macro_rules! float_value {
42    ($typ:ty) => {
43        impl core::hash::Hash for NativeValue<$typ> {
44            fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
45                self.0.to_bits().hash(state);
46            }
47        }
48    };
49}
50
51prim_value!(u8);
52prim_value!(u16);
53prim_value!(u32);
54prim_value!(u64);
55prim_value!(i8);
56prim_value!(i16);
57prim_value!(i32);
58prim_value!(i64);
59float_value!(half::f16);
60float_value!(f32);
61float_value!(f64);