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)]
37pub enum VectorMut {
38 Null(NullVectorMut),
40 Bool(BoolVectorMut),
42 Decimal(DecimalVectorMut),
49 Primitive(PrimitiveVectorMut),
56 String(StringVectorMut),
58 Binary(BinaryVectorMut),
60 List(ListViewVectorMut),
62 FixedSizeList(FixedSizeListVectorMut),
64 Struct(StructVectorMut),
66}
67
68impl VectorMut {
69 pub fn with_capacity(dtype: &DType, capacity: usize) -> Self {
71 match dtype {
72 DType::Null => NullVectorMut::new(0).into(),
73 DType::Bool(_) => BoolVectorMut::with_capacity(capacity).into(),
74 DType::Primitive(ptype, _) => {
75 PrimitiveVectorMut::with_capacity(*ptype, capacity).into()
76 }
77 DType::FixedSizeList(elem_dtype, list_size, _) => {
78 FixedSizeListVectorMut::with_capacity(elem_dtype, *list_size, capacity).into()
79 }
80 DType::Struct(struct_fields, _) => {
81 StructVectorMut::with_capacity(struct_fields, capacity).into()
82 }
83 DType::Decimal(decimal_dtype, _) => {
84 DecimalVectorMut::with_capacity(decimal_dtype, capacity).into()
85 }
86 DType::Utf8(..) => StringVectorMut::with_capacity(capacity).into(),
87 DType::Binary(..) => BinaryVectorMut::with_capacity(capacity).into(),
88 DType::Extension(ext) => VectorMut::with_capacity(ext.storage_dtype(), capacity),
89 DType::List(elem, ..) => {
90 ListViewVectorMut::with_capacity(elem.as_ref(), capacity, 2 * capacity).into()
93 }
94 }
95 }
96}
97
98impl VectorMutOps for VectorMut {
99 type Immutable = Vector;
100
101 fn len(&self) -> usize {
102 match_each_vector_mut!(self, |v| { v.len() })
103 }
104
105 fn validity(&self) -> &MaskMut {
106 match_each_vector_mut!(self, |v| { v.validity() })
107 }
108
109 fn capacity(&self) -> usize {
110 match_each_vector_mut!(self, |v| { v.capacity() })
111 }
112
113 fn reserve(&mut self, additional: usize) {
114 match_each_vector_mut!(self, |v| { v.reserve(additional) })
115 }
116
117 fn clear(&mut self) {
118 match_each_vector_mut!(self, |v| { v.clear() })
119 }
120
121 fn truncate(&mut self, len: usize) {
122 match_each_vector_mut!(self, |v| { v.truncate(len) })
123 }
124
125 fn extend_from_vector(&mut self, other: &Vector) {
126 match_vector_pair!(self, other, |a: VectorMut, b: Vector| {
127 a.extend_from_vector(b)
128 })
129 }
130
131 fn append_nulls(&mut self, n: usize) {
132 match_each_vector_mut!(self, |v| { v.append_nulls(n) })
133 }
134
135 fn append_zeros(&mut self, n: usize) {
136 match_each_vector_mut!(self, |v| { v.append_zeros(n) })
137 }
138
139 fn append_scalars(&mut self, scalar: &<Self::Immutable as VectorOps>::Scalar, n: usize) {
140 match_vector_pair!(self, scalar, |a: VectorMut, b: Scalar| {
141 a.append_scalars(b, n)
142 })
143 }
144
145 fn freeze(self) -> Vector {
146 match_each_vector_mut!(self, |v| { v.freeze().into() })
147 }
148
149 fn split_off(&mut self, at: usize) -> Self {
150 match_each_vector_mut!(self, |v| { v.split_off(at).into() })
151 }
152
153 fn unsplit(&mut self, other: Self) {
154 match_vector_pair!(self, other, |a: VectorMut, b: VectorMut| a.unsplit(b))
155 }
156}
157
158impl VectorMut {
159 pub fn as_null_mut(&mut self) -> &mut NullVectorMut {
161 if let VectorMut::Null(v) = self {
162 return v;
163 }
164 vortex_panic!("Expected NullVectorMut, got {self:?}");
165 }
166
167 pub fn as_bool_mut(&mut self) -> &mut BoolVectorMut {
169 if let VectorMut::Bool(v) = self {
170 return v;
171 }
172 vortex_panic!("Expected BoolVectorMut, got {self:?}");
173 }
174
175 pub fn as_primitive_mut(&mut self) -> &mut PrimitiveVectorMut {
177 if let VectorMut::Primitive(v) = self {
178 return v;
179 }
180 vortex_panic!("Expected PrimitiveVectorMut, got {self:?}");
181 }
182
183 pub fn as_string_mut(&mut self) -> &mut StringVectorMut {
185 if let VectorMut::String(v) = self {
186 return v;
187 }
188 vortex_panic!("Expected StringVectorMut, got {self:?}");
189 }
190
191 pub fn as_binary_mut(&mut self) -> &mut BinaryVectorMut {
193 if let VectorMut::Binary(v) = self {
194 return v;
195 }
196 vortex_panic!("Expected BinaryVectorMut, got {self:?}");
197 }
198
199 pub fn as_list_mut(&mut self) -> &mut ListViewVectorMut {
201 if let VectorMut::List(v) = self {
202 return v;
203 }
204 vortex_panic!("Expected ListViewVectorMut, got {self:?}");
205 }
206
207 pub fn as_fixed_size_list_mut(&mut self) -> &mut FixedSizeListVectorMut {
209 if let VectorMut::FixedSizeList(v) = self {
210 return v;
211 }
212 vortex_panic!("Expected FixedSizeListVectorMut, got {self:?}");
213 }
214
215 pub fn as_struct_mut(&mut self) -> &mut StructVectorMut {
217 if let VectorMut::Struct(v) = self {
218 return v;
219 }
220 vortex_panic!("Expected StructVectorMut, got {self:?}");
221 }
222
223 pub fn into_null(self) -> NullVectorMut {
225 if let VectorMut::Null(v) = self {
226 return v;
227 }
228 vortex_panic!("Expected NullVectorMut, got {self:?}");
229 }
230
231 pub fn into_bool(self) -> BoolVectorMut {
233 if let VectorMut::Bool(v) = self {
234 return v;
235 }
236 vortex_panic!("Expected BoolVectorMut, got {self:?}");
237 }
238
239 pub fn into_primitive(self) -> PrimitiveVectorMut {
241 if let VectorMut::Primitive(v) = self {
242 return v;
243 }
244 vortex_panic!("Expected PrimitiveVectorMut, got {self:?}");
245 }
246
247 pub fn into_decimal(self) -> DecimalVectorMut {
249 if let VectorMut::Decimal(v) = self {
250 return v;
251 }
252 vortex_panic!("Expected DecimalVectorMut, got {self:?}");
253 }
254
255 #[expect(
257 clippy::same_name_method,
258 reason = "intentionally shadows VarBinTypeDowncast method"
259 )]
260 pub fn into_string(self) -> StringVectorMut {
261 if let VectorMut::String(v) = self {
262 return v;
263 }
264 vortex_panic!("Expected StringVectorMut, got {self:?}");
265 }
266
267 #[expect(
269 clippy::same_name_method,
270 reason = "intentionally shadows VarBinTypeDowncast method"
271 )]
272 pub fn into_binary(self) -> BinaryVectorMut {
273 if let VectorMut::Binary(v) = self {
274 return v;
275 }
276 vortex_panic!("Expected BinaryVectorMut, got {self:?}");
277 }
278
279 pub fn into_list(self) -> ListViewVectorMut {
281 if let VectorMut::List(v) = self {
282 return v;
283 }
284 vortex_panic!("Expected ListViewVectorMut, got {self:?}");
285 }
286
287 pub fn into_fixed_size_list(self) -> FixedSizeListVectorMut {
290 if let VectorMut::FixedSizeList(v) = self {
291 return v;
292 }
293 vortex_panic!("Expected FixedSizeListVectorMut, got {self:?}");
294 }
295
296 pub fn into_struct(self) -> StructVectorMut {
298 if let VectorMut::Struct(v) = self {
299 return v;
300 }
301 vortex_panic!("Expected StructVectorMut, got {self:?}");
302 }
303}
304
305#[cfg(test)]
306mod tests {
307 use vortex_dtype::DecimalDType;
308 use vortex_dtype::Nullability;
309 use vortex_dtype::PType;
310
311 use super::*;
312 use crate::VectorOps;
313 use crate::decimal::DecimalVectorMut;
314 use crate::primitive::PVectorMut;
315
316 #[test]
317 fn test_with_capacity() {
318 let null_vec = VectorMut::with_capacity(&DType::Null, 10);
320 assert_eq!(null_vec.capacity(), usize::MAX); let bool_vec = VectorMut::with_capacity(&DType::Bool(Nullability::Nullable), 100);
323 assert!(bool_vec.capacity() >= 100);
324
325 let prim_vec =
326 VectorMut::with_capacity(&DType::Primitive(PType::I32, Nullability::Nullable), 50);
327 assert!(prim_vec.capacity() >= 50);
328 }
329
330 #[test]
331 fn test_with_capacity_decimal() {
332 let decimal_dtype = DType::Decimal(DecimalDType::new(4, 2), Nullability::Nullable);
338 let decimal_vec = VectorMut::with_capacity(&decimal_dtype, 50);
339
340 match decimal_vec {
341 VectorMut::Decimal(dec_vec) => {
342 assert_eq!(dec_vec.len(), 0, "New vector should be empty");
343 assert!(dec_vec.capacity() >= 50, "Capacity should be at least 50");
344
345 assert!(
347 matches!(dec_vec, DecimalVectorMut::D16(_)),
348 "Precision 4 should use D16 variant"
349 );
350 }
351 _ => panic!("Expected decimal vector for decimal dtype"),
352 }
353
354 let decimal_dtype = DType::Decimal(DecimalDType::new(9, 0), Nullability::NonNullable);
356 let decimal_vec = VectorMut::with_capacity(&decimal_dtype, 100);
357
358 match decimal_vec {
359 VectorMut::Decimal(dec_vec) => {
360 assert_eq!(dec_vec.len(), 0, "New vector should be empty");
361 assert!(dec_vec.capacity() >= 100, "Capacity should be at least 100");
362
363 assert!(
365 matches!(dec_vec, DecimalVectorMut::D32(_)),
366 "Precision 9 should use D32 variant"
367 );
368 }
369 _ => panic!("Expected decimal vector for decimal dtype"),
370 }
371
372 let decimal_dtype = DType::Decimal(DecimalDType::new(18, -2), Nullability::Nullable);
374 let decimal_vec = VectorMut::with_capacity(&decimal_dtype, 75);
375
376 match decimal_vec {
377 VectorMut::Decimal(dec_vec) => {
378 assert_eq!(dec_vec.len(), 0, "New vector should be empty");
379 assert!(dec_vec.capacity() >= 75, "Capacity should be at least 75");
380
381 assert!(
383 matches!(dec_vec, DecimalVectorMut::D64(_)),
384 "Precision 18 should use D64 variant"
385 );
386 }
387 _ => panic!("Expected decimal vector for decimal dtype"),
388 }
389
390 let decimal_dtype = DType::Decimal(DecimalDType::new(38, 10), Nullability::NonNullable);
392 let decimal_vec = VectorMut::with_capacity(&decimal_dtype, 25);
393
394 match decimal_vec {
395 VectorMut::Decimal(dec_vec) => {
396 assert_eq!(dec_vec.len(), 0, "New vector should be empty");
397 assert!(dec_vec.capacity() >= 25, "Capacity should be at least 25");
398
399 assert!(
401 matches!(dec_vec, DecimalVectorMut::D128(_)),
402 "Precision 38 should use D128 variant"
403 );
404 }
405 _ => panic!("Expected decimal vector for decimal dtype"),
406 }
407 }
408
409 #[test]
410 #[should_panic(expected = "Mismatched vector types")]
411 fn test_type_mismatch_panics() {
412 let mut vec1 = VectorMut::with_capacity(&DType::Bool(Nullability::Nullable), 10);
414 let vec2 =
415 VectorMut::with_capacity(&DType::Primitive(PType::I32, Nullability::Nullable), 10);
416
417 vec1.unsplit(vec2); }
419
420 #[test]
421 fn test_split_and_unsplit() {
422 let mut vec: VectorMut = BoolVectorMut::from_iter([true, false, true].map(Some)).into();
424
425 let second = vec.split_off(0);
427 assert_eq!(vec.len(), 0);
428 assert_eq!(second.len(), 3);
429
430 vec.unsplit(second);
432 assert_eq!(vec.len(), 3);
433
434 let second = vec.split_off(3);
436 assert_eq!(vec.len(), 3);
437 assert_eq!(second.len(), 0);
438 }
439
440 #[test]
441 fn test_reserve_ensures_len_plus_additional() {
442 let mut bool_vec: VectorMut = BoolVectorMut::with_capacity(10).into();
445 let initial_len = bool_vec.len();
446 assert_eq!(initial_len, 0);
447
448 bool_vec.reserve(100);
450
451 assert!(bool_vec.capacity() >= initial_len + 100);
453 assert!(bool_vec.capacity() >= 100); let mut prim_vec: VectorMut = PVectorMut::<i32>::with_capacity(10).into();
457 prim_vec.reserve(100);
458 assert!(prim_vec.capacity() >= prim_vec.len() + 100);
459
460 let mut vec: VectorMut = BoolVectorMut::from_iter([true, false, true].map(Some)).into();
462 let len = vec.len();
463 assert_eq!(len, 3);
464 vec.reserve(50);
465 assert!(vec.capacity() >= len + 50);
466 assert!(vec.capacity() >= 53);
467 }
468
469 #[test]
470 fn test_append_nulls_preserves_validity() {
471 let mut vec: VectorMut = BoolVectorMut::from_iter([true].map(Some)).into();
473 vec.append_nulls(2);
474 assert_eq!(vec.len(), 3);
475
476 let frozen = vec.freeze();
477 assert_eq!(frozen.validity().true_count(), 1); }
479
480 #[test]
481 fn test_extend_from_vector() {
482 let mut vec: VectorMut = PVectorMut::<i32>::from_iter([1, 2, 3].map(Some)).into();
484 assert_eq!(vec.len(), 3);
485
486 let to_append: Vector = PVectorMut::<i32>::from_iter([4, 5, 6].map(Some))
488 .freeze()
489 .into();
490 assert_eq!(to_append.len(), 3);
491
492 vec.extend_from_vector(&to_append);
494
495 assert_eq!(vec.len(), 6);
497
498 let frozen = vec.freeze();
500 assert_eq!(frozen.validity().true_count(), 6);
501 }
502}