1use crate::array::{get_offsets_from_buffer, print_long_array};
19use crate::builder::GenericByteBuilder;
20use crate::iterator::ArrayIter;
21use crate::types::ByteArrayType;
22use crate::types::bytes::ByteArrayNativeType;
23use crate::{Array, ArrayAccessor, ArrayRef, OffsetSizeTrait, Scalar};
24use arrow_buffer::{ArrowNativeType, Buffer, MutableBuffer};
25use arrow_buffer::{NullBuffer, OffsetBuffer};
26use arrow_data::{ArrayData, ArrayDataBuilder};
27use arrow_schema::{ArrowError, DataType};
28use std::any::Any;
29use std::sync::Arc;
30
31pub struct GenericByteArray<T: ByteArrayType> {
88 data_type: DataType,
89 value_offsets: OffsetBuffer<T::Offset>,
90 value_data: Buffer,
91 nulls: Option<NullBuffer>,
92}
93
94impl<T: ByteArrayType> Clone for GenericByteArray<T> {
95 fn clone(&self) -> Self {
96 Self {
97 data_type: T::DATA_TYPE,
98 value_offsets: self.value_offsets.clone(),
99 value_data: self.value_data.clone(),
100 nulls: self.nulls.clone(),
101 }
102 }
103}
104
105impl<T: ByteArrayType> GenericByteArray<T> {
106 pub const DATA_TYPE: DataType = T::DATA_TYPE;
108
109 pub fn new(
115 offsets: OffsetBuffer<T::Offset>,
116 values: Buffer,
117 nulls: Option<NullBuffer>,
118 ) -> Self {
119 Self::try_new(offsets, values, nulls).unwrap()
120 }
121
122 pub fn try_new(
129 offsets: OffsetBuffer<T::Offset>,
130 values: Buffer,
131 nulls: Option<NullBuffer>,
132 ) -> Result<Self, ArrowError> {
133 let len = offsets.len() - 1;
134
135 T::validate(&offsets, &values)?;
137
138 if let Some(n) = nulls.as_ref()
139 && n.len() != len
140 {
141 return Err(ArrowError::InvalidArgumentError(format!(
142 "Incorrect length of null buffer for {}{}Array, expected {len} got {}",
143 T::Offset::PREFIX,
144 T::PREFIX,
145 n.len(),
146 )));
147 }
148
149 Ok(Self {
150 data_type: T::DATA_TYPE,
151 value_offsets: offsets,
152 value_data: values,
153 nulls,
154 })
155 }
156
157 pub unsafe fn new_unchecked(
163 offsets: OffsetBuffer<T::Offset>,
164 values: Buffer,
165 nulls: Option<NullBuffer>,
166 ) -> Self {
167 if cfg!(feature = "force_validate") {
168 return Self::new(offsets, values, nulls);
169 }
170 Self {
171 data_type: T::DATA_TYPE,
172 value_offsets: offsets,
173 value_data: values,
174 nulls,
175 }
176 }
177
178 pub fn new_null(len: usize) -> Self {
180 Self {
181 data_type: T::DATA_TYPE,
182 value_offsets: OffsetBuffer::new_zeroed(len),
183 value_data: MutableBuffer::new(0).into(),
184 nulls: Some(NullBuffer::new_null(len)),
185 }
186 }
187
188 pub fn new_scalar(value: impl AsRef<T::Native>) -> Scalar<Self> {
190 Scalar::new(Self::from_iter_values(std::iter::once(value)))
191 }
192
193 pub fn new_repeated(value: impl AsRef<T::Native>, repeat_count: usize) -> Self {
199 let s: &[u8] = value.as_ref().as_ref();
200 let value_offsets = OffsetBuffer::from_repeated_length(s.len(), repeat_count);
201 let bytes: Buffer = {
202 let mut mutable_buffer = MutableBuffer::with_capacity(0);
203 mutable_buffer.repeat_slice_n_times(s, repeat_count);
204
205 mutable_buffer.into()
206 };
207
208 Self {
209 data_type: T::DATA_TYPE,
210 value_data: bytes,
211 value_offsets,
212 nulls: None,
213 }
214 }
215
216 pub fn from_iter_values<Ptr, I>(iter: I) -> Self
221 where
222 Ptr: AsRef<T::Native>,
223 I: IntoIterator<Item = Ptr>,
224 {
225 let iter = iter.into_iter();
226 let (lower, upper) = iter.size_hint();
229 let capacity = upper.unwrap_or(lower);
230
231 let mut offsets = MutableBuffer::new(
232 capacity
233 .saturating_add(1)
234 .saturating_mul(std::mem::size_of::<T::Offset>()),
235 );
236 offsets.push(T::Offset::usize_as(0));
237
238 let mut values = MutableBuffer::new(0);
239 for s in iter {
240 let s: &[u8] = s.as_ref().as_ref();
241 values.extend_from_slice(s);
242 offsets.push(T::Offset::usize_as(values.len()));
243 }
244
245 T::Offset::from_usize(values.len()).expect("offset overflow");
246 let offsets = Buffer::from(offsets);
247
248 let value_offsets = unsafe { OffsetBuffer::new_unchecked(offsets.into()) };
250
251 Self {
252 data_type: T::DATA_TYPE,
253 value_data: values.into(),
254 value_offsets,
255 nulls: None,
256 }
257 }
258
259 pub fn into_parts(self) -> (OffsetBuffer<T::Offset>, Buffer, Option<NullBuffer>) {
261 (self.value_offsets, self.value_data, self.nulls)
262 }
263
264 #[inline]
268 pub fn value_length(&self, i: usize) -> T::Offset {
269 let offsets = self.value_offsets();
270 offsets[i + 1] - offsets[i]
271 }
272
273 #[inline]
278 pub fn offsets(&self) -> &OffsetBuffer<T::Offset> {
279 &self.value_offsets
280 }
281
282 #[inline]
287 pub fn values(&self) -> &Buffer {
288 &self.value_data
289 }
290
291 pub fn value_data(&self) -> &[u8] {
293 self.value_data.as_slice()
294 }
295
296 pub fn is_ascii(&self) -> bool {
298 let offsets = &self.value_offsets;
299 self.value_data()[offsets.first().as_usize()..offsets.last().as_usize()].is_ascii()
300 }
301
302 #[inline]
304 pub fn value_offsets(&self) -> &[T::Offset] {
305 &self.value_offsets
306 }
307
308 pub unsafe fn value_unchecked(&self, i: usize) -> &T::Native {
316 let end = *unsafe { self.value_offsets().get_unchecked(i + 1) };
317 let start = *unsafe { self.value_offsets().get_unchecked(i) };
318
319 let b = unsafe {
329 std::slice::from_raw_parts(
330 self.value_data
331 .as_ptr()
332 .offset(start.to_isize().unwrap_unchecked()),
333 (end - start).to_usize().unwrap_unchecked(),
334 )
335 };
336
337 unsafe { T::Native::from_bytes_unchecked(b) }
340 }
341
342 pub fn value(&self, i: usize) -> &T::Native {
350 assert!(
351 i < self.len(),
352 "Trying to access an element at index {} from a {}{}Array of length {}",
353 i,
354 T::Offset::PREFIX,
355 T::PREFIX,
356 self.len()
357 );
358 unsafe { self.value_unchecked(i) }
361 }
362
363 pub fn iter(&self) -> ArrayIter<&Self> {
365 ArrayIter::new(self)
366 }
367
368 pub fn slice(&self, offset: usize, length: usize) -> Self {
373 Self {
374 data_type: T::DATA_TYPE,
375 value_offsets: self.value_offsets.slice(offset, length),
376 value_data: self.value_data.clone(),
377 nulls: self.nulls.as_ref().map(|n| n.slice(offset, length)),
378 }
379 }
380
381 pub fn into_builder(self) -> Result<GenericByteBuilder<T>, Self> {
384 let len = self.len();
385 let value_len = T::Offset::as_usize(self.value_offsets()[len] - self.value_offsets()[0]);
386
387 let data = self.into_data();
388 let null_bit_buffer = data.nulls().map(|b| b.inner().sliced());
389
390 let element_len = std::mem::size_of::<T::Offset>();
391 let offset_buffer = data.buffers()[0]
392 .slice_with_length(data.offset() * element_len, (len + 1) * element_len);
393
394 let element_len = std::mem::size_of::<u8>();
395 let value_buffer = data.buffers()[1]
396 .slice_with_length(data.offset() * element_len, value_len * element_len);
397
398 drop(data);
399
400 let try_mutable_null_buffer = match null_bit_buffer {
401 None => Ok(None),
402 Some(null_buffer) => {
403 null_buffer.into_mutable().map(Some)
405 }
406 };
407
408 let try_mutable_buffers = match try_mutable_null_buffer {
409 Ok(mutable_null_buffer) => {
410 let try_mutable_offset_buffer = offset_buffer.into_mutable();
412 let try_mutable_value_buffer = value_buffer.into_mutable();
413
414 match (try_mutable_offset_buffer, try_mutable_value_buffer) {
417 (Ok(mutable_offset_buffer), Ok(mutable_value_buffer)) => unsafe {
418 Ok(GenericByteBuilder::<T>::new_from_buffer(
419 mutable_offset_buffer,
420 mutable_value_buffer,
421 mutable_null_buffer,
422 ))
423 },
424 (Ok(mutable_offset_buffer), Err(value_buffer)) => Err((
425 mutable_offset_buffer.into(),
426 value_buffer,
427 mutable_null_buffer.map(|b| b.into()),
428 )),
429 (Err(offset_buffer), Ok(mutable_value_buffer)) => Err((
430 offset_buffer,
431 mutable_value_buffer.into(),
432 mutable_null_buffer.map(|b| b.into()),
433 )),
434 (Err(offset_buffer), Err(value_buffer)) => Err((
435 offset_buffer,
436 value_buffer,
437 mutable_null_buffer.map(|b| b.into()),
438 )),
439 }
440 }
441 Err(mutable_null_buffer) => {
442 Err((offset_buffer, value_buffer, Some(mutable_null_buffer)))
444 }
445 };
446
447 match try_mutable_buffers {
448 Ok(builder) => Ok(builder),
449 Err((offset_buffer, value_buffer, null_bit_buffer)) => {
450 let builder = ArrayData::builder(T::DATA_TYPE)
451 .len(len)
452 .add_buffer(offset_buffer)
453 .add_buffer(value_buffer)
454 .null_bit_buffer(null_bit_buffer);
455
456 let array_data = unsafe { builder.build_unchecked() };
457 let array = GenericByteArray::<T>::from(array_data);
458
459 Err(array)
460 }
461 }
462 }
463}
464
465impl<T: ByteArrayType> std::fmt::Debug for GenericByteArray<T> {
466 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
467 write!(f, "{}{}Array\n[\n", T::Offset::PREFIX, T::PREFIX)?;
468 print_long_array(self, f, &mut |index, f| {
469 std::fmt::Debug::fmt(&self.value(index), f)
470 })?;
471 write!(f, "]")
472 }
473}
474
475unsafe impl<T: ByteArrayType> Array for GenericByteArray<T> {
477 fn as_any(&self) -> &dyn Any {
478 self
479 }
480
481 fn to_data(&self) -> ArrayData {
482 self.clone().into()
483 }
484
485 fn into_data(self) -> ArrayData {
486 self.into()
487 }
488
489 fn data_type(&self) -> &DataType {
490 &self.data_type
491 }
492
493 fn slice(&self, offset: usize, length: usize) -> ArrayRef {
494 Arc::new(self.slice(offset, length))
495 }
496
497 fn len(&self) -> usize {
498 self.value_offsets.len() - 1
499 }
500
501 fn is_empty(&self) -> bool {
502 self.value_offsets.len() <= 1
503 }
504
505 fn shrink_to_fit(&mut self) {
506 self.value_offsets.shrink_to_fit();
507 self.value_data.shrink_to_fit();
508 if let Some(nulls) = &mut self.nulls {
509 nulls.shrink_to_fit();
510 }
511 }
512
513 fn offset(&self) -> usize {
514 0
515 }
516
517 fn nulls(&self) -> Option<&NullBuffer> {
518 self.nulls.as_ref()
519 }
520
521 fn logical_null_count(&self) -> usize {
522 self.null_count()
524 }
525
526 fn get_buffer_memory_size(&self) -> usize {
527 let mut sum = self.value_offsets.inner().inner().capacity();
528 sum += self.value_data.capacity();
529 if let Some(x) = &self.nulls {
530 sum += x.buffer().capacity()
531 }
532 sum
533 }
534
535 fn get_array_memory_size(&self) -> usize {
536 std::mem::size_of::<Self>() + self.get_buffer_memory_size()
537 }
538
539 #[cfg(feature = "pool")]
540 fn claim(&self, pool: &dyn arrow_buffer::MemoryPool) {
541 self.value_offsets.claim(pool);
542 self.value_data.claim(pool);
543 if let Some(nulls) = &self.nulls {
544 nulls.claim(pool);
545 }
546 }
547}
548
549impl<'a, T: ByteArrayType> ArrayAccessor for &'a GenericByteArray<T> {
550 type Item = &'a T::Native;
551
552 fn value(&self, index: usize) -> Self::Item {
553 GenericByteArray::value(self, index)
554 }
555
556 unsafe fn value_unchecked(&self, index: usize) -> Self::Item {
557 unsafe { GenericByteArray::value_unchecked(self, index) }
558 }
559}
560
561impl<T: ByteArrayType> From<ArrayData> for GenericByteArray<T> {
562 fn from(data: ArrayData) -> Self {
563 let (data_type, len, nulls, offset, mut buffers, _child_data) = data.into_parts();
564 assert_eq!(
565 data_type,
566 Self::DATA_TYPE,
567 "{}{}Array expects DataType::{}",
568 T::Offset::PREFIX,
569 T::PREFIX,
570 Self::DATA_TYPE
571 );
572 assert_eq!(
573 buffers.len(),
574 2,
575 "{}{}Array data should contain 2 buffers only (offsets and values)",
576 T::Offset::PREFIX,
577 T::PREFIX,
578 );
579 let value_data = buffers.pop().expect("checked above");
581 let offset_buffer = buffers.pop().expect("checked above");
582
583 let value_offsets = unsafe { get_offsets_from_buffer(offset_buffer, offset, len) };
586 Self {
587 data_type,
588 value_offsets,
589 value_data,
590 nulls,
591 }
592 }
593}
594
595impl<T: ByteArrayType> From<GenericByteArray<T>> for ArrayData {
596 fn from(array: GenericByteArray<T>) -> Self {
597 let len = array.len();
598
599 let offsets = array.value_offsets.into_inner().into_inner();
600 let builder = ArrayDataBuilder::new(array.data_type)
601 .len(len)
602 .buffers(vec![offsets, array.value_data])
603 .nulls(array.nulls);
604
605 unsafe { builder.build_unchecked() }
606 }
607}
608
609impl<'a, T: ByteArrayType> IntoIterator for &'a GenericByteArray<T> {
610 type Item = Option<&'a T::Native>;
611 type IntoIter = ArrayIter<Self>;
612
613 fn into_iter(self) -> Self::IntoIter {
614 ArrayIter::new(self)
615 }
616}
617
618impl<'a, Ptr, T: ByteArrayType> FromIterator<&'a Option<Ptr>> for GenericByteArray<T>
619where
620 Ptr: AsRef<T::Native> + 'a,
621{
622 fn from_iter<I: IntoIterator<Item = &'a Option<Ptr>>>(iter: I) -> Self {
623 iter.into_iter()
624 .map(|o| o.as_ref().map(|p| p.as_ref()))
625 .collect()
626 }
627}
628
629impl<Ptr, T: ByteArrayType> FromIterator<Option<Ptr>> for GenericByteArray<T>
630where
631 Ptr: AsRef<T::Native>,
632{
633 fn from_iter<I: IntoIterator<Item = Option<Ptr>>>(iter: I) -> Self {
634 let iter = iter.into_iter();
635 let mut builder = GenericByteBuilder::with_capacity(iter.size_hint().0, 1024);
636 builder.extend(iter);
637 builder.finish()
638 }
639}
640
641#[cfg(test)]
642mod tests {
643 use crate::{Array, BinaryArray, StringArray};
644 use arrow_buffer::{Buffer, NullBuffer, OffsetBuffer};
645
646 #[test]
649 fn from_iter_values_untrusted_size_hint() {
650 let no_upper_bound = (0..20).filter(|i| i % 2 == 0).map(|i| format!("v{i}"));
652 assert_eq!(no_upper_bound.size_hint(), (0, Some(20)));
653 let array = StringArray::from_iter_values(no_upper_bound);
654 assert_eq!(array.len(), 10);
655 assert_eq!(array.value(0), "v0");
656 assert_eq!(array.value(9), "v18");
657
658 let too_large_upper_bound = (0..).map(|i| format!("v{i}")).take_while(|v| v != "v3");
660 assert_eq!(too_large_upper_bound.size_hint(), (0, None));
661 let array = StringArray::from_iter_values(too_large_upper_bound);
662 assert_eq!(array.len(), 3);
663 assert_eq!(array.value(2), "v2");
664 }
665
666 #[test]
667 fn try_new() {
668 let data = Buffer::from_slice_ref("helloworld");
669 let offsets = OffsetBuffer::new(vec![0, 5, 10].into());
670 StringArray::new(offsets.clone(), data.clone(), None);
671
672 let nulls = NullBuffer::new_null(3);
673 let err =
674 StringArray::try_new(offsets.clone(), data.clone(), Some(nulls.clone())).unwrap_err();
675 assert_eq!(
676 err.to_string(),
677 "Invalid argument error: Incorrect length of null buffer for StringArray, expected 2 got 3"
678 );
679
680 let err = BinaryArray::try_new(offsets.clone(), data.clone(), Some(nulls)).unwrap_err();
681 assert_eq!(
682 err.to_string(),
683 "Invalid argument error: Incorrect length of null buffer for BinaryArray, expected 2 got 3"
684 );
685
686 let non_utf8_data = Buffer::from_slice_ref(b"he\xFFloworld");
687 let err = StringArray::try_new(offsets.clone(), non_utf8_data.clone(), None).unwrap_err();
688 assert_eq!(
689 err.to_string(),
690 "Invalid argument error: Encountered non UTF-8 data: invalid utf-8 sequence of 1 bytes from index 2"
691 );
692
693 BinaryArray::new(offsets, non_utf8_data, None);
694
695 let offsets = OffsetBuffer::new(vec![0, 5, 11].into());
696 let err = StringArray::try_new(offsets.clone(), data.clone(), None).unwrap_err();
697 assert_eq!(
698 err.to_string(),
699 "Invalid argument error: Offset of 11 exceeds length of values 10"
700 );
701
702 let err = BinaryArray::try_new(offsets.clone(), data, None).unwrap_err();
703 assert_eq!(
704 err.to_string(),
705 "Invalid argument error: Maximum offset of 11 is larger than values of length 10"
706 );
707
708 let non_ascii_data = Buffer::from_slice_ref("heìloworld");
709 StringArray::new(offsets.clone(), non_ascii_data.clone(), None);
710 BinaryArray::new(offsets, non_ascii_data.clone(), None);
711
712 let offsets = OffsetBuffer::new(vec![0, 3, 10].into());
713 let err = StringArray::try_new(offsets.clone(), non_ascii_data.clone(), None).unwrap_err();
714 assert_eq!(
715 err.to_string(),
716 "Invalid argument error: Split UTF-8 codepoint at offset 3"
717 );
718
719 BinaryArray::new(offsets, non_ascii_data, None);
720 }
721
722 #[test]
723 fn create_repeated() {
724 let arr = BinaryArray::new_repeated(b"hello", 3);
725 assert_eq!(arr.len(), 3);
726 assert_eq!(arr.value(0), b"hello");
727 assert_eq!(arr.value(1), b"hello");
728 assert_eq!(arr.value(2), b"hello");
729
730 let arr = StringArray::new_repeated("world", 2);
731 assert_eq!(arr.len(), 2);
732 assert_eq!(arr.value(0), "world");
733 assert_eq!(arr.value(1), "world");
734 }
735
736 #[test]
737 #[should_panic(expected = "total length overflow: does not fit in usize")]
738 fn create_repeated_usize_overflow_1() {
739 let _arr = BinaryArray::new_repeated(b"hello", (usize::MAX / "hello".len()) + 1);
740 }
741
742 #[test]
743 #[should_panic(expected = "total length overflow: does not fit in usize")]
744 fn create_repeated_usize_overflow_2() {
745 let _arr = BinaryArray::new_repeated(b"hello", usize::MAX);
746 }
747
748 #[test]
749 #[should_panic(expected = "offset overflow")]
750 fn create_repeated_i32_offset_overflow_1() {
751 let _arr = BinaryArray::new_repeated(b"hello", usize::MAX / "hello".len());
752 }
753
754 #[test]
755 #[should_panic(expected = "offset overflow")]
756 fn create_repeated_i32_offset_overflow_2() {
757 let _arr = BinaryArray::new_repeated(b"hello", ((i32::MAX as usize) / "hello".len()) + 1);
758 }
759}