1use crate::builder::ArrayBuilder;
19use crate::types::{ByteArrayType, GenericBinaryType, GenericStringType};
20use crate::{Array, ArrayRef, GenericByteArray, OffsetSizeTrait};
21use arrow_buffer::{ArrowNativeType, Buffer, MutableBuffer, NullBufferBuilder, ScalarBuffer};
22use arrow_data::ArrayDataBuilder;
23use arrow_schema::ArrowError;
24use std::any::Any;
25use std::sync::Arc;
26
27pub struct GenericByteBuilder<T: ByteArrayType> {
32 value_builder: Vec<u8>,
33 offsets_builder: Vec<T::Offset>,
34 null_buffer_builder: NullBufferBuilder,
35}
36
37impl<T: ByteArrayType> GenericByteBuilder<T> {
38 pub fn new() -> Self {
40 Self::with_capacity(1024, 1024)
41 }
42
43 pub fn with_capacity(item_capacity: usize, data_capacity: usize) -> Self {
50 let mut offsets_builder = Vec::with_capacity(item_capacity + 1);
51 offsets_builder.push(T::Offset::from_usize(0).unwrap());
52 Self {
53 value_builder: Vec::with_capacity(data_capacity),
54 offsets_builder,
55 null_buffer_builder: NullBufferBuilder::new(item_capacity),
56 }
57 }
58
59 pub unsafe fn new_from_buffer(
66 offsets_buffer: MutableBuffer,
67 value_buffer: MutableBuffer,
68 null_buffer: Option<MutableBuffer>,
69 ) -> Self {
70 let offsets_builder: Vec<T::Offset> =
71 ScalarBuffer::<T::Offset>::from(offsets_buffer).into();
72 let value_builder: Vec<u8> = ScalarBuffer::<u8>::from(value_buffer).into();
73
74 let null_buffer_builder = null_buffer
75 .map(|buffer| NullBufferBuilder::new_from_buffer(buffer, offsets_builder.len() - 1))
76 .unwrap_or_else(|| NullBufferBuilder::new_with_len(offsets_builder.len() - 1));
77
78 Self {
79 value_builder,
80 offsets_builder,
81 null_buffer_builder,
82 }
83 }
84
85 #[inline]
86 fn next_offset(&self) -> T::Offset {
87 T::Offset::from_usize(self.value_builder.len()).expect("byte array offset overflow")
88 }
89
90 #[inline]
106 pub fn append_value(&mut self, value: impl AsRef<T::Native>) {
107 self.value_builder
108 .extend_from_slice(value.as_ref().as_ref());
109 self.null_buffer_builder.append(true);
110 self.offsets_builder.push(self.next_offset());
111 }
112
113 #[inline]
121 pub fn append_value_n(&mut self, value: impl AsRef<T::Native>, n: usize) {
122 let bytes: &[u8] = value.as_ref().as_ref();
123 self.value_builder.reserve(bytes.len() * n);
124 self.offsets_builder.reserve(n);
125 for _ in 0..n {
126 self.value_builder.extend_from_slice(bytes);
127 self.offsets_builder.push(self.next_offset());
128 }
129 self.null_buffer_builder.append_n_non_nulls(n);
130 }
131
132 #[inline]
143 pub fn append_option(&mut self, value: Option<impl AsRef<T::Native>>) {
144 match value {
145 None => self.append_null(),
146 Some(v) => self.append_value(v),
147 };
148 }
149
150 #[inline]
152 pub fn append_null(&mut self) {
153 self.null_buffer_builder.append(false);
154 self.offsets_builder.push(self.next_offset());
155 }
156
157 #[inline]
159 pub fn append_nulls(&mut self, n: usize) {
160 self.null_buffer_builder.append_n_nulls(n);
161 let next_offset = self.next_offset();
162 self.offsets_builder
163 .extend(std::iter::repeat_n(next_offset, n));
164 }
165
166 #[inline]
169 pub fn append_array(&mut self, array: &GenericByteArray<T>) -> Result<(), ArrowError> {
170 use num_traits::CheckedAdd;
171 if array.len() == 0 {
172 return Ok(());
173 }
174
175 let offsets = array.offsets();
176
177 if self.next_offset() == offsets[0] {
180 self.offsets_builder.extend_from_slice(&offsets[1..]);
181 } else {
182 let shift: T::Offset = self.next_offset() - offsets[0];
184
185 if shift.checked_add(&offsets[offsets.len() - 1]).is_none() {
186 return Err(ArrowError::OffsetOverflowError(
187 shift.as_usize() + offsets[offsets.len() - 1].as_usize(),
188 ));
189 }
190
191 self.offsets_builder
192 .extend(offsets[1..].iter().map(|&offset| offset + shift));
193 }
194
195 self.value_builder.extend_from_slice(
197 &array.values().as_slice()[offsets[0].as_usize()..offsets[array.len()].as_usize()],
198 );
199
200 if let Some(null_buffer) = array.nulls() {
201 self.null_buffer_builder.append_buffer(null_buffer);
202 } else {
203 self.null_buffer_builder.append_n_non_nulls(array.len());
204 }
205 Ok(())
206 }
207
208 pub fn finish(&mut self) -> GenericByteArray<T> {
210 let array_type = T::DATA_TYPE;
211 let array_builder = ArrayDataBuilder::new(array_type)
212 .len(self.len())
213 .add_buffer(std::mem::take(&mut self.offsets_builder).into())
214 .add_buffer(std::mem::take(&mut self.value_builder).into())
215 .nulls(self.null_buffer_builder.finish());
216
217 self.offsets_builder.push(self.next_offset());
218 let array_data = unsafe { array_builder.build_unchecked() };
219 GenericByteArray::from(array_data)
220 }
221
222 pub fn finish_cloned(&self) -> GenericByteArray<T> {
224 let array_type = T::DATA_TYPE;
225 let offset_buffer = Buffer::from_slice_ref(self.offsets_builder.as_slice());
226 let value_buffer = Buffer::from_slice_ref(self.value_builder.as_slice());
227 let array_builder = ArrayDataBuilder::new(array_type)
228 .len(self.len())
229 .add_buffer(offset_buffer)
230 .add_buffer(value_buffer)
231 .nulls(self.null_buffer_builder.finish_cloned());
232
233 let array_data = unsafe { array_builder.build_unchecked() };
234 GenericByteArray::from(array_data)
235 }
236
237 pub fn values_slice(&self) -> &[u8] {
239 self.value_builder.as_slice()
240 }
241
242 pub fn values_capacity(&self) -> usize {
244 self.value_builder.capacity()
245 }
246
247 pub fn offsets_slice(&self) -> &[T::Offset] {
249 self.offsets_builder.as_slice()
250 }
251
252 pub fn offsets_capacity(&self) -> usize {
254 self.offsets_builder.capacity()
255 }
256
257 pub fn validity_slice(&self) -> Option<&[u8]> {
259 self.null_buffer_builder.as_slice()
260 }
261
262 pub fn validity_capacity(&self) -> usize {
264 self.null_buffer_builder.allocated_size()
265 }
266
267 pub fn validity_slice_mut(&mut self) -> Option<&mut [u8]> {
269 self.null_buffer_builder.as_slice_mut()
270 }
271}
272
273impl<T: ByteArrayType> std::fmt::Debug for GenericByteBuilder<T> {
274 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275 write!(f, "{}{}Builder", T::Offset::PREFIX, T::PREFIX)?;
276 f.debug_struct("")
277 .field("value_builder", &self.value_builder)
278 .field("offsets_builder", &self.offsets_builder)
279 .field("null_buffer_builder", &self.null_buffer_builder)
280 .finish()
281 }
282}
283
284impl<T: ByteArrayType> Default for GenericByteBuilder<T> {
285 fn default() -> Self {
286 Self::new()
287 }
288}
289
290impl<T: ByteArrayType> ArrayBuilder for GenericByteBuilder<T> {
291 fn len(&self) -> usize {
293 self.null_buffer_builder.len()
294 }
295
296 fn finish(&mut self) -> ArrayRef {
298 Arc::new(self.finish())
299 }
300
301 fn finish_cloned(&self) -> ArrayRef {
303 Arc::new(self.finish_cloned())
304 }
305
306 fn as_any(&self) -> &dyn Any {
308 self
309 }
310
311 fn as_any_mut(&mut self) -> &mut dyn Any {
313 self
314 }
315
316 fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
318 self
319 }
320}
321
322impl<T: ByteArrayType, V: AsRef<T::Native>> Extend<Option<V>> for GenericByteBuilder<T> {
323 #[inline]
324 fn extend<I: IntoIterator<Item = Option<V>>>(&mut self, iter: I) {
325 for v in iter {
326 self.append_option(v)
327 }
328 }
329}
330
331pub type GenericStringBuilder<O> = GenericByteBuilder<GenericStringType<O>>;
381
382impl<O: OffsetSizeTrait> std::fmt::Write for GenericStringBuilder<O> {
383 fn write_str(&mut self, s: &str) -> std::fmt::Result {
384 self.value_builder.extend_from_slice(s.as_bytes());
385 Ok(())
386 }
387}
388
389const AVERAGE_STRING_LENGTH: usize = 16;
400pub trait StringLikeArrayBuilder: ArrayBuilder {
405 fn type_name() -> &'static str;
407
408 fn with_capacity(capacity: usize) -> Self;
410
411 fn append_value(&mut self, value: &str);
413
414 fn append_null(&mut self);
416}
417
418impl<O: OffsetSizeTrait> StringLikeArrayBuilder for GenericStringBuilder<O> {
419 fn type_name() -> &'static str {
420 std::any::type_name::<Self>()
421 }
422 fn with_capacity(capacity: usize) -> Self {
423 Self::with_capacity(capacity, capacity * AVERAGE_STRING_LENGTH)
424 }
425 fn append_value(&mut self, value: &str) {
426 Self::append_value(self, value);
427 }
428 fn append_null(&mut self) {
429 Self::append_null(self);
430 }
431}
432
433const AVERAGE_BINARY_LENGTH: usize = 128;
444pub trait BinaryLikeArrayBuilder: ArrayBuilder {
449 fn type_name() -> &'static str;
451
452 fn with_capacity(capacity: usize) -> Self;
454
455 fn append_value(&mut self, value: &[u8]);
457
458 fn append_null(&mut self);
460}
461
462impl<O: OffsetSizeTrait> BinaryLikeArrayBuilder for GenericBinaryBuilder<O> {
463 fn type_name() -> &'static str {
464 std::any::type_name::<Self>()
465 }
466 fn with_capacity(capacity: usize) -> Self {
467 Self::with_capacity(capacity, capacity * AVERAGE_BINARY_LENGTH)
468 }
469 fn append_value(&mut self, value: &[u8]) {
470 Self::append_value(self, value);
471 }
472 fn append_null(&mut self) {
473 Self::append_null(self);
474 }
475}
476
477pub type GenericBinaryBuilder<O> = GenericByteBuilder<GenericBinaryType<O>>;
523
524impl<O: OffsetSizeTrait> std::io::Write for GenericBinaryBuilder<O> {
525 fn write(&mut self, bs: &[u8]) -> std::io::Result<usize> {
526 self.value_builder.extend_from_slice(bs);
527 Ok(bs.len())
528 }
529
530 fn flush(&mut self) -> std::io::Result<()> {
531 Ok(())
532 }
533}
534
535#[cfg(test)]
536mod tests {
537 use super::*;
538 use crate::GenericStringArray;
539 use crate::array::Array;
540 use arrow_buffer::NullBuffer;
541 use std::fmt::Write as _;
542 use std::io::Write as _;
543
544 fn _test_generic_binary_builder<O: OffsetSizeTrait>() {
545 let mut builder = GenericBinaryBuilder::<O>::new();
546
547 builder.append_value(b"hello");
548 builder.append_value(b"");
549 builder.append_null();
550 builder.append_value(b"rust");
551
552 let array = builder.finish();
553
554 assert_eq!(4, array.len());
555 assert_eq!(1, array.null_count());
556 assert_eq!(b"hello", array.value(0));
557 assert_eq!([] as [u8; 0], array.value(1));
558 assert!(array.is_null(2));
559 assert_eq!(b"rust", array.value(3));
560 assert_eq!(O::from_usize(5).unwrap(), array.value_offsets()[2]);
561 assert_eq!(O::from_usize(4).unwrap(), array.value_length(3));
562 }
563
564 #[test]
565 fn test_binary_builder() {
566 _test_generic_binary_builder::<i32>()
567 }
568
569 #[test]
570 fn test_large_binary_builder() {
571 _test_generic_binary_builder::<i64>()
572 }
573
574 fn _test_generic_binary_builder_all_nulls<O: OffsetSizeTrait>() {
575 let mut builder = GenericBinaryBuilder::<O>::new();
576 builder.append_null();
577 builder.append_null();
578 builder.append_null();
579 builder.append_nulls(2);
580 assert_eq!(5, builder.len());
581 assert!(!builder.is_empty());
582
583 let array = builder.finish();
584 assert_eq!(5, array.null_count());
585 assert_eq!(5, array.len());
586 assert!(array.is_null(0));
587 assert!(array.is_null(1));
588 assert!(array.is_null(2));
589 assert!(array.is_null(3));
590 assert!(array.is_null(4));
591 }
592
593 #[test]
594 fn test_binary_builder_all_nulls() {
595 _test_generic_binary_builder_all_nulls::<i32>()
596 }
597
598 #[test]
599 fn test_large_binary_builder_all_nulls() {
600 _test_generic_binary_builder_all_nulls::<i64>()
601 }
602
603 fn _test_generic_binary_builder_reset<O: OffsetSizeTrait>() {
604 let mut builder = GenericBinaryBuilder::<O>::new();
605
606 builder.append_value(b"hello");
607 builder.append_value(b"");
608 builder.append_null();
609 builder.append_value(b"rust");
610 builder.finish();
611
612 assert!(builder.is_empty());
613
614 builder.append_value(b"parquet");
615 builder.append_null();
616 builder.append_value(b"arrow");
617 builder.append_value(b"");
618 builder.append_nulls(2);
619 builder.append_value(b"hi");
620 let array = builder.finish();
621
622 assert_eq!(7, array.len());
623 assert_eq!(3, array.null_count());
624 assert_eq!(b"parquet", array.value(0));
625 assert!(array.is_null(1));
626 assert!(array.is_null(4));
627 assert!(array.is_null(5));
628 assert_eq!(b"arrow", array.value(2));
629 assert_eq!(b"", array.value(1));
630 assert_eq!(b"hi", array.value(6));
631
632 assert_eq!(O::zero(), array.value_offsets()[0]);
633 assert_eq!(O::from_usize(7).unwrap(), array.value_offsets()[2]);
634 assert_eq!(O::from_usize(14).unwrap(), array.value_offsets()[7]);
635 assert_eq!(O::from_usize(5).unwrap(), array.value_length(2));
636 }
637
638 #[test]
639 fn test_binary_builder_reset() {
640 _test_generic_binary_builder_reset::<i32>()
641 }
642
643 #[test]
644 fn test_large_binary_builder_reset() {
645 _test_generic_binary_builder_reset::<i64>()
646 }
647
648 fn _test_generic_string_array_builder<O: OffsetSizeTrait>() {
649 let mut builder = GenericStringBuilder::<O>::new();
650 let owned = "arrow".to_owned();
651
652 builder.append_value("hello");
653 builder.append_value("");
654 builder.append_value(&owned);
655 builder.append_null();
656 builder.append_option(Some("rust"));
657 builder.append_option(None::<&str>);
658 builder.append_option(None::<String>);
659 builder.append_nulls(2);
660 builder.append_value("parquet");
661 assert_eq!(10, builder.len());
662
663 assert_eq!(
664 GenericStringArray::<O>::from(vec![
665 Some("hello"),
666 Some(""),
667 Some("arrow"),
668 None,
669 Some("rust"),
670 None,
671 None,
672 None,
673 None,
674 Some("parquet")
675 ]),
676 builder.finish()
677 );
678 }
679
680 #[test]
681 fn test_string_array_builder() {
682 _test_generic_string_array_builder::<i32>()
683 }
684
685 #[test]
686 fn test_large_string_array_builder() {
687 _test_generic_string_array_builder::<i64>()
688 }
689
690 fn _test_generic_string_array_builder_finish<O: OffsetSizeTrait>() {
691 let mut builder = GenericStringBuilder::<O>::with_capacity(3, 11);
692
693 builder.append_value("hello");
694 builder.append_value("rust");
695 builder.append_null();
696
697 builder.finish();
698 assert!(builder.is_empty());
699 assert_eq!(&[O::zero()], builder.offsets_slice());
700
701 builder.append_value("arrow");
702 builder.append_value("parquet");
703 let arr = builder.finish();
704 assert!(arr.nulls().is_none());
706 assert_eq!(GenericStringArray::<O>::from(vec!["arrow", "parquet"]), arr,)
707 }
708
709 #[test]
710 fn test_string_array_builder_finish() {
711 _test_generic_string_array_builder_finish::<i32>()
712 }
713
714 #[test]
715 fn test_large_string_array_builder_finish() {
716 _test_generic_string_array_builder_finish::<i64>()
717 }
718
719 fn _test_generic_string_array_builder_finish_cloned<O: OffsetSizeTrait>() {
720 let mut builder = GenericStringBuilder::<O>::with_capacity(3, 11);
721
722 builder.append_value("hello");
723 builder.append_value("rust");
724 builder.append_null();
725
726 let mut arr = builder.finish_cloned();
727 assert!(!builder.is_empty());
728 assert_eq!(3, arr.len());
729
730 builder.append_value("arrow");
731 builder.append_value("parquet");
732 arr = builder.finish();
733
734 assert!(arr.nulls().is_some());
735 assert_eq!(&[O::zero()], builder.offsets_slice());
736 assert_eq!(5, arr.len());
737 }
738
739 #[test]
740 fn test_string_array_builder_finish_cloned() {
741 _test_generic_string_array_builder_finish_cloned::<i32>()
742 }
743
744 #[test]
745 fn test_large_string_array_builder_finish_cloned() {
746 _test_generic_string_array_builder_finish_cloned::<i64>()
747 }
748
749 #[test]
750 fn test_extend() {
751 let mut builder = GenericStringBuilder::<i32>::new();
752 builder.extend(["a", "b", "c", "", "a", "b", "c"].into_iter().map(Some));
753 builder.extend(["d", "cupcakes", "hello"].into_iter().map(Some));
754 let array = builder.finish();
755 assert_eq!(array.value_offsets(), &[0, 1, 2, 3, 3, 4, 5, 6, 7, 15, 20]);
756 assert_eq!(array.value_data(), b"abcabcdcupcakeshello");
757 }
758
759 #[test]
760 fn test_write_str() {
761 let mut builder = GenericStringBuilder::<i32>::new();
762 write!(builder, "foo").unwrap();
763 builder.append_value("");
764 writeln!(builder, "bar").unwrap();
765 builder.append_value("");
766 write!(builder, "fiz").unwrap();
767 write!(builder, "buz").unwrap();
768 builder.append_value("");
769 let a = builder.finish();
770 let r: Vec<_> = a.iter().flatten().collect();
771 assert_eq!(r, &["foo", "bar\n", "fizbuz"])
772 }
773
774 #[test]
775 fn test_write_bytes() {
776 let mut builder = GenericBinaryBuilder::<i32>::new();
777 write!(builder, "foo").unwrap();
778 builder.append_value("");
779 writeln!(builder, "bar").unwrap();
780 builder.append_value("");
781 write!(builder, "fiz").unwrap();
782 write!(builder, "buz").unwrap();
783 builder.append_value("");
784 let a = builder.finish();
785 let r: Vec<_> = a.iter().flatten().collect();
786 assert_eq!(
787 r,
788 &["foo".as_bytes(), "bar\n".as_bytes(), "fizbuz".as_bytes()]
789 )
790 }
791
792 #[test]
793 fn test_append_array_without_nulls() {
794 let input = vec![
795 "hello", "world", "how", "are", "you", "doing", "today", "I", "am", "doing", "well",
796 "thank", "you", "for", "asking",
797 ];
798 let arr1 = GenericStringArray::<i32>::from(input[..3].to_vec());
799 let arr2 = GenericStringArray::<i32>::from(input[3..7].to_vec());
800 let arr3 = GenericStringArray::<i32>::from(input[7..].to_vec());
801
802 let mut builder = GenericStringBuilder::<i32>::new();
803 builder.append_array(&arr1).unwrap();
804 builder.append_array(&arr2).unwrap();
805 builder.append_array(&arr3).unwrap();
806
807 let actual = builder.finish();
808 let expected = GenericStringArray::<i32>::from(input);
809
810 assert_eq!(actual, expected);
811 }
812
813 #[test]
814 fn test_append_array_with_nulls() {
815 let input = vec![
816 Some("hello"),
817 None,
818 Some("how"),
819 None,
820 None,
821 None,
822 None,
823 Some("I"),
824 Some("am"),
825 Some("doing"),
826 Some("well"),
827 ];
828 let arr1 = GenericStringArray::<i32>::from(input[..3].to_vec());
829 let arr2 = GenericStringArray::<i32>::from(input[3..7].to_vec());
830 let arr3 = GenericStringArray::<i32>::from(input[7..].to_vec());
831
832 let mut builder = GenericStringBuilder::<i32>::new();
833 builder.append_array(&arr1).unwrap();
834 builder.append_array(&arr2).unwrap();
835 builder.append_array(&arr3).unwrap();
836
837 let actual = builder.finish();
838 let expected = GenericStringArray::<i32>::from(input);
839
840 assert_eq!(actual, expected);
841 }
842
843 #[test]
844 fn test_append_empty_array() {
845 let arr = GenericStringArray::<i32>::from(Vec::<&str>::new());
846 let mut builder = GenericStringBuilder::<i32>::new();
847 builder.append_array(&arr).unwrap();
848 let result = builder.finish();
849 assert_eq!(result.len(), 0);
850 }
851
852 #[test]
853 fn test_append_array_with_offset_not_starting_at_0() {
854 let input = vec![
855 Some("hello"),
856 None,
857 Some("how"),
858 None,
859 None,
860 None,
861 None,
862 Some("I"),
863 Some("am"),
864 Some("doing"),
865 Some("well"),
866 ];
867 let full_array = GenericStringArray::<i32>::from(input);
868 let sliced = full_array.slice(1, 4);
869
870 assert_ne!(sliced.offsets()[0].as_usize(), 0);
871 assert_ne!(sliced.offsets().last(), full_array.offsets().last());
872
873 let mut builder = GenericStringBuilder::<i32>::new();
874 builder.append_array(&sliced).unwrap();
875 let actual = builder.finish();
876
877 let expected = GenericStringArray::<i32>::from(vec![None, Some("how"), None, None]);
878
879 assert_eq!(actual, expected);
880 }
881
882 #[test]
883 fn test_append_underlying_null_values_added_as_is() {
884 let input_1_array_with_nulls = {
885 let input = vec![
886 "hello", "world", "how", "are", "you", "doing", "today", "I", "am",
887 ];
888 let (offsets, buffer, _) = GenericStringArray::<i32>::from(input).into_parts();
889
890 GenericStringArray::<i32>::new(
891 offsets,
892 buffer,
893 Some(NullBuffer::from(&[
894 true, false, true, false, false, true, true, true, false,
895 ])),
896 )
897 };
898 let input_2_array_with_nulls = {
899 let input = vec!["doing", "well", "thank", "you", "for", "asking"];
900 let (offsets, buffer, _) = GenericStringArray::<i32>::from(input).into_parts();
901
902 GenericStringArray::<i32>::new(
903 offsets,
904 buffer,
905 Some(NullBuffer::from(&[false, false, true, false, true, true])),
906 )
907 };
908
909 let mut builder = GenericStringBuilder::<i32>::new();
910 builder.append_array(&input_1_array_with_nulls).unwrap();
911 builder.append_array(&input_2_array_with_nulls).unwrap();
912
913 let actual = builder.finish();
914 let expected = GenericStringArray::<i32>::from(vec![
915 Some("hello"),
916 None, Some("how"),
918 None, None, Some("doing"),
921 Some("today"),
922 Some("I"),
923 None, None, None, Some("thank"),
927 None, Some("for"),
929 Some("asking"),
930 ]);
931
932 assert_eq!(actual, expected);
933
934 let expected_underlying_buffer = Buffer::from(
935 [
936 "hello", "world", "how", "are", "you", "doing", "today", "I", "am", "doing",
937 "well", "thank", "you", "for", "asking",
938 ]
939 .join("")
940 .as_bytes(),
941 );
942 assert_eq!(actual.values(), &expected_underlying_buffer);
943 }
944
945 #[test]
946 fn append_array_with_continues_indices() {
947 let input = vec![
948 "hello", "world", "how", "are", "you", "doing", "today", "I", "am", "doing", "well",
949 "thank", "you", "for", "asking",
950 ];
951 let full_array = GenericStringArray::<i32>::from(input);
952 let slice1 = full_array.slice(0, 3);
953 let slice2 = full_array.slice(3, 4);
954 let slice3 = full_array.slice(7, full_array.len() - 7);
955
956 let mut builder = GenericStringBuilder::<i32>::new();
957 builder.append_array(&slice1).unwrap();
958 builder.append_array(&slice2).unwrap();
959 builder.append_array(&slice3).unwrap();
960
961 let actual = builder.finish();
962
963 assert_eq!(actual, full_array);
964 }
965
966 #[test]
967 fn test_append_array_offset_overflow_precise() {
968 let mut builder = GenericStringBuilder::<i32>::new();
969
970 let initial_string = "x".repeat(i32::MAX as usize - 100);
971 builder.append_value(&initial_string);
972
973 let overflow_string = "y".repeat(200);
974 let overflow_array = GenericStringArray::<i32>::from(vec![overflow_string.as_str()]);
975
976 let result = builder.append_array(&overflow_array);
977
978 assert!(matches!(result, Err(ArrowError::OffsetOverflowError(_))));
979 }
980
981 #[test]
982 fn test_append_value_n() {
983 let mut builder = GenericStringBuilder::<i32>::new();
984 builder.append_value("hello");
985 builder.append_value_n("world", 3);
986 builder.append_null();
987 let array = builder.finish();
988
989 assert_eq!(5, array.len());
990 assert_eq!(1, array.null_count());
991 assert_eq!("hello", array.value(0));
992 assert_eq!("world", array.value(1));
993 assert_eq!("world", array.value(2));
994 assert_eq!("world", array.value(3));
995 assert!(array.is_null(4));
996 }
997}