1use vortex_dtype::DType;
10use vortex_error::vortex_panic;
11use vortex_mask::MaskMut;
12
13use crate::Vector;
14use crate::VectorMutOps;
15use crate::VectorOps;
16use crate::binaryview::BinaryVectorMut;
17use crate::binaryview::StringVectorMut;
18use crate::bool::BoolVectorMut;
19use crate::decimal::DecimalVectorMut;
20use crate::fixed_size_list::FixedSizeListVectorMut;
21use crate::listview::ListViewVectorMut;
22use crate::match_each_vector_mut;
23use crate::match_vector_pair;
24use crate::null::NullVectorMut;
25use crate::primitive::PrimitiveVectorMut;
26use crate::struct_::StructVectorMut;
27
28#[derive(Debug, Clone)]
38pub enum VectorMut {
39 Null(NullVectorMut),
41 Bool(BoolVectorMut),
43 Decimal(DecimalVectorMut),
50 Primitive(PrimitiveVectorMut),
57 String(StringVectorMut),
59 Binary(BinaryVectorMut),
61 List(ListViewVectorMut),
63 FixedSizeList(FixedSizeListVectorMut),
65 Struct(StructVectorMut),
67}
68
69impl VectorMut {
70 pub fn with_capacity(dtype: &DType, capacity: usize) -> Self {
72 match dtype {
73 DType::Null => NullVectorMut::new(0).into(),
74 DType::Bool(_) => BoolVectorMut::with_capacity(capacity).into(),
75 DType::Primitive(ptype, _) => {
76 PrimitiveVectorMut::with_capacity(*ptype, capacity).into()
77 }
78 DType::FixedSizeList(elem_dtype, list_size, _) => {
79 FixedSizeListVectorMut::with_capacity(elem_dtype, *list_size, capacity).into()
80 }
81 DType::Struct(struct_fields, _) => {
82 StructVectorMut::with_capacity(struct_fields, capacity).into()
83 }
84 DType::Decimal(decimal_dtype, _) => {
85 DecimalVectorMut::with_capacity(decimal_dtype, capacity).into()
86 }
87 DType::Utf8(..) => StringVectorMut::with_capacity(capacity).into(),
88 DType::Binary(..) => BinaryVectorMut::with_capacity(capacity).into(),
89 DType::Extension(ext) => VectorMut::with_capacity(ext.storage_dtype(), capacity),
90 DType::List(..) => ListViewVectorMut::with_capacity(dtype, capacity).into(),
91 }
92 }
93}
94
95impl VectorMutOps for VectorMut {
96 type Immutable = Vector;
97
98 fn len(&self) -> usize {
99 match_each_vector_mut!(self, |v| { v.len() })
100 }
101
102 fn validity(&self) -> &MaskMut {
103 match_each_vector_mut!(self, |v| { v.validity() })
104 }
105
106 fn capacity(&self) -> usize {
107 match_each_vector_mut!(self, |v| { v.capacity() })
108 }
109
110 fn reserve(&mut self, additional: usize) {
111 match_each_vector_mut!(self, |v| { v.reserve(additional) })
112 }
113
114 fn clear(&mut self) {
115 match_each_vector_mut!(self, |v| { v.clear() })
116 }
117
118 fn truncate(&mut self, len: usize) {
119 match_each_vector_mut!(self, |v| { v.truncate(len) })
120 }
121
122 fn extend_from_vector(&mut self, other: &Vector) {
123 match_vector_pair!(self, other, |a: VectorMut, b: Vector| {
124 a.extend_from_vector(b)
125 })
126 }
127
128 fn append_nulls(&mut self, n: usize) {
129 match_each_vector_mut!(self, |v| { v.append_nulls(n) })
130 }
131
132 fn append_zeros(&mut self, n: usize) {
133 match_each_vector_mut!(self, |v| { v.append_zeros(n) })
134 }
135
136 fn append_scalars(&mut self, scalar: &<Self::Immutable as VectorOps>::Scalar, n: usize) {
137 match_vector_pair!(self, scalar, |a: VectorMut, b: Scalar| {
138 a.append_scalars(b, n)
139 })
140 }
141
142 fn freeze(self) -> Vector {
143 match_each_vector_mut!(self, |v| { v.freeze().into() })
144 }
145
146 fn split_off(&mut self, at: usize) -> Self {
147 match_each_vector_mut!(self, |v| { v.split_off(at).into() })
148 }
149
150 fn unsplit(&mut self, other: Self) {
151 match_vector_pair!(self, other, |a: VectorMut, b: VectorMut| a.unsplit(b))
152 }
153}
154
155impl VectorMut {
156 pub fn as_null_mut(&mut self) -> &mut NullVectorMut {
158 if let VectorMut::Null(v) = self {
159 return v;
160 }
161 vortex_panic!("Expected NullVectorMut, got {self:?}");
162 }
163
164 pub fn as_bool_mut(&mut self) -> &mut BoolVectorMut {
166 if let VectorMut::Bool(v) = self {
167 return v;
168 }
169 vortex_panic!("Expected BoolVectorMut, got {self:?}");
170 }
171
172 pub fn as_primitive_mut(&mut self) -> &mut PrimitiveVectorMut {
174 if let VectorMut::Primitive(v) = self {
175 return v;
176 }
177 vortex_panic!("Expected PrimitiveVectorMut, got {self:?}");
178 }
179
180 pub fn as_string_mut(&mut self) -> &mut StringVectorMut {
182 if let VectorMut::String(v) = self {
183 return v;
184 }
185 vortex_panic!("Expected StringVectorMut, got {self:?}");
186 }
187
188 pub fn as_binary_mut(&mut self) -> &mut BinaryVectorMut {
190 if let VectorMut::Binary(v) = self {
191 return v;
192 }
193 vortex_panic!("Expected BinaryVectorMut, got {self:?}");
194 }
195
196 pub fn as_list_mut(&mut self) -> &mut ListViewVectorMut {
198 if let VectorMut::List(v) = self {
199 return v;
200 }
201 vortex_panic!("Expected ListViewVectorMut, got {self:?}");
202 }
203
204 pub fn as_fixed_size_list_mut(&mut self) -> &mut FixedSizeListVectorMut {
206 if let VectorMut::FixedSizeList(v) = self {
207 return v;
208 }
209 vortex_panic!("Expected FixedSizeListVectorMut, got {self:?}");
210 }
211
212 pub fn as_struct_mut(&mut self) -> &mut StructVectorMut {
214 if let VectorMut::Struct(v) = self {
215 return v;
216 }
217 vortex_panic!("Expected StructVectorMut, got {self:?}");
218 }
219
220 pub fn into_null(self) -> NullVectorMut {
222 if let VectorMut::Null(v) = self {
223 return v;
224 }
225 vortex_panic!("Expected NullVectorMut, got {self:?}");
226 }
227
228 pub fn into_bool(self) -> BoolVectorMut {
230 if let VectorMut::Bool(v) = self {
231 return v;
232 }
233 vortex_panic!("Expected BoolVectorMut, got {self:?}");
234 }
235
236 pub fn into_primitive(self) -> PrimitiveVectorMut {
238 if let VectorMut::Primitive(v) = self {
239 return v;
240 }
241 vortex_panic!("Expected PrimitiveVectorMut, got {self:?}");
242 }
243
244 #[expect(
246 clippy::same_name_method,
247 reason = "intentionally shadows VarBinTypeDowncast method"
248 )]
249 pub fn into_string(self) -> StringVectorMut {
250 if let VectorMut::String(v) = self {
251 return v;
252 }
253 vortex_panic!("Expected StringVectorMut, got {self:?}");
254 }
255
256 #[expect(
258 clippy::same_name_method,
259 reason = "intentionally shadows VarBinTypeDowncast method"
260 )]
261 pub fn into_binary(self) -> BinaryVectorMut {
262 if let VectorMut::Binary(v) = self {
263 return v;
264 }
265 vortex_panic!("Expected BinaryVectorMut, got {self:?}");
266 }
267
268 pub fn into_list(self) -> ListViewVectorMut {
270 if let VectorMut::List(v) = self {
271 return v;
272 }
273 vortex_panic!("Expected ListViewVectorMut, got {self:?}");
274 }
275
276 pub fn into_fixed_size_list(self) -> FixedSizeListVectorMut {
279 if let VectorMut::FixedSizeList(v) = self {
280 return v;
281 }
282 vortex_panic!("Expected FixedSizeListVectorMut, got {self:?}");
283 }
284
285 pub fn into_struct(self) -> StructVectorMut {
287 if let VectorMut::Struct(v) = self {
288 return v;
289 }
290 vortex_panic!("Expected StructVectorMut, got {self:?}");
291 }
292}
293
294#[cfg(test)]
295mod tests {
296 use vortex_dtype::DecimalDType;
297 use vortex_dtype::Nullability;
298 use vortex_dtype::PType;
299
300 use super::*;
301 use crate::VectorOps;
302 use crate::decimal::DecimalVectorMut;
303 use crate::primitive::PVectorMut;
304
305 #[test]
306 fn test_with_capacity() {
307 let null_vec = VectorMut::with_capacity(&DType::Null, 10);
309 assert_eq!(null_vec.capacity(), usize::MAX); let bool_vec = VectorMut::with_capacity(&DType::Bool(Nullability::Nullable), 100);
312 assert!(bool_vec.capacity() >= 100);
313
314 let prim_vec =
315 VectorMut::with_capacity(&DType::Primitive(PType::I32, Nullability::Nullable), 50);
316 assert!(prim_vec.capacity() >= 50);
317 }
318
319 #[test]
320 fn test_with_capacity_decimal() {
321 let decimal_dtype = DType::Decimal(DecimalDType::new(4, 2), Nullability::Nullable);
327 let decimal_vec = VectorMut::with_capacity(&decimal_dtype, 50);
328
329 match decimal_vec {
330 VectorMut::Decimal(dec_vec) => {
331 assert_eq!(dec_vec.len(), 0, "New vector should be empty");
332 assert!(dec_vec.capacity() >= 50, "Capacity should be at least 50");
333
334 assert!(
336 matches!(dec_vec, DecimalVectorMut::D16(_)),
337 "Precision 4 should use D16 variant"
338 );
339 }
340 _ => panic!("Expected decimal vector for decimal dtype"),
341 }
342
343 let decimal_dtype = DType::Decimal(DecimalDType::new(9, 0), Nullability::NonNullable);
345 let decimal_vec = VectorMut::with_capacity(&decimal_dtype, 100);
346
347 match decimal_vec {
348 VectorMut::Decimal(dec_vec) => {
349 assert_eq!(dec_vec.len(), 0, "New vector should be empty");
350 assert!(dec_vec.capacity() >= 100, "Capacity should be at least 100");
351
352 assert!(
354 matches!(dec_vec, DecimalVectorMut::D32(_)),
355 "Precision 9 should use D32 variant"
356 );
357 }
358 _ => panic!("Expected decimal vector for decimal dtype"),
359 }
360
361 let decimal_dtype = DType::Decimal(DecimalDType::new(18, -2), Nullability::Nullable);
363 let decimal_vec = VectorMut::with_capacity(&decimal_dtype, 75);
364
365 match decimal_vec {
366 VectorMut::Decimal(dec_vec) => {
367 assert_eq!(dec_vec.len(), 0, "New vector should be empty");
368 assert!(dec_vec.capacity() >= 75, "Capacity should be at least 75");
369
370 assert!(
372 matches!(dec_vec, DecimalVectorMut::D64(_)),
373 "Precision 18 should use D64 variant"
374 );
375 }
376 _ => panic!("Expected decimal vector for decimal dtype"),
377 }
378
379 let decimal_dtype = DType::Decimal(DecimalDType::new(38, 10), Nullability::NonNullable);
381 let decimal_vec = VectorMut::with_capacity(&decimal_dtype, 25);
382
383 match decimal_vec {
384 VectorMut::Decimal(dec_vec) => {
385 assert_eq!(dec_vec.len(), 0, "New vector should be empty");
386 assert!(dec_vec.capacity() >= 25, "Capacity should be at least 25");
387
388 assert!(
390 matches!(dec_vec, DecimalVectorMut::D128(_)),
391 "Precision 38 should use D128 variant"
392 );
393 }
394 _ => panic!("Expected decimal vector for decimal dtype"),
395 }
396 }
397
398 #[test]
399 #[should_panic(expected = "Mismatched vector types")]
400 fn test_type_mismatch_panics() {
401 let mut vec1 = VectorMut::with_capacity(&DType::Bool(Nullability::Nullable), 10);
403 let vec2 =
404 VectorMut::with_capacity(&DType::Primitive(PType::I32, Nullability::Nullable), 10);
405
406 vec1.unsplit(vec2); }
408
409 #[test]
410 fn test_split_and_unsplit() {
411 let mut vec: VectorMut = BoolVectorMut::from_iter([true, false, true].map(Some)).into();
413
414 let second = vec.split_off(0);
416 assert_eq!(vec.len(), 0);
417 assert_eq!(second.len(), 3);
418
419 vec.unsplit(second);
421 assert_eq!(vec.len(), 3);
422
423 let second = vec.split_off(3);
425 assert_eq!(vec.len(), 3);
426 assert_eq!(second.len(), 0);
427 }
428
429 #[test]
430 fn test_reserve_ensures_len_plus_additional() {
431 let mut bool_vec: VectorMut = BoolVectorMut::with_capacity(10).into();
434 let initial_len = bool_vec.len();
435 assert_eq!(initial_len, 0);
436
437 bool_vec.reserve(100);
439
440 assert!(bool_vec.capacity() >= initial_len + 100);
442 assert!(bool_vec.capacity() >= 100); let mut prim_vec: VectorMut = PVectorMut::<i32>::with_capacity(10).into();
446 prim_vec.reserve(100);
447 assert!(prim_vec.capacity() >= prim_vec.len() + 100);
448
449 let mut vec: VectorMut = BoolVectorMut::from_iter([true, false, true].map(Some)).into();
451 let len = vec.len();
452 assert_eq!(len, 3);
453 vec.reserve(50);
454 assert!(vec.capacity() >= len + 50);
455 assert!(vec.capacity() >= 53);
456 }
457
458 #[test]
459 fn test_append_nulls_preserves_validity() {
460 let mut vec: VectorMut = BoolVectorMut::from_iter([true].map(Some)).into();
462 vec.append_nulls(2);
463 assert_eq!(vec.len(), 3);
464
465 let frozen = vec.freeze();
466 assert_eq!(frozen.validity().true_count(), 1); }
468
469 #[test]
470 fn test_extend_from_vector() {
471 let mut vec: VectorMut = PVectorMut::<i32>::from_iter([1, 2, 3].map(Some)).into();
473 assert_eq!(vec.len(), 3);
474
475 let to_append: Vector = PVectorMut::<i32>::from_iter([4, 5, 6].map(Some))
477 .freeze()
478 .into();
479 assert_eq!(to_append.len(), 3);
480
481 vec.extend_from_vector(&to_append);
483
484 assert_eq!(vec.len(), 6);
486
487 let frozen = vec.freeze();
489 assert_eq!(frozen.validity().true_count(), 6);
490 }
491}