1use crate::filter::SlicesIterator;
21use arrow_array::*;
22use arrow_data::transform::MutableArrayData;
23use arrow_schema::ArrowError;
24
25pub fn zip(
85 mask: &BooleanArray,
86 truthy: &dyn Datum,
87 falsy: &dyn Datum,
88) -> Result<ArrayRef, ArrowError> {
89 let (truthy, truthy_is_scalar) = truthy.get();
90 let (falsy, falsy_is_scalar) = falsy.get();
91
92 if truthy.data_type() != falsy.data_type() {
93 return Err(ArrowError::InvalidArgumentError(
94 "arguments need to have the same data type".into(),
95 ));
96 }
97
98 if truthy_is_scalar && truthy.len() != 1 {
99 return Err(ArrowError::InvalidArgumentError(
100 "scalar arrays must have 1 element".into(),
101 ));
102 }
103 if !truthy_is_scalar && truthy.len() != mask.len() {
104 return Err(ArrowError::InvalidArgumentError(
105 "all arrays should have the same length".into(),
106 ));
107 }
108 if falsy_is_scalar && falsy.len() != 1 {
109 return Err(ArrowError::InvalidArgumentError(
110 "scalar arrays must have 1 element".into(),
111 ));
112 }
113 if !falsy_is_scalar && falsy.len() != mask.len() {
114 return Err(ArrowError::InvalidArgumentError(
115 "all arrays should have the same length".into(),
116 ));
117 }
118
119 let falsy = falsy.to_data();
120 let truthy = truthy.to_data();
121
122 let mut mutable = MutableArrayData::new(vec![&truthy, &falsy], false, truthy.len());
123
124 let mut filled = 0;
129
130 SlicesIterator::new(mask).for_each(|(start, end)| {
131 if start > filled {
133 if falsy_is_scalar {
134 for _ in filled..start {
135 mutable.extend(1, 0, 1);
137 }
138 } else {
139 mutable.extend(1, filled, start);
140 }
141 }
142 if truthy_is_scalar {
144 for _ in start..end {
145 mutable.extend(0, 0, 1);
147 }
148 } else {
149 mutable.extend(0, start, end);
150 }
151 filled = end;
152 });
153 if filled < mask.len() {
155 if falsy_is_scalar {
156 for _ in filled..mask.len() {
157 mutable.extend(1, 0, 1);
159 }
160 } else {
161 mutable.extend(1, filled, mask.len());
162 }
163 }
164
165 let data = mutable.freeze();
166 Ok(make_array(data))
167}
168
169#[cfg(test)]
170mod test {
171 use super::*;
172
173 #[test]
174 fn test_zip_kernel_one() {
175 let a = Int32Array::from(vec![Some(5), None, Some(7), None, Some(1)]);
176 let b = Int32Array::from(vec![None, Some(3), Some(6), Some(7), Some(3)]);
177 let mask = BooleanArray::from(vec![true, true, false, false, true]);
178 let out = zip(&mask, &a, &b).unwrap();
179 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
180 let expected = Int32Array::from(vec![Some(5), None, Some(6), Some(7), Some(1)]);
181 assert_eq!(actual, &expected);
182 }
183
184 #[test]
185 fn test_zip_kernel_two() {
186 let a = Int32Array::from(vec![Some(5), None, Some(7), None, Some(1)]);
187 let b = Int32Array::from(vec![None, Some(3), Some(6), Some(7), Some(3)]);
188 let mask = BooleanArray::from(vec![false, false, true, true, false]);
189 let out = zip(&mask, &a, &b).unwrap();
190 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
191 let expected = Int32Array::from(vec![None, Some(3), Some(7), None, Some(3)]);
192 assert_eq!(actual, &expected);
193 }
194
195 #[test]
196 fn test_zip_kernel_scalar_falsy_1() {
197 let a = Int32Array::from(vec![Some(5), None, Some(7), None, Some(1)]);
198
199 let fallback = Scalar::new(Int32Array::from_value(42, 1));
200
201 let mask = BooleanArray::from(vec![true, true, false, false, true]);
202 let out = zip(&mask, &a, &fallback).unwrap();
203 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
204 let expected = Int32Array::from(vec![Some(5), None, Some(42), Some(42), Some(1)]);
205 assert_eq!(actual, &expected);
206 }
207
208 #[test]
209 fn test_zip_kernel_scalar_falsy_2() {
210 let a = Int32Array::from(vec![Some(5), None, Some(7), None, Some(1)]);
211
212 let fallback = Scalar::new(Int32Array::from_value(42, 1));
213
214 let mask = BooleanArray::from(vec![false, false, true, true, false]);
215 let out = zip(&mask, &a, &fallback).unwrap();
216 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
217 let expected = Int32Array::from(vec![Some(42), Some(42), Some(7), None, Some(42)]);
218 assert_eq!(actual, &expected);
219 }
220
221 #[test]
222 fn test_zip_kernel_scalar_truthy_1() {
223 let a = Int32Array::from(vec![Some(5), None, Some(7), None, Some(1)]);
224
225 let fallback = Scalar::new(Int32Array::from_value(42, 1));
226
227 let mask = BooleanArray::from(vec![true, true, false, false, true]);
228 let out = zip(&mask, &fallback, &a).unwrap();
229 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
230 let expected = Int32Array::from(vec![Some(42), Some(42), Some(7), None, Some(42)]);
231 assert_eq!(actual, &expected);
232 }
233
234 #[test]
235 fn test_zip_kernel_scalar_truthy_2() {
236 let a = Int32Array::from(vec![Some(5), None, Some(7), None, Some(1)]);
237
238 let fallback = Scalar::new(Int32Array::from_value(42, 1));
239
240 let mask = BooleanArray::from(vec![false, false, true, true, false]);
241 let out = zip(&mask, &fallback, &a).unwrap();
242 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
243 let expected = Int32Array::from(vec![Some(5), None, Some(42), Some(42), Some(1)]);
244 assert_eq!(actual, &expected);
245 }
246
247 #[test]
248 fn test_zip_kernel_scalar_both() {
249 let scalar_truthy = Scalar::new(Int32Array::from_value(42, 1));
250 let scalar_falsy = Scalar::new(Int32Array::from_value(123, 1));
251
252 let mask = BooleanArray::from(vec![true, true, false, false, true]);
253 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
254 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
255 let expected = Int32Array::from(vec![Some(42), Some(42), Some(123), Some(123), Some(42)]);
256 assert_eq!(actual, &expected);
257 }
258
259 #[test]
260 fn test_zip_kernel_scalar_none_1() {
261 let scalar_truthy = Scalar::new(Int32Array::from_value(42, 1));
262 let scalar_falsy = Scalar::new(Int32Array::new_null(1));
263
264 let mask = BooleanArray::from(vec![true, true, false, false, true]);
265 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
266 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
267 let expected = Int32Array::from(vec![Some(42), Some(42), None, None, Some(42)]);
268 assert_eq!(actual, &expected);
269 }
270
271 #[test]
272 fn test_zip_kernel_scalar_none_2() {
273 let scalar_truthy = Scalar::new(Int32Array::from_value(42, 1));
274 let scalar_falsy = Scalar::new(Int32Array::new_null(1));
275
276 let mask = BooleanArray::from(vec![false, false, true, true, false]);
277 let out = zip(&mask, &scalar_truthy, &scalar_falsy).unwrap();
278 let actual = out.as_any().downcast_ref::<Int32Array>().unwrap();
279 let expected = Int32Array::from(vec![None, None, Some(42), Some(42), None]);
280 assert_eq!(actual, &expected);
281 }
282}