vortex_dtype/
nullability.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use std::fmt::Display;
5use std::fmt::Formatter;
6use std::ops::BitOr;
7use std::ops::BitOrAssign;
8
9/// Whether an instance of a DType can be `null or not
10#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
11pub enum Nullability {
12    /// Instances of this DType are guaranteed to be non-nullable
13    #[default]
14    NonNullable,
15    /// Instances of this DType may contain a null value
16    Nullable,
17}
18
19impl Nullability {
20    /// Returns `true` if the nullability is [`Nullable`](Self::Nullable), otherwise returns
21    /// `false`.
22    ///
23    /// # Examples
24    ///
25    /// ```
26    /// use vortex_dtype::Nullability::*;
27    ///
28    /// assert!(!NonNullable.is_nullable());
29    /// assert!(Nullable.is_nullable());
30    /// ```
31    pub fn is_nullable(&self) -> bool {
32        match self {
33            Nullability::NonNullable => false,
34            Nullability::Nullable => true,
35        }
36    }
37}
38
39impl BitOr for Nullability {
40    type Output = Nullability;
41
42    #[inline]
43    fn bitor(self, rhs: Self) -> Self::Output {
44        match (self, rhs) {
45            (Self::NonNullable, Self::NonNullable) => Self::NonNullable,
46            _ => Self::Nullable,
47        }
48    }
49}
50
51impl BitOrAssign for Nullability {
52    fn bitor_assign(&mut self, rhs: Self) {
53        *self = *self | rhs
54    }
55}
56
57impl From<bool> for Nullability {
58    #[inline]
59    fn from(value: bool) -> Self {
60        if value {
61            Self::Nullable
62        } else {
63            Self::NonNullable
64        }
65    }
66}
67
68impl From<Nullability> for bool {
69    #[inline]
70    fn from(value: Nullability) -> Self {
71        match value {
72            Nullability::NonNullable => false,
73            Nullability::Nullable => true,
74        }
75    }
76}
77
78impl Display for Nullability {
79    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
80        match self {
81            Self::NonNullable => write!(f, ""),
82            Self::Nullable => write!(f, "?"),
83        }
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90
91    #[test]
92    fn test_nullability_default() {
93        let default = Nullability::default();
94        assert_eq!(default, Nullability::NonNullable);
95    }
96
97    #[test]
98    fn test_nullability_bitor() {
99        use Nullability::*;
100
101        // NonNullable | NonNullable = NonNullable
102        assert_eq!(NonNullable | NonNullable, NonNullable);
103
104        // NonNullable | Nullable = Nullable
105        assert_eq!(NonNullable | Nullable, Nullable);
106
107        // Nullable | NonNullable = Nullable
108        assert_eq!(Nullable | NonNullable, Nullable);
109
110        // Nullable | Nullable = Nullable
111        assert_eq!(Nullable | Nullable, Nullable);
112    }
113
114    #[test]
115    fn test_nullability_from_bool() {
116        assert_eq!(Nullability::from(false), Nullability::NonNullable);
117        assert_eq!(Nullability::from(true), Nullability::Nullable);
118    }
119
120    #[test]
121    fn test_bool_from_nullability() {
122        assert!(!bool::from(Nullability::NonNullable));
123        assert!(bool::from(Nullability::Nullable));
124    }
125
126    #[test]
127    fn test_nullability_roundtrip() {
128        // Test roundtrip conversion bool -> Nullability -> bool
129        assert!(!bool::from(Nullability::from(false)));
130        assert!(bool::from(Nullability::from(true)));
131
132        // Test roundtrip conversion Nullability -> bool -> Nullability
133        assert_eq!(
134            Nullability::from(bool::from(Nullability::NonNullable)),
135            Nullability::NonNullable
136        );
137        assert_eq!(
138            Nullability::from(bool::from(Nullability::Nullable)),
139            Nullability::Nullable
140        );
141    }
142
143    #[test]
144    fn test_nullability_chained_bitor() {
145        // Test chaining multiple BitOr operations
146        let result = Nullability::NonNullable | Nullability::NonNullable | Nullability::NonNullable;
147        assert_eq!(result, Nullability::NonNullable);
148
149        let result = Nullability::NonNullable | Nullability::Nullable | Nullability::NonNullable;
150        assert_eq!(result, Nullability::Nullable);
151    }
152}