arrow_array/builder/
struct_array_assembler.rs1use crate::{ArrayRef, StructArray};
19use arrow_buffer::NullBuffer;
20use arrow_schema::{ArrowError, Field, FieldRef, Fields};
21use std::sync::Arc;
22
23#[derive(Debug, Default, Clone)]
47pub struct StructArrayAssembler {
48 fields: Vec<FieldRef>,
49 arrays: Vec<ArrayRef>,
50 nulls: Option<NullBuffer>,
51}
52
53impl StructArrayAssembler {
54 pub fn new() -> Self {
56 Self::default()
57 }
58
59 pub fn with_field(
61 mut self,
62 field_name: impl Into<String>,
63 array: ArrayRef,
64 nullable: bool,
65 ) -> Self {
66 self.fields.push(Arc::new(Field::new(
67 field_name,
68 array.data_type().clone(),
69 nullable,
70 )));
71 self.arrays.push(array);
72 self
73 }
74
75 pub fn with_field_ref(mut self, field: FieldRef, array: ArrayRef) -> Self {
80 self.fields.push(field);
81 self.arrays.push(array);
82 self
83 }
84
85 pub fn with_nulls(mut self, nulls: NullBuffer) -> Self {
87 self.nulls = Some(nulls);
88 self
89 }
90
91 pub fn build(self) -> Result<StructArray, ArrowError> {
98 StructArray::try_new(Fields::from(self.fields), self.arrays, self.nulls)
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105 use crate::{Array, Int32Array, StringArray};
106 use arrow_schema::DataType;
107 use std::collections::HashMap;
108
109 #[test]
110 fn build_from_completed_arrays() {
111 let names = Arc::new(StringArray::from(vec!["one", "two"])) as ArrayRef;
112 let values = Arc::new(Int32Array::from(vec![1, 2])) as ArrayRef;
113 let metadata = HashMap::from([("key".to_string(), "value".to_string())]);
114 let value_field =
115 Arc::new(Field::new("value", DataType::Int32, false).with_metadata(metadata.clone()));
116 let nulls = NullBuffer::from(vec![true, false]);
117
118 let array = StructArrayAssembler::new()
119 .with_field("name", names, false)
120 .with_field_ref(value_field, values)
121 .with_nulls(nulls.clone())
122 .build()
123 .unwrap();
124
125 assert_eq!(array.len(), 2);
126 assert_eq!(array.column_names(), &["name", "value"]);
127 assert_eq!(array.fields()[1].metadata(), &metadata);
128 assert_eq!(array.nulls(), Some(&nulls));
129 }
130
131 #[test]
132 fn build_errors_on_mismatched_child_lengths() {
133 let names = Arc::new(StringArray::from(vec!["one", "two"])) as ArrayRef;
134 let values = Arc::new(Int32Array::from(vec![1])) as ArrayRef;
135
136 let err = StructArrayAssembler::new()
137 .with_field("name", names, false)
138 .with_field("value", values, false)
139 .build()
140 .unwrap_err();
141
142 assert_eq!(
143 err.to_string(),
144 "Invalid argument error: Incorrect array length for StructArray field \"value\", expected 2 got 1"
145 );
146 }
147
148 #[test]
149 fn build_errors_on_mismatched_field_data_type() {
150 let value_field = Arc::new(Field::new("value", DataType::Int64, false));
151 let values = Arc::new(Int32Array::from(vec![1, 2])) as ArrayRef;
152
153 let err = StructArrayAssembler::new()
154 .with_field_ref(value_field, values)
155 .build()
156 .unwrap_err();
157
158 assert_eq!(
159 err.to_string(),
160 "Invalid argument error: Incorrect datatype for StructArray field \"value\", expected Int64 got Int32"
161 );
162 }
163}