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() };
220 GenericByteArray::from(array_data)
221 }
222
223 pub fn finish_cloned(&self) -> GenericByteArray<T> {
225 let array_type = T::DATA_TYPE;
226 let offset_buffer = Buffer::from_slice_ref(self.offsets_builder.as_slice());
227 let value_buffer = Buffer::from_slice_ref(self.value_builder.as_slice());
228 let array_builder = ArrayDataBuilder::new(array_type)
229 .len(self.len())
230 .add_buffer(offset_buffer)
231 .add_buffer(value_buffer)
232 .nulls(self.null_buffer_builder.finish_cloned());
233
234 let array_data = unsafe { array_builder.build_unchecked() };
236 GenericByteArray::from(array_data)
237 }
238
239 pub fn values_slice(&self) -> &[u8] {
241 self.value_builder.as_slice()
242 }
243
244 pub fn values_capacity(&self) -> usize {
246 self.value_builder.capacity()
247 }
248
249 pub fn offsets_slice(&self) -> &[T::Offset] {
251 self.offsets_builder.as_slice()
252 }
253
254 pub fn offsets_capacity(&self) -> usize {
256 self.offsets_builder.capacity()
257 }
258
259 pub fn validity_slice(&self) -> Option<&[u8]> {
261 self.null_buffer_builder.as_slice()
262 }
263
264 pub fn validity_capacity(&self) -> usize {
266 self.null_buffer_builder.allocated_size()
267 }
268
269 pub fn validity_slice_mut(&mut self) -> Option<&mut [u8]> {
271 self.null_buffer_builder.as_slice_mut()
272 }
273}
274
275impl<T: ByteArrayType> std::fmt::Debug for GenericByteBuilder<T> {
276 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
277 write!(f, "{}{}Builder", T::Offset::PREFIX, T::PREFIX)?;
278 f.debug_struct("")
279 .field("value_builder", &self.value_builder)
280 .field("offsets_builder", &self.offsets_builder)
281 .field("null_buffer_builder", &self.null_buffer_builder)
282 .finish()
283 }
284}
285
286impl<T: ByteArrayType> Default for GenericByteBuilder<T> {
287 fn default() -> Self {
288 Self::new()
289 }
290}
291
292impl<T: ByteArrayType> ArrayBuilder for GenericByteBuilder<T> {
293 fn len(&self) -> usize {
295 self.null_buffer_builder.len()
296 }
297
298 fn finish(&mut self) -> ArrayRef {
300 Arc::new(self.finish())
301 }
302
303 fn finish_cloned(&self) -> ArrayRef {
305 Arc::new(self.finish_cloned())
306 }
307
308 fn as_any(&self) -> &dyn Any {
310 self
311 }
312
313 fn as_any_mut(&mut self) -> &mut dyn Any {
315 self
316 }
317
318 fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
320 self
321 }
322}
323
324impl<T: ByteArrayType, V: AsRef<T::Native>> Extend<Option<V>> for GenericByteBuilder<T> {
325 #[inline]
326 fn extend<I: IntoIterator<Item = Option<V>>>(&mut self, iter: I) {
327 for v in iter {
328 self.append_option(v)
329 }
330 }
331}
332
333pub type GenericStringBuilder<O> = GenericByteBuilder<GenericStringType<O>>;
383
384impl<O: OffsetSizeTrait> std::fmt::Write for GenericStringBuilder<O> {
385 fn write_str(&mut self, s: &str) -> std::fmt::Result {
386 self.value_builder.extend_from_slice(s.as_bytes());
387 Ok(())
388 }
389}
390
391const AVERAGE_STRING_LENGTH: usize = 16;
402pub trait StringLikeArrayBuilder: ArrayBuilder {
407 fn type_name() -> &'static str;
409
410 fn with_capacity(capacity: usize) -> Self;
412
413 fn append_value(&mut self, value: &str);
415
416 fn append_null(&mut self);
418}
419
420impl<O: OffsetSizeTrait> StringLikeArrayBuilder for GenericStringBuilder<O> {
421 fn type_name() -> &'static str {
422 std::any::type_name::<Self>()
423 }
424 fn with_capacity(capacity: usize) -> Self {
425 Self::with_capacity(capacity, capacity * AVERAGE_STRING_LENGTH)
426 }
427 fn append_value(&mut self, value: &str) {
428 Self::append_value(self, value);
429 }
430 fn append_null(&mut self) {
431 Self::append_null(self);
432 }
433}
434
435const AVERAGE_BINARY_LENGTH: usize = 128;
446pub trait BinaryLikeArrayBuilder: ArrayBuilder {
451 fn type_name() -> &'static str;
453
454 fn with_capacity(capacity: usize) -> Self;
456
457 fn append_value(&mut self, value: &[u8]);
459
460 fn append_null(&mut self);
462}
463
464impl<O: OffsetSizeTrait> BinaryLikeArrayBuilder for GenericBinaryBuilder<O> {
465 fn type_name() -> &'static str {
466 std::any::type_name::<Self>()
467 }
468 fn with_capacity(capacity: usize) -> Self {
469 Self::with_capacity(capacity, capacity * AVERAGE_BINARY_LENGTH)
470 }
471 fn append_value(&mut self, value: &[u8]) {
472 Self::append_value(self, value);
473 }
474 fn append_null(&mut self) {
475 Self::append_null(self);
476 }
477}
478
479pub type GenericBinaryBuilder<O> = GenericByteBuilder<GenericBinaryType<O>>;
525
526impl<O: OffsetSizeTrait> std::io::Write for GenericBinaryBuilder<O> {
527 fn write(&mut self, bs: &[u8]) -> std::io::Result<usize> {
528 self.value_builder.extend_from_slice(bs);
529 Ok(bs.len())
530 }
531
532 fn flush(&mut self) -> std::io::Result<()> {
533 Ok(())
534 }
535}
536
537#[cfg(test)]
538mod tests {
539 use super::*;
540 use crate::GenericStringArray;
541 use crate::array::Array;
542 use arrow_buffer::NullBuffer;
543 use std::fmt::Write as _;
544 use std::io::Write as _;
545
546 fn _test_generic_binary_builder<O: OffsetSizeTrait>() {
547 let mut builder = GenericBinaryBuilder::<O>::new();
548
549 builder.append_value(b"hello");
550 builder.append_value(b"");
551 builder.append_null();
552 builder.append_value(b"rust");
553
554 let array = builder.finish();
555
556 assert_eq!(4, array.len());
557 assert_eq!(1, array.null_count());
558 assert_eq!(b"hello", array.value(0));
559 assert_eq!([] as [u8; 0], array.value(1));
560 assert!(array.is_null(2));
561 assert_eq!(b"rust", array.value(3));
562 assert_eq!(O::from_usize(5).unwrap(), array.value_offsets()[2]);
563 assert_eq!(O::from_usize(4).unwrap(), array.value_length(3));
564 }
565
566 #[test]
567 fn test_binary_builder() {
568 _test_generic_binary_builder::<i32>()
569 }
570
571 #[test]
572 fn test_large_binary_builder() {
573 _test_generic_binary_builder::<i64>()
574 }
575
576 fn _test_generic_binary_builder_all_nulls<O: OffsetSizeTrait>() {
577 let mut builder = GenericBinaryBuilder::<O>::new();
578 builder.append_null();
579 builder.append_null();
580 builder.append_null();
581 builder.append_nulls(2);
582 assert_eq!(5, builder.len());
583 assert!(!builder.is_empty());
584
585 let array = builder.finish();
586 assert_eq!(5, array.null_count());
587 assert_eq!(5, array.len());
588 assert!(array.is_null(0));
589 assert!(array.is_null(1));
590 assert!(array.is_null(2));
591 assert!(array.is_null(3));
592 assert!(array.is_null(4));
593 }
594
595 #[test]
596 fn test_binary_builder_all_nulls() {
597 _test_generic_binary_builder_all_nulls::<i32>()
598 }
599
600 #[test]
601 fn test_large_binary_builder_all_nulls() {
602 _test_generic_binary_builder_all_nulls::<i64>()
603 }
604
605 fn _test_generic_binary_builder_reset<O: OffsetSizeTrait>() {
606 let mut builder = GenericBinaryBuilder::<O>::new();
607
608 builder.append_value(b"hello");
609 builder.append_value(b"");
610 builder.append_null();
611 builder.append_value(b"rust");
612 builder.finish();
613
614 assert!(builder.is_empty());
615
616 builder.append_value(b"parquet");
617 builder.append_null();
618 builder.append_value(b"arrow");
619 builder.append_value(b"");
620 builder.append_nulls(2);
621 builder.append_value(b"hi");
622 let array = builder.finish();
623
624 assert_eq!(7, array.len());
625 assert_eq!(3, array.null_count());
626 assert_eq!(b"parquet", array.value(0));
627 assert!(array.is_null(1));
628 assert!(array.is_null(4));
629 assert!(array.is_null(5));
630 assert_eq!(b"arrow", array.value(2));
631 assert_eq!(b"", array.value(1));
632 assert_eq!(b"hi", array.value(6));
633
634 assert_eq!(O::zero(), array.value_offsets()[0]);
635 assert_eq!(O::from_usize(7).unwrap(), array.value_offsets()[2]);
636 assert_eq!(O::from_usize(14).unwrap(), array.value_offsets()[7]);
637 assert_eq!(O::from_usize(5).unwrap(), array.value_length(2));
638 }
639
640 #[test]
641 fn test_binary_builder_reset() {
642 _test_generic_binary_builder_reset::<i32>()
643 }
644
645 #[test]
646 fn test_large_binary_builder_reset() {
647 _test_generic_binary_builder_reset::<i64>()
648 }
649
650 fn _test_generic_string_array_builder<O: OffsetSizeTrait>() {
651 let mut builder = GenericStringBuilder::<O>::new();
652 let owned = "arrow".to_owned();
653
654 builder.append_value("hello");
655 builder.append_value("");
656 builder.append_value(&owned);
657 builder.append_null();
658 builder.append_option(Some("rust"));
659 builder.append_option(None::<&str>);
660 builder.append_option(None::<String>);
661 builder.append_nulls(2);
662 builder.append_value("parquet");
663 assert_eq!(10, builder.len());
664
665 assert_eq!(
666 GenericStringArray::<O>::from(vec![
667 Some("hello"),
668 Some(""),
669 Some("arrow"),
670 None,
671 Some("rust"),
672 None,
673 None,
674 None,
675 None,
676 Some("parquet")
677 ]),
678 builder.finish()
679 );
680 }
681
682 #[test]
683 fn test_string_array_builder() {
684 _test_generic_string_array_builder::<i32>()
685 }
686
687 #[test]
688 fn test_large_string_array_builder() {
689 _test_generic_string_array_builder::<i64>()
690 }
691
692 fn _test_generic_string_array_builder_finish<O: OffsetSizeTrait>() {
693 let mut builder = GenericStringBuilder::<O>::with_capacity(3, 11);
694
695 builder.append_value("hello");
696 builder.append_value("rust");
697 builder.append_null();
698
699 builder.finish();
700 assert!(builder.is_empty());
701 assert_eq!(&[O::zero()], builder.offsets_slice());
702
703 builder.append_value("arrow");
704 builder.append_value("parquet");
705 let arr = builder.finish();
706 assert!(arr.nulls().is_none());
708 assert_eq!(GenericStringArray::<O>::from(vec!["arrow", "parquet"]), arr,)
709 }
710
711 #[test]
712 fn test_string_array_builder_finish() {
713 _test_generic_string_array_builder_finish::<i32>()
714 }
715
716 #[test]
717 fn test_large_string_array_builder_finish() {
718 _test_generic_string_array_builder_finish::<i64>()
719 }
720
721 fn _test_generic_string_array_builder_finish_cloned<O: OffsetSizeTrait>() {
722 let mut builder = GenericStringBuilder::<O>::with_capacity(3, 11);
723
724 builder.append_value("hello");
725 builder.append_value("rust");
726 builder.append_null();
727
728 let mut arr = builder.finish_cloned();
729 assert!(!builder.is_empty());
730 assert_eq!(3, arr.len());
731
732 builder.append_value("arrow");
733 builder.append_value("parquet");
734 arr = builder.finish();
735
736 assert!(arr.nulls().is_some());
737 assert_eq!(&[O::zero()], builder.offsets_slice());
738 assert_eq!(5, arr.len());
739 }
740
741 #[test]
742 fn test_string_array_builder_finish_cloned() {
743 _test_generic_string_array_builder_finish_cloned::<i32>()
744 }
745
746 #[test]
747 fn test_large_string_array_builder_finish_cloned() {
748 _test_generic_string_array_builder_finish_cloned::<i64>()
749 }
750
751 #[test]
752 fn test_extend() {
753 let mut builder = GenericStringBuilder::<i32>::new();
754 builder.extend(["a", "b", "c", "", "a", "b", "c"].into_iter().map(Some));
755 builder.extend(["d", "cupcakes", "hello"].into_iter().map(Some));
756 let array = builder.finish();
757 assert_eq!(array.value_offsets(), &[0, 1, 2, 3, 3, 4, 5, 6, 7, 15, 20]);
758 assert_eq!(array.value_data(), b"abcabcdcupcakeshello");
759 }
760
761 #[test]
762 fn test_write_str() {
763 let mut builder = GenericStringBuilder::<i32>::new();
764 write!(builder, "foo").unwrap();
765 builder.append_value("");
766 writeln!(builder, "bar").unwrap();
767 builder.append_value("");
768 write!(builder, "fiz").unwrap();
769 write!(builder, "buz").unwrap();
770 builder.append_value("");
771 let a = builder.finish();
772 let r: Vec<_> = a.iter().flatten().collect();
773 assert_eq!(r, &["foo", "bar\n", "fizbuz"])
774 }
775
776 #[test]
777 fn test_write_bytes() {
778 let mut builder = GenericBinaryBuilder::<i32>::new();
779 write!(builder, "foo").unwrap();
780 builder.append_value("");
781 writeln!(builder, "bar").unwrap();
782 builder.append_value("");
783 write!(builder, "fiz").unwrap();
784 write!(builder, "buz").unwrap();
785 builder.append_value("");
786 let a = builder.finish();
787 let r: Vec<_> = a.iter().flatten().collect();
788 assert_eq!(
789 r,
790 &[b"foo".as_slice(), b"bar\n".as_slice(), b"fizbuz".as_slice()]
791 )
792 }
793
794 #[test]
795 fn test_append_array_without_nulls() {
796 let input = vec![
797 "hello", "world", "how", "are", "you", "doing", "today", "I", "am", "doing", "well",
798 "thank", "you", "for", "asking",
799 ];
800 let arr1 = GenericStringArray::<i32>::from(input[..3].to_vec());
801 let arr2 = GenericStringArray::<i32>::from(input[3..7].to_vec());
802 let arr3 = GenericStringArray::<i32>::from(input[7..].to_vec());
803
804 let mut builder = GenericStringBuilder::<i32>::new();
805 builder.append_array(&arr1).unwrap();
806 builder.append_array(&arr2).unwrap();
807 builder.append_array(&arr3).unwrap();
808
809 let actual = builder.finish();
810 let expected = GenericStringArray::<i32>::from(input);
811
812 assert_eq!(actual, expected);
813 }
814
815 #[test]
816 fn test_append_array_with_nulls() {
817 let input = vec![
818 Some("hello"),
819 None,
820 Some("how"),
821 None,
822 None,
823 None,
824 None,
825 Some("I"),
826 Some("am"),
827 Some("doing"),
828 Some("well"),
829 ];
830 let arr1 = GenericStringArray::<i32>::from(input[..3].to_vec());
831 let arr2 = GenericStringArray::<i32>::from(input[3..7].to_vec());
832 let arr3 = GenericStringArray::<i32>::from(input[7..].to_vec());
833
834 let mut builder = GenericStringBuilder::<i32>::new();
835 builder.append_array(&arr1).unwrap();
836 builder.append_array(&arr2).unwrap();
837 builder.append_array(&arr3).unwrap();
838
839 let actual = builder.finish();
840 let expected = GenericStringArray::<i32>::from(input);
841
842 assert_eq!(actual, expected);
843 }
844
845 #[test]
846 fn test_append_empty_array() {
847 let arr = GenericStringArray::<i32>::from(Vec::<&str>::new());
848 let mut builder = GenericStringBuilder::<i32>::new();
849 builder.append_array(&arr).unwrap();
850 let result = builder.finish();
851 assert_eq!(result.len(), 0);
852 }
853
854 #[test]
855 fn test_append_array_with_offset_not_starting_at_0() {
856 let input = vec![
857 Some("hello"),
858 None,
859 Some("how"),
860 None,
861 None,
862 None,
863 None,
864 Some("I"),
865 Some("am"),
866 Some("doing"),
867 Some("well"),
868 ];
869 let full_array = GenericStringArray::<i32>::from(input);
870 let sliced = full_array.slice(1, 4);
871
872 assert_ne!(sliced.offsets()[0].as_usize(), 0);
873 assert_ne!(sliced.offsets().last(), full_array.offsets().last());
874
875 let mut builder = GenericStringBuilder::<i32>::new();
876 builder.append_array(&sliced).unwrap();
877 let actual = builder.finish();
878
879 let expected = GenericStringArray::<i32>::from(vec![None, Some("how"), None, None]);
880
881 assert_eq!(actual, expected);
882 }
883
884 #[test]
885 fn test_append_underlying_null_values_added_as_is() {
886 let input_1_array_with_nulls = {
887 let input = vec![
888 "hello", "world", "how", "are", "you", "doing", "today", "I", "am",
889 ];
890 let (offsets, buffer, _) = GenericStringArray::<i32>::from(input).into_parts();
891
892 GenericStringArray::<i32>::new(
893 offsets,
894 buffer,
895 Some(NullBuffer::from(&[
896 true, false, true, false, false, true, true, true, false,
897 ])),
898 )
899 };
900 let input_2_array_with_nulls = {
901 let input = vec!["doing", "well", "thank", "you", "for", "asking"];
902 let (offsets, buffer, _) = GenericStringArray::<i32>::from(input).into_parts();
903
904 GenericStringArray::<i32>::new(
905 offsets,
906 buffer,
907 Some(NullBuffer::from(&[false, false, true, false, true, true])),
908 )
909 };
910
911 let mut builder = GenericStringBuilder::<i32>::new();
912 builder.append_array(&input_1_array_with_nulls).unwrap();
913 builder.append_array(&input_2_array_with_nulls).unwrap();
914
915 let actual = builder.finish();
916 let expected = GenericStringArray::<i32>::from(vec![
917 Some("hello"),
918 None, Some("how"),
920 None, None, Some("doing"),
923 Some("today"),
924 Some("I"),
925 None, None, None, Some("thank"),
929 None, Some("for"),
931 Some("asking"),
932 ]);
933
934 assert_eq!(actual, expected);
935
936 let expected_underlying_buffer = Buffer::from(
937 [
938 "hello", "world", "how", "are", "you", "doing", "today", "I", "am", "doing",
939 "well", "thank", "you", "for", "asking",
940 ]
941 .join("")
942 .as_bytes(),
943 );
944 assert_eq!(actual.values(), &expected_underlying_buffer);
945 }
946
947 #[test]
948 fn append_array_with_continues_indices() {
949 let input = vec![
950 "hello", "world", "how", "are", "you", "doing", "today", "I", "am", "doing", "well",
951 "thank", "you", "for", "asking",
952 ];
953 let full_array = GenericStringArray::<i32>::from(input);
954 let slice1 = full_array.slice(0, 3);
955 let slice2 = full_array.slice(3, 4);
956 let slice3 = full_array.slice(7, full_array.len() - 7);
957
958 let mut builder = GenericStringBuilder::<i32>::new();
959 builder.append_array(&slice1).unwrap();
960 builder.append_array(&slice2).unwrap();
961 builder.append_array(&slice3).unwrap();
962
963 let actual = builder.finish();
964
965 assert_eq!(actual, full_array);
966 }
967
968 #[test]
969 fn test_append_array_offset_overflow_precise() {
970 let mut builder = GenericStringBuilder::<i32>::new();
971
972 let initial_string = "x".repeat(i32::MAX as usize - 100);
973 builder.append_value(&initial_string);
974
975 let overflow_string = "y".repeat(200);
976 let overflow_array = GenericStringArray::<i32>::from(vec![overflow_string.as_str()]);
977
978 let result = builder.append_array(&overflow_array);
979
980 assert!(matches!(result, Err(ArrowError::OffsetOverflowError(_))));
981 }
982
983 #[test]
984 fn test_append_value_n() {
985 let mut builder = GenericStringBuilder::<i32>::new();
986 builder.append_value("hello");
987 builder.append_value_n("world", 3);
988 builder.append_null();
989 let array = builder.finish();
990
991 assert_eq!(5, array.len());
992 assert_eq!(1, array.null_count());
993 assert_eq!("hello", array.value(0));
994 assert_eq!("world", array.value(1));
995 assert_eq!("world", array.value(2));
996 assert_eq!("world", array.value(3));
997 assert!(array.is_null(4));
998 }
999}