vortex_array/arrays/primitive/array/
conversion.rs1use vortex_buffer::{BitBufferMut, Buffer, BufferMut};
7use vortex_dtype::{NativePType, Nullability};
8use vortex_error::{VortexResult, vortex_ensure, vortex_panic};
9use vortex_vector::primitive::PrimitiveVector;
10use vortex_vector::{VectorOps, match_each_pvector};
11
12use crate::arrays::PrimitiveArray;
13use crate::validity::Validity;
14use crate::vtable::ValidityHelper;
15use crate::{ArrayRef, IntoArray};
16
17impl PrimitiveArray {
18 pub fn try_from_vector(
25 primitive_vector: PrimitiveVector,
26 nullability: Nullability,
27 ) -> VortexResult<Self> {
28 vortex_ensure!(
30 nullability.is_nullable() || primitive_vector.validity().all_true(),
31 "tried to create a non-nullable `PrimitiveArray` from a `PrimitiveVector` that had nulls"
32 );
33
34 match_each_pvector!(primitive_vector, |v| {
35 let (buffer, mask) = v.into_parts();
36 debug_assert_eq!(buffer.len(), mask.len());
37
38 let validity = Validity::from_mask(mask, nullability);
39
40 Ok(unsafe { Self::new_unchecked(buffer, validity) })
43 })
44 }
45
46 pub fn from_option_iter<T: NativePType, I: IntoIterator<Item = Option<T>>>(iter: I) -> Self {
49 let iter = iter.into_iter();
50 let mut values = BufferMut::with_capacity(iter.size_hint().0);
51 let mut validity = BitBufferMut::with_capacity(values.capacity());
52
53 for i in iter {
54 match i {
55 None => {
56 validity.append(false);
57 values.push(T::default());
58 }
59 Some(e) => {
60 validity.append(true);
61 values.push(e);
62 }
63 }
64 }
65 Self::new(values.freeze(), Validity::from(validity.freeze()))
66 }
67
68 pub fn buffer<T: NativePType>(&self) -> Buffer<T> {
69 if T::PTYPE != self.ptype() {
70 vortex_panic!(
71 "Attempted to get buffer of type {} from array of type {}",
72 T::PTYPE,
73 self.ptype()
74 )
75 }
76 Buffer::from_byte_buffer(self.byte_buffer().clone())
77 }
78
79 pub fn into_buffer<T: NativePType>(self) -> Buffer<T> {
80 if T::PTYPE != self.ptype() {
81 vortex_panic!(
82 "Attempted to get buffer of type {} from array of type {}",
83 T::PTYPE,
84 self.ptype()
85 )
86 }
87 Buffer::from_byte_buffer(self.buffer)
88 }
89
90 pub fn into_buffer_mut<T: NativePType>(self) -> BufferMut<T> {
93 if T::PTYPE != self.ptype() {
94 vortex_panic!(
95 "Attempted to get buffer_mut of type {} from array of type {}",
96 T::PTYPE,
97 self.ptype()
98 )
99 }
100 self.into_buffer()
101 .try_into_mut()
102 .unwrap_or_else(|buffer| BufferMut::<T>::copy_from(&buffer))
103 }
104
105 #[allow(clippy::panic_in_result_fn)]
107 pub fn try_into_buffer_mut<T: NativePType>(self) -> Result<BufferMut<T>, PrimitiveArray> {
108 if T::PTYPE != self.ptype() {
109 vortex_panic!(
110 "Attempted to get buffer_mut of type {} from array of type {}",
111 T::PTYPE,
112 self.ptype()
113 )
114 }
115 let validity = self.validity().clone();
116 Buffer::<T>::from_byte_buffer(self.into_byte_buffer())
117 .try_into_mut()
118 .map_err(|buffer| PrimitiveArray::new(buffer, validity))
119 }
120}
121
122impl<T: NativePType> FromIterator<T> for PrimitiveArray {
123 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
124 let values = BufferMut::from_iter(iter);
125 PrimitiveArray::new(values, Validity::NonNullable)
126 }
127}
128
129impl<T: NativePType> IntoArray for Buffer<T> {
130 fn into_array(self) -> ArrayRef {
131 PrimitiveArray::new(self, Validity::NonNullable).into_array()
132 }
133}
134
135impl<T: NativePType> IntoArray for BufferMut<T> {
136 fn into_array(self) -> ArrayRef {
137 self.freeze().into_array()
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use vortex_buffer::BufferMut;
144 use vortex_dtype::{Nullability, PType};
145 use vortex_mask::MaskMut;
146 use vortex_vector::primitive::PVector;
147
148 use super::*;
149
150 #[test]
151 fn test_try_from_vector_with_nulls_nullable() {
152 let mut values = BufferMut::<i32>::with_capacity(5);
154 values.extend_from_slice(&[1, 0, 3, 4, 0]);
155
156 let mut validity = MaskMut::with_capacity(5);
157 validity.append_n(true, 1);
158 validity.append_n(false, 1);
159 validity.append_n(true, 1);
160 validity.append_n(true, 1);
161 validity.append_n(false, 1);
162
163 let pvector =
164 PVector::try_new(values.freeze(), validity.freeze()).expect("Failed to create PVector");
165
166 let result =
168 PrimitiveArray::try_from_vector(pvector.into(), Nullability::Nullable).unwrap();
169
170 assert_eq!(result.len(), 5);
171 assert_eq!(result.ptype(), PType::I32);
172 assert!(result.is_valid(0));
173 assert!(!result.is_valid(1));
174 assert!(result.is_valid(2));
175 assert!(result.is_valid(3));
176 assert!(!result.is_valid(4));
177 }
178
179 #[test]
180 fn test_try_from_vector_non_nullable_with_nulls_errors() {
181 let mut values = BufferMut::<i32>::with_capacity(3);
183 values.extend_from_slice(&[1, 0, 3]);
184
185 let mut validity = MaskMut::with_capacity(3);
186 validity.append_n(true, 1);
187 validity.append_n(false, 1);
188 validity.append_n(true, 1);
189
190 let pvector =
191 PVector::try_new(values.freeze(), validity.freeze()).expect("Failed to create PVector");
192
193 let result = PrimitiveArray::try_from_vector(pvector.into(), Nullability::NonNullable);
196
197 assert!(result.is_err());
198 assert!(
199 result
200 .unwrap_err()
201 .to_string()
202 .contains("non-nullable `PrimitiveArray`")
203 );
204 }
205}