1mod nullvec_convert;
18mod nullvec_impl;
19mod nullvec_impl_aggregation;
20mod nullvec_impl_iter;
21
22mod nullvec_ops_primitive;
24mod nullvec_ops_nullable;
25
26mod nullvec_ops_vec;
28mod nullvec_ops_nullvec;
29
30mod nullvec_scalar;
32
33use algos::vec_ops::Elemwise;
34use traits::NullStorable;
35
36#[derive(Clone, Debug, PartialEq)]
38pub struct NullVec<T: NullStorable> {
39 data: Vec<T>,
40 mask: Option<Vec<bool>>,
42}
43
44fn maybe_null<T: NullStorable>(values: Vec<T>) -> (Vec<T>, Option<Vec<bool>>) {
45 if T::has_primitive_null() {
46 let mut not_null: Vec<T> = Vec::with_capacity(values.len());
47 let mut mask: Vec<bool> = Vec::with_capacity(values.len());
48 let mut has_null = false;
49
50 for v in values.into_iter() {
51 if v.is_null() {
52 not_null.push(T::default());
53 mask.push(true);
54 has_null = true;
55 } else {
56 not_null.push(v);
57 mask.push(false);
58 }
59 }
60 if has_null == true {
61 (not_null, Some(mask))
62 } else {
63 (not_null, None)
64 }
65 } else {
66 (values, None)
67 }
68
69}
70
71impl<T: NullStorable> NullVec<T> {
72 pub fn new(values: Vec<T>) -> Self {
91 let (not_null, mask) = maybe_null(values);
92
93 NullVec {
94 data: not_null,
95 mask: mask,
96 }
97 }
98
99 pub fn with_mask(values: Vec<T>, mask: Option<Vec<bool>>) -> Self {
123 let (not_null, null_mask) = maybe_null(values);
124 let new_mask = match (null_mask, mask) {
125 (Some(lmask), Some(rmask)) => Some(Elemwise::elemwise_oo(lmask, rmask, |x, y| x | y)),
126 (Some(lmask), None) => Some(lmask),
127 (None, Some(rmask)) => Some(rmask),
128 (None, None) => None,
129 };
130
131 NullVec {
132 data: not_null,
133 mask: new_mask,
134 }
135 }
136}
137
138
139#[cfg(test)]
140mod tests {
141
142 use std::f64;
143
144 use super::{NullVec, maybe_null};
145
146 #[test]
147 fn test_int() {
148 let values: Vec<usize> = vec![1, 2, 3];
149 let nvec = NullVec::new(values);
150 assert_eq!(nvec.data, vec![1, 2, 3]);
151 assert_eq!(nvec.mask, None);
152 }
153
154 #[test]
155 fn test_float() {
156 let values: Vec<f64> = vec![1.1, 1.2, 1.3];
157 let nvec = NullVec::new(values);
158 assert_eq!(nvec.data, vec![1.1, 1.2, 1.3]);
159 assert_eq!(nvec.mask, None);
160 }
161
162 #[test]
163 fn test_float_nan() {
164 let values: Vec<f64> = vec![1.1, f64::NAN, 1.3];
165 let nvec = NullVec::new(values);
166 assert_eq!(nvec.data, vec![1.1, 0., 1.3]);
167 assert_eq!(nvec.mask, Some(vec![false, true, false]));
168 }
169
170 #[test]
171 fn test_int_with_mask() {
172 let values: Vec<usize> = vec![1, 2, 3];
173 let nvec = NullVec::with_mask(values, Some(vec![true, false, false]));
174 assert_eq!(nvec.data, vec![1, 2, 3]);
175 assert_eq!(nvec.mask, Some(vec![true, false, false]));
176 }
177
178 #[test]
179 fn test_float_with_mask() {
180 let values: Vec<f64> = vec![1.1, f64::NAN, 1.3];
181 let nvec = NullVec::with_mask(values, Some(vec![true, false, false]));
182 assert_eq!(nvec.data, vec![1.1, 0., 1.3]);
183 assert_eq!(nvec.mask, Some(vec![true, true, false]));
184
185 let values: Vec<f64> = vec![1.1, f64::NAN, 1.3];
186 let nvec = NullVec::with_mask(values, None);
187 assert_eq!(nvec.data, vec![1.1, 0., 1.3]);
188 assert_eq!(nvec.mask, Some(vec![false, true, false]));
189 }
190
191 #[test]
192 fn test_maybe_null() {
193 let values: Vec<f64> = vec![1.1, f64::NAN, 1.3];
194 let (not_null, mask) = maybe_null(values);
195 assert_eq!(not_null, vec![1.1, 0., 1.3]);
196 assert_eq!(mask, Some(vec![false, true, false]));
197
198 let values: Vec<f64> = vec![1.1, 1.2, 1.3];
199 let (not_null, mask) = maybe_null(values);
200 assert_eq!(not_null, vec![1.1, 1.2, 1.3]);
201 assert_eq!(mask, None);
202 }
203}