1use crate::alloc::Deallocation;
19use crate::buffer::Buffer;
20use crate::native::ArrowNativeType;
21use crate::{BufferBuilder, MutableBuffer, OffsetBuffer};
22use std::fmt::Formatter;
23use std::marker::PhantomData;
24use std::ops::Deref;
25
26#[derive(Clone, Default)]
66pub struct ScalarBuffer<T: ArrowNativeType> {
67 buffer: Buffer,
69 phantom: PhantomData<T>,
70}
71
72impl<T: ArrowNativeType> std::fmt::Debug for ScalarBuffer<T> {
73 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
74 f.debug_tuple("ScalarBuffer").field(&self.as_ref()).finish()
75 }
76}
77
78impl<T: ArrowNativeType> ScalarBuffer<T> {
79 pub fn new(buffer: Buffer, offset: usize, len: usize) -> Self {
90 let size = std::mem::size_of::<T>();
91 let byte_offset = offset.checked_mul(size).expect("offset overflow");
92 let byte_len = len.checked_mul(size).expect("length overflow");
93 buffer.slice_with_length(byte_offset, byte_len).into()
94 }
95
96 pub unsafe fn new_unchecked(buffer: Buffer) -> Self {
103 Self {
104 buffer,
105 phantom: Default::default(),
106 }
107 }
108
109 pub fn shrink_to_fit(&mut self) {
111 self.buffer.shrink_to_fit();
112 }
113
114 pub fn slice(&self, offset: usize, len: usize) -> Self {
120 Self::new(self.buffer.clone(), offset, len)
121 }
122
123 pub fn inner(&self) -> &Buffer {
125 &self.buffer
126 }
127
128 pub fn into_inner(self) -> Buffer {
130 self.buffer
131 }
132
133 #[cfg(feature = "pool")]
137 pub fn claim(&self, pool: &dyn crate::MemoryPool) {
138 self.buffer.claim(pool);
139 }
140
141 #[inline]
145 pub fn ptr_eq(&self, other: &Self) -> bool {
146 self.buffer.ptr_eq(&other.buffer)
147 }
148
149 pub fn len(&self) -> usize {
151 self.buffer.len() / std::mem::size_of::<T>()
152 }
153
154 pub fn is_empty(&self) -> bool {
156 self.len() == 0
157 }
158}
159
160impl<T: ArrowNativeType> Deref for ScalarBuffer<T> {
161 type Target = [T];
162
163 #[inline]
164 fn deref(&self) -> &Self::Target {
165 unsafe {
167 std::slice::from_raw_parts(
168 self.buffer.as_ptr().cast::<T>(),
169 self.buffer.len() / std::mem::size_of::<T>(),
170 )
171 }
172 }
173}
174
175impl<T: ArrowNativeType> AsRef<[T]> for ScalarBuffer<T> {
176 #[inline]
177 fn as_ref(&self) -> &[T] {
178 self
179 }
180}
181
182impl<T: ArrowNativeType> From<MutableBuffer> for ScalarBuffer<T> {
183 fn from(value: MutableBuffer) -> Self {
184 Buffer::from(value).into()
185 }
186}
187
188impl<T: ArrowNativeType> From<Buffer> for ScalarBuffer<T> {
189 fn from(buffer: Buffer) -> Self {
190 let align = std::mem::align_of::<T>();
191 let is_aligned = buffer.as_ptr().align_offset(align) == 0;
192
193 match buffer.deallocation() {
194 Deallocation::Standard(_) => assert!(
195 is_aligned,
196 "Memory pointer is not aligned with the specified scalar type"
197 ),
198 Deallocation::Custom(_, _) => assert!(
199 is_aligned,
200 "Memory pointer from external source (e.g, FFI) is not aligned with the specified scalar type. Before importing buffer through FFI, please make sure the allocation is aligned."
201 ),
202 }
203
204 Self {
205 buffer,
206 phantom: Default::default(),
207 }
208 }
209}
210
211impl<T: ArrowNativeType> From<OffsetBuffer<T>> for ScalarBuffer<T> {
212 fn from(value: OffsetBuffer<T>) -> Self {
213 value.into_inner()
214 }
215}
216
217impl<T: ArrowNativeType> From<Vec<T>> for ScalarBuffer<T> {
218 fn from(value: Vec<T>) -> Self {
219 Self {
220 buffer: Buffer::from_vec(value),
221 phantom: Default::default(),
222 }
223 }
224}
225
226impl<T: ArrowNativeType> From<ScalarBuffer<T>> for Vec<T> {
227 fn from(value: ScalarBuffer<T>) -> Self {
228 value
229 .buffer
230 .into_vec()
231 .unwrap_or_else(|buffer| buffer.typed_data::<T>().into())
232 }
233}
234
235impl<T: ArrowNativeType> From<BufferBuilder<T>> for ScalarBuffer<T> {
236 fn from(mut value: BufferBuilder<T>) -> Self {
237 let len = value.len();
238 Self::new(value.finish(), 0, len)
239 }
240}
241
242impl<T: ArrowNativeType> FromIterator<T> for ScalarBuffer<T> {
243 #[inline]
244 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
245 iter.into_iter().collect::<Vec<_>>().into()
246 }
247}
248
249impl<'a, T: ArrowNativeType> IntoIterator for &'a ScalarBuffer<T> {
250 type Item = &'a T;
251 type IntoIter = std::slice::Iter<'a, T>;
252
253 fn into_iter(self) -> Self::IntoIter {
254 self.as_ref().iter()
255 }
256}
257
258impl<T: ArrowNativeType, S: AsRef<[T]> + ?Sized> PartialEq<S> for ScalarBuffer<T> {
259 fn eq(&self, other: &S) -> bool {
260 self.as_ref().eq(other.as_ref())
261 }
262}
263
264impl<T: ArrowNativeType, const N: usize> PartialEq<ScalarBuffer<T>> for [T; N] {
265 fn eq(&self, other: &ScalarBuffer<T>) -> bool {
266 self.as_ref().eq(other.as_ref())
267 }
268}
269
270impl<T: ArrowNativeType> PartialEq<ScalarBuffer<T>> for [T] {
271 fn eq(&self, other: &ScalarBuffer<T>) -> bool {
272 self.as_ref().eq(other.as_ref())
273 }
274}
275
276impl<T: ArrowNativeType> PartialEq<ScalarBuffer<T>> for Vec<T> {
277 fn eq(&self, other: &ScalarBuffer<T>) -> bool {
278 self.as_slice().eq(other.as_ref())
279 }
280}
281
282impl<T: ArrowNativeType + Eq> Eq for ScalarBuffer<T> {}
284
285#[cfg(test)]
286mod tests {
287 use std::{ptr::NonNull, sync::Arc};
288
289 use super::*;
290
291 #[test]
292 fn test_basic() {
293 let expected = [0_i32, 1, 2];
294 let buffer = Buffer::from_iter(expected.iter().copied());
295 let typed = ScalarBuffer::<i32>::new(buffer.clone(), 0, 3);
296 assert_eq!(*typed, expected);
297
298 let typed = ScalarBuffer::<i32>::new(buffer.clone(), 1, 2);
299 assert_eq!(*typed, expected[1..]);
300
301 let typed = ScalarBuffer::<i32>::new(buffer.clone(), 1, 0);
302 assert!(typed.is_empty());
303
304 let typed = ScalarBuffer::<i32>::new(buffer, 3, 0);
305 assert!(typed.is_empty());
306 }
307
308 #[test]
309 fn test_debug() {
310 let buffer = ScalarBuffer::from(vec![1, 2, 3]);
311 assert_eq!(format!("{buffer:?}"), "ScalarBuffer([1, 2, 3])");
312 }
313
314 #[test]
315 #[should_panic(expected = "Memory pointer is not aligned with the specified scalar type")]
316 fn test_unaligned() {
317 let expected = [0_i32, 1, 2];
318 let buffer = Buffer::from_iter(expected.iter().copied());
319 let buffer = buffer.slice(1);
320 ScalarBuffer::<i32>::new(buffer, 0, 2);
321 }
322
323 #[test]
324 #[should_panic(expected = "the offset of the new Buffer cannot exceed the existing length")]
325 fn test_length_out_of_bounds() {
326 let buffer = Buffer::from_iter([0_i32, 1, 2]);
327 ScalarBuffer::<i32>::new(buffer, 1, 3);
328 }
329
330 #[test]
331 #[should_panic(expected = "the offset of the new Buffer cannot exceed the existing length")]
332 fn test_offset_out_of_bounds() {
333 let buffer = Buffer::from_iter([0_i32, 1, 2]);
334 ScalarBuffer::<i32>::new(buffer, 4, 0);
335 }
336
337 #[test]
338 #[should_panic(expected = "offset overflow")]
339 fn test_length_overflow() {
340 let buffer = Buffer::from_iter([0_i32, 1, 2]);
341 ScalarBuffer::<i32>::new(buffer, usize::MAX, 1);
342 }
343
344 #[test]
345 #[should_panic(expected = "offset overflow")]
346 fn test_start_overflow() {
347 let buffer = Buffer::from_iter([0_i32, 1, 2]);
348 ScalarBuffer::<i32>::new(buffer, usize::MAX / 4 + 1, 0);
349 }
350
351 #[test]
352 #[should_panic(expected = "length overflow")]
353 fn test_end_overflow() {
354 let buffer = Buffer::from_iter([0_i32, 1, 2]);
355 ScalarBuffer::<i32>::new(buffer, 0, usize::MAX / 4 + 1);
356 }
357
358 #[test]
359 fn convert_from_buffer_builder() {
360 let input = vec![1, 2, 3, 4];
361 let buffer_builder = BufferBuilder::from(input.clone());
362 let scalar_buffer = ScalarBuffer::from(buffer_builder);
363 assert_eq!(scalar_buffer.as_ref(), input);
364 }
365
366 #[test]
367 fn into_vec() {
368 let input = vec![1u8, 2, 3, 4];
369
370 let input_buffer = Buffer::from_vec(input.clone());
372 let input_ptr = input_buffer.as_ptr();
373 let input_len = input_buffer.len();
374 let scalar_buffer = ScalarBuffer::<u8>::new(input_buffer, 0, input_len);
375 let vec = Vec::from(scalar_buffer);
376 assert_eq!(vec.as_slice(), input.as_slice());
377 assert_eq!(vec.as_ptr(), input_ptr);
378
379 let mut input_clone = input.clone();
381 let input_ptr = NonNull::new(input_clone.as_mut_ptr()).unwrap();
382 let dealloc = Arc::new(());
383 let buffer =
384 unsafe { Buffer::from_custom_allocation(input_ptr, input_clone.len(), dealloc as _) };
385 let scalar_buffer = ScalarBuffer::<u8>::new(buffer, 0, input.len());
386 let vec = Vec::from(scalar_buffer);
387 assert_eq!(vec, input.as_slice());
388 assert_ne!(vec.as_ptr(), input_ptr.as_ptr());
389
390 let input_buffer = Buffer::from_vec(input.clone());
392 let input_ptr = input_buffer.as_ptr();
393 let input_len = input_buffer.len();
394 let scalar_buffer = ScalarBuffer::<u8>::new(input_buffer, 1, input_len - 1);
395 let vec = Vec::from(scalar_buffer);
396 assert_eq!(vec.as_slice(), &input[1..]);
397 assert_ne!(vec.as_ptr(), input_ptr);
398
399 let buffer = Buffer::from_slice_ref(input.as_slice());
401 let scalar_buffer = ScalarBuffer::<u8>::new(buffer, 0, input.len());
402 let vec = Vec::from(scalar_buffer);
403 assert_eq!(vec, input.as_slice());
404 assert_ne!(vec.as_ptr(), input.as_ptr());
405 }
406
407 #[test]
408 fn scalar_buffer_impl_eq() {
409 fn are_equal<T: Eq>(a: &T, b: &T) -> bool {
410 a.eq(b)
411 }
412
413 assert!(
414 are_equal(
415 &ScalarBuffer::<i16>::from(vec![23]),
416 &ScalarBuffer::<i16>::from(vec![23])
417 ),
418 "ScalarBuffer should implement Eq if the inner type does"
419 );
420 }
421}