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(
69 offsets_buffer: MutableBuffer,
70 mut value_buffer: MutableBuffer,
71 null_buffer: Option<MutableBuffer>,
72 ) -> Self {
73 let offsets_builder: Vec<T::Offset> =
74 ScalarBuffer::<T::Offset>::from(offsets_buffer).into();
75
76 value_buffer.truncate(offsets_builder.last().unwrap().as_usize());
79 let value_builder: Vec<u8> = ScalarBuffer::<u8>::from(value_buffer).into();
80
81 let null_buffer_builder = null_buffer
82 .map(|buffer| NullBufferBuilder::new_from_buffer(buffer, offsets_builder.len() - 1))
83 .unwrap_or_else(|| NullBufferBuilder::new_with_len(offsets_builder.len() - 1));
84
85 Self {
86 offsets_builder,
87 value_builder,
88 null_buffer_builder,
89 }
90 }
91
92 #[inline]
93 fn next_offset(&self) -> T::Offset {
94 T::Offset::from_usize(self.value_builder.len()).expect("byte array offset overflow")
95 }
96
97 #[inline]
113 pub fn append_value(&mut self, value: impl AsRef<T::Native>) {
114 self.value_builder
115 .extend_from_slice(value.as_ref().as_ref());
116 self.null_buffer_builder.append(true);
117 self.offsets_builder.push(self.next_offset());
118 }
119
120 #[inline]
124 pub fn append_value_n(&mut self, value: impl AsRef<T::Native>, n: usize) {
125 let bytes: &[u8] = value.as_ref().as_ref();
126 self.value_builder.reserve(bytes.len() * n);
127 self.offsets_builder.reserve(n);
128 for _ in 0..n {
129 self.value_builder.extend_from_slice(bytes);
130 self.offsets_builder.push(self.next_offset());
131 }
132 self.null_buffer_builder.append_n_non_nulls(n);
133 }
134
135 #[inline]
142 pub fn append_option(&mut self, value: Option<impl AsRef<T::Native>>) {
143 match value {
144 None => self.append_null(),
145 Some(v) => self.append_value(v),
146 };
147 }
148
149 #[inline]
151 pub fn append_null(&mut self) {
152 self.null_buffer_builder.append(false);
153 self.offsets_builder.push(self.next_offset());
154 }
155
156 #[inline]
158 pub fn append_nulls(&mut self, n: usize) {
159 self.null_buffer_builder.append_n_nulls(n);
160 let next_offset = self.next_offset();
161 self.offsets_builder
162 .extend(std::iter::repeat_n(next_offset, n));
163 }
164
165 #[inline]
168 pub fn append_array(&mut self, array: &GenericByteArray<T>) -> Result<(), ArrowError> {
169 use num_traits::CheckedAdd;
170 if array.len() == 0 {
171 return Ok(());
172 }
173
174 let offsets = array.offsets();
175
176 if self.next_offset() == offsets[0] {
179 self.offsets_builder.extend_from_slice(&offsets[1..]);
180 } else {
181 let shift: T::Offset = self.next_offset() - offsets[0];
183
184 if shift.checked_add(&offsets[offsets.len() - 1]).is_none() {
185 return Err(ArrowError::OffsetOverflowError(
186 shift.as_usize() + offsets[offsets.len() - 1].as_usize(),
187 ));
188 }
189
190 self.offsets_builder
191 .extend(offsets[1..].iter().map(|&offset| offset + shift));
192 }
193
194 self.value_builder.extend_from_slice(
196 &array.values().as_slice()[offsets[0].as_usize()..offsets[array.len()].as_usize()],
197 );
198
199 if let Some(null_buffer) = array.nulls() {
200 self.null_buffer_builder.append_buffer(null_buffer);
201 } else {
202 self.null_buffer_builder.append_n_non_nulls(array.len());
203 }
204 Ok(())
205 }
206
207 pub fn finish(&mut self) -> GenericByteArray<T> {
209 let array_type = T::DATA_TYPE;
210 let array_builder = ArrayDataBuilder::new(array_type)
211 .len(self.len())
212 .add_buffer(std::mem::take(&mut self.offsets_builder).into())
213 .add_buffer(std::mem::take(&mut self.value_builder).into())
214 .nulls(self.null_buffer_builder.finish());
215
216 self.offsets_builder.push(self.next_offset());
217 let array_data = unsafe { array_builder.build_unchecked() };
218 GenericByteArray::from(array_data)
219 }
220
221 pub fn finish_cloned(&self) -> GenericByteArray<T> {
223 let array_type = T::DATA_TYPE;
224 let offset_buffer = Buffer::from_slice_ref(self.offsets_builder.as_slice());
225 let value_buffer = Buffer::from_slice_ref(self.value_builder.as_slice());
226 let array_builder = ArrayDataBuilder::new(array_type)
227 .len(self.len())
228 .add_buffer(offset_buffer)
229 .add_buffer(value_buffer)
230 .nulls(self.null_buffer_builder.finish_cloned());
231
232 let array_data = unsafe { array_builder.build_unchecked() };
233 GenericByteArray::from(array_data)
234 }
235
236 pub fn values_slice(&self) -> &[u8] {
238 self.value_builder.as_slice()
239 }
240
241 pub fn offsets_slice(&self) -> &[T::Offset] {
243 self.offsets_builder.as_slice()
244 }
245
246 pub fn validity_slice(&self) -> Option<&[u8]> {
248 self.null_buffer_builder.as_slice()
249 }
250
251 pub fn validity_slice_mut(&mut self) -> Option<&mut [u8]> {
253 self.null_buffer_builder.as_slice_mut()
254 }
255}
256
257impl<T: ByteArrayType> std::fmt::Debug for GenericByteBuilder<T> {
258 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
259 write!(f, "{}{}Builder", T::Offset::PREFIX, T::PREFIX)?;
260 f.debug_struct("")
261 .field("value_builder", &self.value_builder)
262 .field("offsets_builder", &self.offsets_builder)
263 .field("null_buffer_builder", &self.null_buffer_builder)
264 .finish()
265 }
266}
267
268impl<T: ByteArrayType> Default for GenericByteBuilder<T> {
269 fn default() -> Self {
270 Self::new()
271 }
272}
273
274impl<T: ByteArrayType> ArrayBuilder for GenericByteBuilder<T> {
275 fn len(&self) -> usize {
277 self.null_buffer_builder.len()
278 }
279
280 fn finish(&mut self) -> ArrayRef {
282 Arc::new(self.finish())
283 }
284
285 fn finish_cloned(&self) -> ArrayRef {
287 Arc::new(self.finish_cloned())
288 }
289
290 fn as_any(&self) -> &dyn Any {
292 self
293 }
294
295 fn as_any_mut(&mut self) -> &mut dyn Any {
297 self
298 }
299
300 fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
302 self
303 }
304}
305
306impl<T: ByteArrayType, V: AsRef<T::Native>> Extend<Option<V>> for GenericByteBuilder<T> {
307 #[inline]
308 fn extend<I: IntoIterator<Item = Option<V>>>(&mut self, iter: I) {
309 for v in iter {
310 self.append_option(v)
311 }
312 }
313}
314
315pub type GenericStringBuilder<O> = GenericByteBuilder<GenericStringType<O>>;
365
366impl<O: OffsetSizeTrait> std::fmt::Write for GenericStringBuilder<O> {
367 fn write_str(&mut self, s: &str) -> std::fmt::Result {
368 self.value_builder.extend_from_slice(s.as_bytes());
369 Ok(())
370 }
371}
372
373const AVERAGE_STRING_LENGTH: usize = 16;
384pub trait StringLikeArrayBuilder: ArrayBuilder {
389 fn type_name() -> &'static str;
391
392 fn with_capacity(capacity: usize) -> Self;
394
395 fn append_value(&mut self, value: &str);
397
398 fn append_null(&mut self);
400}
401
402impl<O: OffsetSizeTrait> StringLikeArrayBuilder for GenericStringBuilder<O> {
403 fn type_name() -> &'static str {
404 std::any::type_name::<Self>()
405 }
406 fn with_capacity(capacity: usize) -> Self {
407 Self::with_capacity(capacity, capacity * AVERAGE_STRING_LENGTH)
408 }
409 fn append_value(&mut self, value: &str) {
410 Self::append_value(self, value);
411 }
412 fn append_null(&mut self) {
413 Self::append_null(self);
414 }
415}
416
417const AVERAGE_BINARY_LENGTH: usize = 128;
428pub trait BinaryLikeArrayBuilder: ArrayBuilder {
433 fn type_name() -> &'static str;
435
436 fn with_capacity(capacity: usize) -> Self;
438
439 fn append_value(&mut self, value: &[u8]);
441
442 fn append_null(&mut self);
444}
445
446impl<O: OffsetSizeTrait> BinaryLikeArrayBuilder for GenericBinaryBuilder<O> {
447 fn type_name() -> &'static str {
448 std::any::type_name::<Self>()
449 }
450 fn with_capacity(capacity: usize) -> Self {
451 Self::with_capacity(capacity, capacity * AVERAGE_BINARY_LENGTH)
452 }
453 fn append_value(&mut self, value: &[u8]) {
454 Self::append_value(self, value);
455 }
456 fn append_null(&mut self) {
457 Self::append_null(self);
458 }
459}
460
461pub type GenericBinaryBuilder<O> = GenericByteBuilder<GenericBinaryType<O>>;
507
508impl<O: OffsetSizeTrait> std::io::Write for GenericBinaryBuilder<O> {
509 fn write(&mut self, bs: &[u8]) -> std::io::Result<usize> {
510 self.value_builder.extend_from_slice(bs);
511 Ok(bs.len())
512 }
513
514 fn flush(&mut self) -> std::io::Result<()> {
515 Ok(())
516 }
517}
518
519#[cfg(test)]
520mod tests {
521 use super::*;
522 use crate::GenericStringArray;
523 use crate::array::Array;
524 use arrow_buffer::NullBuffer;
525 use std::fmt::Write as _;
526 use std::io::Write as _;
527
528 fn _test_generic_binary_builder<O: OffsetSizeTrait>() {
529 let mut builder = GenericBinaryBuilder::<O>::new();
530
531 builder.append_value(b"hello");
532 builder.append_value(b"");
533 builder.append_null();
534 builder.append_value(b"rust");
535
536 let array = builder.finish();
537
538 assert_eq!(4, array.len());
539 assert_eq!(1, array.null_count());
540 assert_eq!(b"hello", array.value(0));
541 assert_eq!([] as [u8; 0], array.value(1));
542 assert!(array.is_null(2));
543 assert_eq!(b"rust", array.value(3));
544 assert_eq!(O::from_usize(5).unwrap(), array.value_offsets()[2]);
545 assert_eq!(O::from_usize(4).unwrap(), array.value_length(3));
546 }
547
548 #[test]
549 fn test_binary_builder() {
550 _test_generic_binary_builder::<i32>()
551 }
552
553 #[test]
554 fn test_large_binary_builder() {
555 _test_generic_binary_builder::<i64>()
556 }
557
558 fn _test_generic_binary_builder_all_nulls<O: OffsetSizeTrait>() {
559 let mut builder = GenericBinaryBuilder::<O>::new();
560 builder.append_null();
561 builder.append_null();
562 builder.append_null();
563 builder.append_nulls(2);
564 assert_eq!(5, builder.len());
565 assert!(!builder.is_empty());
566
567 let array = builder.finish();
568 assert_eq!(5, array.null_count());
569 assert_eq!(5, array.len());
570 assert!(array.is_null(0));
571 assert!(array.is_null(1));
572 assert!(array.is_null(2));
573 assert!(array.is_null(3));
574 assert!(array.is_null(4));
575 }
576
577 #[test]
578 fn test_binary_builder_all_nulls() {
579 _test_generic_binary_builder_all_nulls::<i32>()
580 }
581
582 #[test]
583 fn test_large_binary_builder_all_nulls() {
584 _test_generic_binary_builder_all_nulls::<i64>()
585 }
586
587 fn _test_generic_binary_builder_reset<O: OffsetSizeTrait>() {
588 let mut builder = GenericBinaryBuilder::<O>::new();
589
590 builder.append_value(b"hello");
591 builder.append_value(b"");
592 builder.append_null();
593 builder.append_value(b"rust");
594 builder.finish();
595
596 assert!(builder.is_empty());
597
598 builder.append_value(b"parquet");
599 builder.append_null();
600 builder.append_value(b"arrow");
601 builder.append_value(b"");
602 builder.append_nulls(2);
603 builder.append_value(b"hi");
604 let array = builder.finish();
605
606 assert_eq!(7, array.len());
607 assert_eq!(3, array.null_count());
608 assert_eq!(b"parquet", array.value(0));
609 assert!(array.is_null(1));
610 assert!(array.is_null(4));
611 assert!(array.is_null(5));
612 assert_eq!(b"arrow", array.value(2));
613 assert_eq!(b"", array.value(1));
614 assert_eq!(b"hi", array.value(6));
615
616 assert_eq!(O::zero(), array.value_offsets()[0]);
617 assert_eq!(O::from_usize(7).unwrap(), array.value_offsets()[2]);
618 assert_eq!(O::from_usize(14).unwrap(), array.value_offsets()[7]);
619 assert_eq!(O::from_usize(5).unwrap(), array.value_length(2));
620 }
621
622 #[test]
623 fn test_binary_builder_reset() {
624 _test_generic_binary_builder_reset::<i32>()
625 }
626
627 #[test]
628 fn test_large_binary_builder_reset() {
629 _test_generic_binary_builder_reset::<i64>()
630 }
631
632 fn _test_generic_string_array_builder<O: OffsetSizeTrait>() {
633 let mut builder = GenericStringBuilder::<O>::new();
634 let owned = "arrow".to_owned();
635
636 builder.append_value("hello");
637 builder.append_value("");
638 builder.append_value(&owned);
639 builder.append_null();
640 builder.append_option(Some("rust"));
641 builder.append_option(None::<&str>);
642 builder.append_option(None::<String>);
643 builder.append_nulls(2);
644 builder.append_value("parquet");
645 assert_eq!(10, builder.len());
646
647 assert_eq!(
648 GenericStringArray::<O>::from(vec![
649 Some("hello"),
650 Some(""),
651 Some("arrow"),
652 None,
653 Some("rust"),
654 None,
655 None,
656 None,
657 None,
658 Some("parquet")
659 ]),
660 builder.finish()
661 );
662 }
663
664 #[test]
665 fn test_string_array_builder() {
666 _test_generic_string_array_builder::<i32>()
667 }
668
669 #[test]
670 fn test_large_string_array_builder() {
671 _test_generic_string_array_builder::<i64>()
672 }
673
674 fn _test_generic_string_array_builder_finish<O: OffsetSizeTrait>() {
675 let mut builder = GenericStringBuilder::<O>::with_capacity(3, 11);
676
677 builder.append_value("hello");
678 builder.append_value("rust");
679 builder.append_null();
680
681 builder.finish();
682 assert!(builder.is_empty());
683 assert_eq!(&[O::zero()], builder.offsets_slice());
684
685 builder.append_value("arrow");
686 builder.append_value("parquet");
687 let arr = builder.finish();
688 assert!(arr.nulls().is_none());
690 assert_eq!(GenericStringArray::<O>::from(vec!["arrow", "parquet"]), arr,)
691 }
692
693 #[test]
694 fn test_string_array_builder_finish() {
695 _test_generic_string_array_builder_finish::<i32>()
696 }
697
698 #[test]
699 fn test_large_string_array_builder_finish() {
700 _test_generic_string_array_builder_finish::<i64>()
701 }
702
703 fn _test_generic_string_array_builder_finish_cloned<O: OffsetSizeTrait>() {
704 let mut builder = GenericStringBuilder::<O>::with_capacity(3, 11);
705
706 builder.append_value("hello");
707 builder.append_value("rust");
708 builder.append_null();
709
710 let mut arr = builder.finish_cloned();
711 assert!(!builder.is_empty());
712 assert_eq!(3, arr.len());
713
714 builder.append_value("arrow");
715 builder.append_value("parquet");
716 arr = builder.finish();
717
718 assert!(arr.nulls().is_some());
719 assert_eq!(&[O::zero()], builder.offsets_slice());
720 assert_eq!(5, arr.len());
721 }
722
723 #[test]
724 fn test_string_array_builder_finish_cloned() {
725 _test_generic_string_array_builder_finish_cloned::<i32>()
726 }
727
728 #[test]
729 fn test_large_string_array_builder_finish_cloned() {
730 _test_generic_string_array_builder_finish_cloned::<i64>()
731 }
732
733 #[test]
734 fn test_extend() {
735 let mut builder = GenericStringBuilder::<i32>::new();
736 builder.extend(["a", "b", "c", "", "a", "b", "c"].into_iter().map(Some));
737 builder.extend(["d", "cupcakes", "hello"].into_iter().map(Some));
738 let array = builder.finish();
739 assert_eq!(array.value_offsets(), &[0, 1, 2, 3, 3, 4, 5, 6, 7, 15, 20]);
740 assert_eq!(array.value_data(), b"abcabcdcupcakeshello");
741 }
742
743 #[test]
744 fn test_write_str() {
745 let mut builder = GenericStringBuilder::<i32>::new();
746 write!(builder, "foo").unwrap();
747 builder.append_value("");
748 writeln!(builder, "bar").unwrap();
749 builder.append_value("");
750 write!(builder, "fiz").unwrap();
751 write!(builder, "buz").unwrap();
752 builder.append_value("");
753 let a = builder.finish();
754 let r: Vec<_> = a.iter().flatten().collect();
755 assert_eq!(r, &["foo", "bar\n", "fizbuz"])
756 }
757
758 #[test]
759 fn test_write_bytes() {
760 let mut builder = GenericBinaryBuilder::<i32>::new();
761 write!(builder, "foo").unwrap();
762 builder.append_value("");
763 writeln!(builder, "bar").unwrap();
764 builder.append_value("");
765 write!(builder, "fiz").unwrap();
766 write!(builder, "buz").unwrap();
767 builder.append_value("");
768 let a = builder.finish();
769 let r: Vec<_> = a.iter().flatten().collect();
770 assert_eq!(
771 r,
772 &["foo".as_bytes(), "bar\n".as_bytes(), "fizbuz".as_bytes()]
773 )
774 }
775
776 #[test]
777 fn test_append_array_without_nulls() {
778 let input = vec![
779 "hello", "world", "how", "are", "you", "doing", "today", "I", "am", "doing", "well",
780 "thank", "you", "for", "asking",
781 ];
782 let arr1 = GenericStringArray::<i32>::from(input[..3].to_vec());
783 let arr2 = GenericStringArray::<i32>::from(input[3..7].to_vec());
784 let arr3 = GenericStringArray::<i32>::from(input[7..].to_vec());
785
786 let mut builder = GenericStringBuilder::<i32>::new();
787 builder.append_array(&arr1).unwrap();
788 builder.append_array(&arr2).unwrap();
789 builder.append_array(&arr3).unwrap();
790
791 let actual = builder.finish();
792 let expected = GenericStringArray::<i32>::from(input);
793
794 assert_eq!(actual, expected);
795 }
796
797 #[test]
798 fn test_append_array_with_nulls() {
799 let input = vec![
800 Some("hello"),
801 None,
802 Some("how"),
803 None,
804 None,
805 None,
806 None,
807 Some("I"),
808 Some("am"),
809 Some("doing"),
810 Some("well"),
811 ];
812 let arr1 = GenericStringArray::<i32>::from(input[..3].to_vec());
813 let arr2 = GenericStringArray::<i32>::from(input[3..7].to_vec());
814 let arr3 = GenericStringArray::<i32>::from(input[7..].to_vec());
815
816 let mut builder = GenericStringBuilder::<i32>::new();
817 builder.append_array(&arr1).unwrap();
818 builder.append_array(&arr2).unwrap();
819 builder.append_array(&arr3).unwrap();
820
821 let actual = builder.finish();
822 let expected = GenericStringArray::<i32>::from(input);
823
824 assert_eq!(actual, expected);
825 }
826
827 #[test]
828 fn test_append_empty_array() {
829 let arr = GenericStringArray::<i32>::from(Vec::<&str>::new());
830 let mut builder = GenericStringBuilder::<i32>::new();
831 builder.append_array(&arr).unwrap();
832 let result = builder.finish();
833 assert_eq!(result.len(), 0);
834 }
835
836 #[test]
837 fn test_append_array_with_offset_not_starting_at_0() {
838 let input = vec![
839 Some("hello"),
840 None,
841 Some("how"),
842 None,
843 None,
844 None,
845 None,
846 Some("I"),
847 Some("am"),
848 Some("doing"),
849 Some("well"),
850 ];
851 let full_array = GenericStringArray::<i32>::from(input);
852 let sliced = full_array.slice(1, 4);
853
854 assert_ne!(sliced.offsets()[0].as_usize(), 0);
855 assert_ne!(sliced.offsets().last(), full_array.offsets().last());
856
857 let mut builder = GenericStringBuilder::<i32>::new();
858 builder.append_array(&sliced).unwrap();
859 let actual = builder.finish();
860
861 let expected = GenericStringArray::<i32>::from(vec![None, Some("how"), None, None]);
862
863 assert_eq!(actual, expected);
864 }
865
866 #[test]
867 fn test_append_underlying_null_values_added_as_is() {
868 let input_1_array_with_nulls = {
869 let input = vec![
870 "hello", "world", "how", "are", "you", "doing", "today", "I", "am",
871 ];
872 let (offsets, buffer, _) = GenericStringArray::<i32>::from(input).into_parts();
873
874 GenericStringArray::<i32>::new(
875 offsets,
876 buffer,
877 Some(NullBuffer::from(&[
878 true, false, true, false, false, true, true, true, false,
879 ])),
880 )
881 };
882 let input_2_array_with_nulls = {
883 let input = vec!["doing", "well", "thank", "you", "for", "asking"];
884 let (offsets, buffer, _) = GenericStringArray::<i32>::from(input).into_parts();
885
886 GenericStringArray::<i32>::new(
887 offsets,
888 buffer,
889 Some(NullBuffer::from(&[false, false, true, false, true, true])),
890 )
891 };
892
893 let mut builder = GenericStringBuilder::<i32>::new();
894 builder.append_array(&input_1_array_with_nulls).unwrap();
895 builder.append_array(&input_2_array_with_nulls).unwrap();
896
897 let actual = builder.finish();
898 let expected = GenericStringArray::<i32>::from(vec![
899 Some("hello"),
900 None, Some("how"),
902 None, None, Some("doing"),
905 Some("today"),
906 Some("I"),
907 None, None, None, Some("thank"),
911 None, Some("for"),
913 Some("asking"),
914 ]);
915
916 assert_eq!(actual, expected);
917
918 let expected_underlying_buffer = Buffer::from(
919 [
920 "hello", "world", "how", "are", "you", "doing", "today", "I", "am", "doing",
921 "well", "thank", "you", "for", "asking",
922 ]
923 .join("")
924 .as_bytes(),
925 );
926 assert_eq!(actual.values(), &expected_underlying_buffer);
927 }
928
929 #[test]
930 fn append_array_with_continues_indices() {
931 let input = vec![
932 "hello", "world", "how", "are", "you", "doing", "today", "I", "am", "doing", "well",
933 "thank", "you", "for", "asking",
934 ];
935 let full_array = GenericStringArray::<i32>::from(input);
936 let slice1 = full_array.slice(0, 3);
937 let slice2 = full_array.slice(3, 4);
938 let slice3 = full_array.slice(7, full_array.len() - 7);
939
940 let mut builder = GenericStringBuilder::<i32>::new();
941 builder.append_array(&slice1).unwrap();
942 builder.append_array(&slice2).unwrap();
943 builder.append_array(&slice3).unwrap();
944
945 let actual = builder.finish();
946
947 assert_eq!(actual, full_array);
948 }
949
950 #[test]
951 fn test_append_array_offset_overflow_precise() {
952 let mut builder = GenericStringBuilder::<i32>::new();
953
954 let initial_string = "x".repeat(i32::MAX as usize - 100);
955 builder.append_value(&initial_string);
956
957 let overflow_string = "y".repeat(200);
958 let overflow_array = GenericStringArray::<i32>::from(vec![overflow_string.as_str()]);
959
960 let result = builder.append_array(&overflow_array);
961
962 assert!(matches!(result, Err(ArrowError::OffsetOverflowError(_))));
963 }
964
965 #[test]
966 fn test_append_value_n() {
967 let mut builder = GenericStringBuilder::<i32>::new();
968 builder.append_value("hello");
969 builder.append_value_n("world", 3);
970 builder.append_null();
971 let array = builder.finish();
972
973 assert_eq!(5, array.len());
974 assert_eq!(1, array.null_count());
975 assert_eq!("hello", array.value(0));
976 assert_eq!("world", array.value(1));
977 assert_eq!("world", array.value(2));
978 assert_eq!("world", array.value(3));
979 assert!(array.is_null(4));
980 }
981}