nullvec/nullvec/
nullvec_convert.rs1use super::NullVec;
2use nullable::Nullable;
3use traits::NullStorable;
4
5impl<T: NullStorable> From<Vec<T>> for NullVec<T> {
6 fn from(values: Vec<T>) -> Self {
7 NullVec::new(values)
8 }
9}
10
11impl<'a> From<Vec<&'a str>> for NullVec<String> {
13 fn from(values: Vec<&'a str>) -> Self {
14 let string: Vec<String> = values.iter().map(|x| x.to_string()).collect();
15 string.into()
16 }
17}
18
19impl<T: NullStorable> From<Vec<Nullable<T>>> for NullVec<T> {
20 fn from(values: Vec<Nullable<T>>) -> Self {
21 let mut new_values: Vec<T> = Vec::with_capacity(values.len());
22 let mut new_mask: Vec<bool> = Vec::with_capacity(values.len());
23 let mut has_null: bool = false;
24 for v in values.into_iter() {
25 match v {
26 Nullable::Value(v) => {
27 new_values.push(v);
28 new_mask.push(false);
29 }
30 Nullable::Null => {
31 new_values.push(T::default());
32 new_mask.push(true);
33 has_null = true;
34 }
35 }
36 }
37 if has_null {
38 NullVec {
39 data: new_values,
40 mask: Some(new_mask),
41 }
42 } else {
43 NullVec {
44 data: new_values,
45 mask: None,
46 }
47 }
48 }
49}
50
51macro_rules! impl_from {
52 ($t:ident) => {
53 impl From<NullVec<$t>> for Vec<$t> {
54 fn from(values: NullVec<$t>) -> Vec<$t> {
55 match values.mask {
57 None => values.data,
58 _ => panic!("Unable to convert NaN to specified type")
60 }
61 }
62 }
63
64 impl From<NullVec<$t>> for Vec<Nullable<$t>> {
65 fn from(values: NullVec<$t>) -> Vec<Nullable<$t>> {
66 match values.mask {
68 None => values.data
69 .into_iter()
70 .map(|x| Nullable::Value(x))
71 .collect(),
72 Some(mask) => values.data
73 .into_iter()
74 .zip(mask.into_iter())
75 .map(|(x, m)| if m == true {
76 Nullable::Null
77 } else {
78 Nullable::Value(x)
79 })
80 .collect(),
81
82 }
83 }
84 }
85 }
86}
87macro_dispatch!(
88 impl_from,
89 i64,
90 i32,
91 i16,
92 i8,
93 isize,
94 u64,
95 u32,
96 u16,
97 u8,
98 usize,
99 f64,
100 f32,
101 bool,
102 String
103);
104
105
106#[cfg(test)]
107mod tests {
108
109 use std::f64;
110 use nullable::Nullable;
111 use nullvec::NullVec;
112
113 #[test]
114 fn test_float_conv_from_vec() {
115 let nv = NullVec::<f64>::from(vec![1., 2.]);
116 assert_eq!(nv.data, vec![1., 2.]);
117 assert_eq!(nv.mask, None);
118
119 let res = Vec::<f64>::from(nv);
120 assert_eq!(res, vec![1., 2.]);
121
122 let nv = NullVec::<f64>::from(vec![1., f64::NAN]);
123 assert_eq!(nv.data, vec![1., 0.]);
124 assert_eq!(nv.mask, Some(vec![false, true]));
125 }
126
127 #[test]
128 fn test_float_conv_from_vec_contains_null() {
129 let nv = NullVec::<f64>::from(vec![1., f64::NAN]);
130 assert_eq!(nv.data, vec![1.0f64, 0.]);
131 assert_eq!(nv.mask, Some(vec![false, true]));
132 }
133
134 #[test]
135 #[should_panic]
136 fn test_float_conv_from_vec_contains_null_panic() {
137 let nv = NullVec::<f64>::from(vec![1., f64::NAN]);
138 Vec::<f64>::from(nv);
140 }
141
142 #[test]
143 fn test_float_conv_from_nullablevec() {
144 let nv = NullVec::<f64>::from(vec![Nullable::Value(1.), Nullable::Value(2.)]);
145 assert_eq!(nv.data, vec![1., 2.]);
146 assert_eq!(nv.mask, None);
147
148 let res = Vec::<Nullable<f64>>::from(nv);
149 assert_eq!(res, vec![Nullable::Value(1.), Nullable::Value(2.)]);
150
151 let nv = NullVec::<f64>::from(vec![Nullable::Value(1.), Nullable::Null]);
152 assert_eq!(nv.data, vec![1., 0.]);
153 assert_eq!(nv.mask, Some(vec![false, true]));
154
155 let res = Vec::<Nullable<f64>>::from(nv);
156 assert_eq!(res, vec![Nullable::Value(1.), Nullable::Null]);
157 }
158
159 #[test]
160 fn test_string_conv_from_vec() {
161 let nv = NullVec::<String>::from(vec!["a".to_string(), "b".to_string()]);
162 assert_eq!(nv.data, vec!["a".to_string(), "b".to_string()]);
163 assert_eq!(nv.mask, None);
164
165 let res = Vec::<String>::from(nv);
166 assert_eq!(res, vec!["a".to_string(), "b".to_string()]);
167 }
168
169 #[test]
170 fn test_str_conv_from_vec() {
171 let nv = NullVec::<String>::from(vec!["a", "b"]);
172 assert_eq!(nv.data, vec!["a".to_string(), "b".to_string()]);
173 assert_eq!(nv.mask, None);
174
175 let res = Vec::<String>::from(nv);
176 assert_eq!(res, vec!["a".to_string(), "b".to_string()]);
177 }
178}