1use crate::array::{get_offsets_from_buffer, print_long_array};
6use crate::builder::GenericByteBuilder;
7use crate::iterator::ArrayIter;
8use crate::types::ByteArrayType;
9use crate::types::bytes::ByteArrayNativeType;
10use crate::{Array, ArrayAccessor, ArrayRef, OffsetSizeTrait, Scalar};
11use arrow_buffer::{ArrowNativeType, Buffer, MutableBuffer};
12use arrow_buffer::{NullBuffer, OffsetBuffer};
13use arrow_data::{ArrayData, ArrayDataBuilder};
14use arrow_schema::{ArrowError, DataType};
15use std::any::Any;
16use std::sync::Arc;
17
18pub struct GenericByteArray<T: ByteArrayType> {
75 data_type: DataType,
76 value_offsets: OffsetBuffer<T::Offset>,
77 value_data: Buffer,
78 nulls: Option<NullBuffer>,
79}
80
81impl<T: ByteArrayType> Clone for GenericByteArray<T> {
82 fn clone(&self) -> Self {
83 Self {
84 data_type: T::DATA_TYPE,
85 value_offsets: self.value_offsets.clone(),
86 value_data: self.value_data.clone(),
87 nulls: self.nulls.clone(),
88 }
89 }
90}
91
92impl<T: ByteArrayType> GenericByteArray<T> {
93 pub const DATA_TYPE: DataType = T::DATA_TYPE;
95
96 pub fn new(
102 offsets: OffsetBuffer<T::Offset>,
103 values: Buffer,
104 nulls: Option<NullBuffer>,
105 ) -> Self {
106 Self::try_new(offsets, values, nulls).unwrap()
107 }
108
109 pub fn try_new(
116 offsets: OffsetBuffer<T::Offset>,
117 values: Buffer,
118 nulls: Option<NullBuffer>,
119 ) -> Result<Self, ArrowError> {
120 let len = offsets.len() - 1;
121
122 T::validate(&offsets, &values)?;
124
125 if let Some(n) = nulls.as_ref()
126 && n.len() != len
127 {
128 return Err(ArrowError::InvalidArgumentError(format!(
129 "Incorrect length of null buffer for {}{}Array, expected {len} got {}",
130 T::Offset::PREFIX,
131 T::PREFIX,
132 n.len(),
133 )));
134 }
135
136 Ok(Self {
137 data_type: T::DATA_TYPE,
138 value_offsets: offsets,
139 value_data: values,
140 nulls,
141 })
142 }
143
144 pub unsafe fn new_unchecked(
150 offsets: OffsetBuffer<T::Offset>,
151 values: Buffer,
152 nulls: Option<NullBuffer>,
153 ) -> Self {
154 if cfg!(feature = "force_validate") {
155 return Self::new(offsets, values, nulls);
156 }
157 Self {
158 data_type: T::DATA_TYPE,
159 value_offsets: offsets,
160 value_data: values,
161 nulls,
162 }
163 }
164
165 pub fn new_null(len: usize) -> Self {
167 Self {
168 data_type: T::DATA_TYPE,
169 value_offsets: OffsetBuffer::new_zeroed(len),
170 value_data: MutableBuffer::new(0).into(),
171 nulls: Some(NullBuffer::new_null(len)),
172 }
173 }
174
175 pub fn new_scalar(value: impl AsRef<T::Native>) -> Scalar<Self> {
177 Scalar::new(Self::from_iter_values(std::iter::once(value)))
178 }
179
180 pub fn new_repeated(value: impl AsRef<T::Native>, repeat_count: usize) -> Self {
186 let s: &[u8] = value.as_ref().as_ref();
187 let value_offsets = OffsetBuffer::from_repeated_length(s.len(), repeat_count);
188 let bytes: Buffer = {
189 let mut mutable_buffer = MutableBuffer::with_capacity(0);
190 mutable_buffer.repeat_slice_n_times(s, repeat_count);
191
192 mutable_buffer.into()
193 };
194
195 Self {
196 data_type: T::DATA_TYPE,
197 value_data: bytes,
198 value_offsets,
199 nulls: None,
200 }
201 }
202
203 pub fn from_iter_values<Ptr, I>(iter: I) -> Self
208 where
209 Ptr: AsRef<T::Native>,
210 I: IntoIterator<Item = Ptr>,
211 {
212 let iter = iter.into_iter();
213 let (lower, upper) = iter.size_hint();
216 let capacity = upper.unwrap_or(lower);
217
218 let mut offsets = MutableBuffer::new(
219 capacity
220 .saturating_add(1)
221 .saturating_mul(std::mem::size_of::<T::Offset>()),
222 );
223 offsets.push(T::Offset::usize_as(0));
224
225 let mut values = MutableBuffer::new(0);
226 for s in iter {
227 let s: &[u8] = s.as_ref().as_ref();
228 values.extend_from_slice(s);
229 offsets.push(T::Offset::usize_as(values.len()));
230 }
231
232 T::Offset::from_usize(values.len()).expect("offset overflow");
233 let offsets = Buffer::from(offsets);
234
235 let value_offsets = unsafe { OffsetBuffer::new_unchecked(offsets.into()) };
237
238 Self {
239 data_type: T::DATA_TYPE,
240 value_data: values.into(),
241 value_offsets,
242 nulls: None,
243 }
244 }
245
246 pub fn into_parts(self) -> (OffsetBuffer<T::Offset>, Buffer, Option<NullBuffer>) {
248 (self.value_offsets, self.value_data, self.nulls)
249 }
250
251 #[inline]
255 pub fn value_length(&self, i: usize) -> T::Offset {
256 let offsets = self.value_offsets();
257 offsets[i + 1] - offsets[i]
258 }
259
260 #[inline]
265 pub fn offsets(&self) -> &OffsetBuffer<T::Offset> {
266 &self.value_offsets
267 }
268
269 #[inline]
275 pub fn values(&self) -> &Buffer {
276 &self.value_data
277 }
278
279 pub fn value_data(&self) -> &[u8] {
285 self.value_data.as_slice()
286 }
287
288 pub fn is_ascii(&self) -> bool {
290 let offsets = &self.value_offsets;
291 self.value_data()[offsets.first().as_usize()..offsets.last().as_usize()].is_ascii()
292 }
293
294 #[inline]
296 pub fn value_offsets(&self) -> &[T::Offset] {
297 &self.value_offsets
298 }
299
300 pub unsafe fn value_unchecked(&self, i: usize) -> &T::Native {
308 let end = *unsafe { self.value_offsets().get_unchecked(i + 1) };
309 let start = *unsafe { self.value_offsets().get_unchecked(i) };
310
311 let b = unsafe {
321 std::slice::from_raw_parts(
322 self.value_data
323 .as_ptr()
324 .offset(start.to_isize().unwrap_unchecked()),
325 (end - start).to_usize().unwrap_unchecked(),
326 )
327 };
328
329 unsafe { T::Native::from_bytes_unchecked(b) }
332 }
333
334 pub fn value(&self, i: usize) -> &T::Native {
342 assert!(
343 i < self.len(),
344 "Trying to access an element at index {} from a {}{}Array of length {}",
345 i,
346 T::Offset::PREFIX,
347 T::PREFIX,
348 self.len()
349 );
350 unsafe { self.value_unchecked(i) }
353 }
354
355 pub fn iter(&self) -> ArrayIter<&Self> {
357 ArrayIter::new(self)
358 }
359
360 pub fn slice(&self, offset: usize, length: usize) -> Self {
365 Self {
366 data_type: T::DATA_TYPE,
367 value_offsets: self.value_offsets.slice(offset, length),
368 value_data: self.value_data.clone(),
369 nulls: self.nulls.as_ref().map(|n| n.slice(offset, length)),
370 }
371 }
372
373 pub fn into_builder(self) -> Result<GenericByteBuilder<T>, Self> {
382 let (offsets, values, nulls) = self.into_parts();
383
384 let rebuild = |offsets: Buffer, values: Buffer, nulls: Option<NullBuffer>| {
386 unsafe {
388 Self::new_unchecked(OffsetBuffer::new_unchecked(offsets.into()), values, nulls)
389 }
390 };
391
392 let offsets = match offsets.into_inner().into_inner().into_mutable() {
396 Ok(offsets) => offsets,
397 Err(offsets) => return Err(rebuild(offsets, values, nulls)),
398 };
399 let values = match values.into_mutable() {
400 Ok(values) => values,
401 Err(values) => return Err(rebuild(offsets.into(), values, nulls)),
402 };
403
404 let nulls = nulls.map(|nulls| {
409 let bits = nulls.into_inner();
410 if bits.offset() == 0 {
411 let len = bits.len();
412 bits.into_inner()
413 .into_mutable()
414 .unwrap_or_else(|buffer| buffer[..len.div_ceil(8)].to_vec().into())
415 } else {
416 bits.sliced().to_vec().into()
418 }
419 });
420
421 Ok(unsafe { GenericByteBuilder::new_from_buffer(offsets, values, nulls) })
423 }
424}
425
426impl<T: ByteArrayType> std::fmt::Debug for GenericByteArray<T> {
427 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
428 write!(f, "{}{}Array\n[\n", T::Offset::PREFIX, T::PREFIX)?;
429 print_long_array(self, f, &mut |index, f| {
430 std::fmt::Debug::fmt(&self.value(index), f)
431 })?;
432 write!(f, "]")
433 }
434}
435
436unsafe impl<T: ByteArrayType> Array for GenericByteArray<T> {
438 fn as_any(&self) -> &dyn Any {
439 self
440 }
441
442 fn to_data(&self) -> ArrayData {
443 self.clone().into()
444 }
445
446 fn into_data(self) -> ArrayData {
447 self.into()
448 }
449
450 fn data_type(&self) -> &DataType {
451 &self.data_type
452 }
453
454 fn slice(&self, offset: usize, length: usize) -> ArrayRef {
455 Arc::new(self.slice(offset, length))
456 }
457
458 fn len(&self) -> usize {
459 self.value_offsets.len() - 1
460 }
461
462 fn is_empty(&self) -> bool {
463 self.value_offsets.len() <= 1
464 }
465
466 fn shrink_to_fit(&mut self) {
467 self.value_offsets.shrink_to_fit();
468 self.value_data.shrink_to_fit();
469 if let Some(nulls) = &mut self.nulls {
470 nulls.shrink_to_fit();
471 }
472 }
473
474 fn offset(&self) -> usize {
475 0
476 }
477
478 fn nulls(&self) -> Option<&NullBuffer> {
479 self.nulls.as_ref()
480 }
481
482 fn logical_null_count(&self) -> usize {
483 self.null_count()
485 }
486
487 fn get_buffer_memory_size(&self) -> usize {
488 let mut sum = self.value_offsets.inner().inner().capacity();
489 sum += self.value_data.capacity();
490 if let Some(x) = &self.nulls {
491 sum += x.buffer().capacity()
492 }
493 sum
494 }
495
496 fn get_array_memory_size(&self) -> usize {
497 std::mem::size_of::<Self>() + self.get_buffer_memory_size()
498 }
499
500 #[cfg(feature = "pool")]
501 fn claim(&self, pool: &dyn arrow_buffer::MemoryPool) {
502 self.value_offsets.claim(pool);
503 self.value_data.claim(pool);
504 if let Some(nulls) = &self.nulls {
505 nulls.claim(pool);
506 }
507 }
508}
509
510impl<'a, T: ByteArrayType> ArrayAccessor for &'a GenericByteArray<T> {
511 type Item = &'a T::Native;
512
513 fn value(&self, index: usize) -> Self::Item {
514 GenericByteArray::value(self, index)
515 }
516
517 unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
518 unsafe { GenericByteArray::value_unchecked(self, index) }
519 }
520}
521
522impl<T: ByteArrayType> From<ArrayData> for GenericByteArray<T> {
523 fn from(data: ArrayData) -> Self {
524 let (data_type, len, nulls, offset, mut buffers, _child_data) = data.into_parts();
525 assert_eq!(
526 data_type,
527 Self::DATA_TYPE,
528 "{}{}Array expects DataType::{}",
529 T::Offset::PREFIX,
530 T::PREFIX,
531 Self::DATA_TYPE
532 );
533 assert_eq!(
534 buffers.len(),
535 2,
536 "{}{}Array data should contain 2 buffers only (offsets and values)",
537 T::Offset::PREFIX,
538 T::PREFIX,
539 );
540 let value_data = buffers.pop().expect("checked above");
542 let offset_buffer = buffers.pop().expect("checked above");
543
544 let value_offsets = unsafe { get_offsets_from_buffer(offset_buffer, offset, len) };
547 Self {
548 data_type,
549 value_offsets,
550 value_data,
551 nulls,
552 }
553 }
554}
555
556impl<T: ByteArrayType> From<GenericByteArray<T>> for ArrayData {
557 fn from(array: GenericByteArray<T>) -> Self {
558 let len = array.len();
559
560 let offsets = array.value_offsets.into_inner().into_inner();
561 let builder = ArrayDataBuilder::new(array.data_type)
562 .len(len)
563 .buffers(vec![offsets, array.value_data])
564 .nulls(array.nulls);
565
566 unsafe { builder.build_unchecked() }
567 }
568}
569
570impl<'a, T: ByteArrayType> IntoIterator for &'a GenericByteArray<T> {
571 type Item = Option<&'a T::Native>;
572 type IntoIter = ArrayIter<Self>;
573
574 fn into_iter(self) -> Self::IntoIter {
575 ArrayIter::new(self)
576 }
577}
578
579impl<'a, Ptr, T: ByteArrayType> FromIterator<&'a Option<Ptr>> for GenericByteArray<T>
580where
581 Ptr: AsRef<T::Native> + 'a,
582{
583 fn from_iter<I: IntoIterator<Item = &'a Option<Ptr>>>(iter: I) -> Self {
584 iter.into_iter()
585 .map(|o| o.as_ref().map(|p| p.as_ref()))
586 .collect()
587 }
588}
589
590impl<Ptr, T: ByteArrayType> FromIterator<Option<Ptr>> for GenericByteArray<T>
591where
592 Ptr: AsRef<T::Native>,
593{
594 fn from_iter<I: IntoIterator<Item = Option<Ptr>>>(iter: I) -> Self {
595 let iter = iter.into_iter();
596 let mut builder = GenericByteBuilder::with_capacity(iter.size_hint().0, 1024);
597 builder.extend(iter);
598 builder.finish()
599 }
600}
601
602#[cfg(test)]
603mod tests {
604 use crate::{Array, BinaryArray, StringArray};
605 use arrow_buffer::{Buffer, NullBuffer, OffsetBuffer};
606
607 #[test]
610 fn from_iter_values_untrusted_size_hint() {
611 let no_upper_bound = (0..20).filter(|i| i % 2 == 0).map(|i| format!("v{i}"));
613 assert_eq!(no_upper_bound.size_hint(), (0, Some(20)));
614 let array = StringArray::from_iter_values(no_upper_bound);
615 assert_eq!(array.len(), 10);
616 assert_eq!(array.value(0), "v0");
617 assert_eq!(array.value(9), "v18");
618
619 let too_large_upper_bound = (0..).map(|i| format!("v{i}")).take_while(|v| v != "v3");
621 assert_eq!(too_large_upper_bound.size_hint(), (0, None));
622 let array = StringArray::from_iter_values(too_large_upper_bound);
623 assert_eq!(array.len(), 3);
624 assert_eq!(array.value(2), "v2");
625 }
626
627 #[test]
628 fn try_new() {
629 let data = Buffer::from_slice_ref("helloworld");
630 let offsets = OffsetBuffer::new(vec![0, 5, 10].into());
631 StringArray::new(offsets.clone(), data.clone(), None);
632
633 let nulls = NullBuffer::new_null(3);
634 let err =
635 StringArray::try_new(offsets.clone(), data.clone(), Some(nulls.clone())).unwrap_err();
636 assert_eq!(
637 err.to_string(),
638 "Invalid argument error: Incorrect length of null buffer for StringArray, expected 2 got 3"
639 );
640
641 let err = BinaryArray::try_new(offsets.clone(), data.clone(), Some(nulls)).unwrap_err();
642 assert_eq!(
643 err.to_string(),
644 "Invalid argument error: Incorrect length of null buffer for BinaryArray, expected 2 got 3"
645 );
646
647 let non_utf8_data = Buffer::from_slice_ref(b"he\xFFloworld");
648 let err = StringArray::try_new(offsets.clone(), non_utf8_data.clone(), None).unwrap_err();
649 assert_eq!(
650 err.to_string(),
651 "Invalid argument error: Encountered non UTF-8 data: invalid utf-8 sequence of 1 bytes from index 2"
652 );
653
654 BinaryArray::new(offsets, non_utf8_data, None);
655
656 let offsets = OffsetBuffer::new(vec![0, 5, 11].into());
657 let err = StringArray::try_new(offsets.clone(), data.clone(), None).unwrap_err();
658 assert_eq!(
659 err.to_string(),
660 "Invalid argument error: Offset of 11 exceeds length of values 10"
661 );
662
663 let err = BinaryArray::try_new(offsets.clone(), data, None).unwrap_err();
664 assert_eq!(
665 err.to_string(),
666 "Invalid argument error: Maximum offset of 11 is larger than values of length 10"
667 );
668
669 let non_ascii_data = Buffer::from_slice_ref("heìloworld");
670 StringArray::new(offsets.clone(), non_ascii_data.clone(), None);
671 BinaryArray::new(offsets, non_ascii_data.clone(), None);
672
673 let offsets = OffsetBuffer::new(vec![0, 3, 10].into());
674 let err = StringArray::try_new(offsets.clone(), non_ascii_data.clone(), None).unwrap_err();
675 assert_eq!(
676 err.to_string(),
677 "Invalid argument error: Split UTF-8 codepoint at offset 3"
678 );
679
680 BinaryArray::new(offsets, non_ascii_data, None);
681 }
682
683 #[test]
684 fn create_repeated() {
685 let arr = BinaryArray::new_repeated(b"hello", 3);
686 assert_eq!(arr.len(), 3);
687 assert_eq!(arr.value(0), b"hello");
688 assert_eq!(arr.value(1), b"hello");
689 assert_eq!(arr.value(2), b"hello");
690
691 let arr = StringArray::new_repeated("world", 2);
692 assert_eq!(arr.len(), 2);
693 assert_eq!(arr.value(0), "world");
694 assert_eq!(arr.value(1), "world");
695 }
696
697 #[test]
698 #[should_panic(expected = "total length overflow: does not fit in usize")]
699 fn create_repeated_usize_overflow_1() {
700 let _arr = BinaryArray::new_repeated(b"hello", (usize::MAX / "hello".len()) + 1);
701 }
702
703 #[test]
704 #[should_panic(expected = "total length overflow: does not fit in usize")]
705 fn create_repeated_usize_overflow_2() {
706 let _arr = BinaryArray::new_repeated(b"hello", usize::MAX);
707 }
708
709 #[test]
710 #[should_panic(expected = "offset overflow")]
711 fn create_repeated_i32_offset_overflow_1() {
712 let _arr = BinaryArray::new_repeated(b"hello", usize::MAX / "hello".len());
713 }
714
715 #[test]
716 #[should_panic(expected = "offset overflow")]
717 fn create_repeated_i32_offset_overflow_2() {
718 let _arr = BinaryArray::new_repeated(b"hello", ((i32::MAX as usize) / "hello".len()) + 1);
719 }
720}