Skip to content

Commit 907c293

Browse files
committed
Add try_new_with_length
1 parent 6468298 commit 907c293

File tree

1 file changed

+66
-8
lines changed

1 file changed

+66
-8
lines changed

arrow-array/src/array/struct_array.rs

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,28 @@ impl StructArray {
9191
Self::try_new(fields, arrays, nulls).unwrap()
9292
}
9393

94+
/// Create a new [`StructArray`] from the provided parts, returning an error on failure
95+
///
96+
/// The length will be inferred from the length of the child arrays. Returns an error if
97+
/// there are no child arrays. Consider using [`Self::try_new_with_length`] if the length
98+
/// is known to avoid this.
99+
///
100+
/// # Errors
101+
///
102+
/// Errors if
103+
///
104+
/// * `fields.len() == 0`
105+
/// * Any reason that [`Self::try_new_with_length`] would error
106+
pub fn try_new(
107+
fields: Fields,
108+
arrays: Vec<ArrayRef>,
109+
nulls: Option<NullBuffer>,
110+
) -> Result<Self, ArrowError> {
111+
let len = arrays.first().map(|x| x.len()).ok_or_else(||ArrowError::InvalidArgumentError("use StructArray::try_new_with_length or StructArray::new_empty to create a struct array with no fields so that the length can be set correctly".to_string()))?;
112+
113+
Self::try_new_with_length(fields, arrays, nulls, len)
114+
}
115+
94116
/// Create a new [`StructArray`] from the provided parts, returning an error on failure
95117
///
96118
/// # Errors
@@ -102,10 +124,11 @@ impl StructArray {
102124
/// * `arrays[i].len() != arrays[j].len()`
103125
/// * `arrays[i].len() != nulls.len()`
104126
/// * `!fields[i].is_nullable() && !nulls.contains(arrays[i].nulls())`
105-
pub fn try_new(
127+
pub fn try_new_with_length(
106128
fields: Fields,
107129
arrays: Vec<ArrayRef>,
108130
nulls: Option<NullBuffer>,
131+
len: usize,
109132
) -> Result<Self, ArrowError> {
110133
if fields.len() != arrays.len() {
111134
return Err(ArrowError::InvalidArgumentError(format!(
@@ -115,8 +138,6 @@ impl StructArray {
115138
)));
116139
}
117140

118-
let len = arrays.first().map(|x| x.len()).ok_or_else(||ArrowError::InvalidArgumentError("use StructArray::new_empty_fields to create a struct array with no fields so that the length can be set correctly".to_string()))?;
119-
120141
if let Some(n) = nulls.as_ref() {
121142
if n.len() != len {
122143
return Err(ArrowError::InvalidArgumentError(format!(
@@ -182,6 +203,10 @@ impl StructArray {
182203

183204
/// Create a new [`StructArray`] from the provided parts without validation
184205
///
206+
/// The length will be inferred from the length of the child arrays. Panics if there are no
207+
/// child arrays. Consider using [`Self::new_unchecked_with_length`] if the length is known
208+
/// to avoid this.
209+
///
185210
/// # Safety
186211
///
187212
/// Safe if [`Self::new`] would not panic with the given arguments
@@ -194,10 +219,31 @@ impl StructArray {
194219
return Self::new(fields, arrays, nulls);
195220
}
196221

197-
let len = arrays
198-
.first()
199-
.map(|x| x.len())
200-
.expect("cannot use new_unchecked if there are no fields, length is unknown");
222+
let len = arrays.first().map(|x| x.len()).expect(
223+
"cannot use StructArray::new_unchecked if there are no fields, length is unknown",
224+
);
225+
Self {
226+
len,
227+
data_type: DataType::Struct(fields),
228+
nulls,
229+
fields: arrays,
230+
}
231+
}
232+
233+
/// Create a new [`StructArray`] from the provided parts without validation
234+
///
235+
/// # Safety
236+
///
237+
/// Safe if [`Self::new`] would not panic with the given arguments
238+
pub unsafe fn new_unchecked_with_length(
239+
fields: Fields,
240+
arrays: Vec<ArrayRef>,
241+
nulls: Option<NullBuffer>,
242+
len: usize,
243+
) -> Self {
244+
if cfg!(feature = "force_validate") {
245+
return Self::try_new_with_length(fields, arrays, nulls, len).unwrap();
246+
}
201247

202248
Self {
203249
len,
@@ -822,7 +868,7 @@ mod tests {
822868
}
823869

824870
#[test]
825-
#[should_panic(expected = "use StructArray::new_empty_fields")]
871+
#[should_panic(expected = "use StructArray::try_new_with_length")]
826872
fn test_struct_array_from_empty() {
827873
// This can't work because we don't know how many rows the array should have. Previously we inferred 0 but
828874
// that often led to bugs.
@@ -838,10 +884,22 @@ mod tests {
838884
assert_eq!(arr.null_count(), 0);
839885
assert_eq!(arr.num_columns(), 0);
840886

887+
let arr2 = StructArray::try_new_with_length(Fields::empty(), vec![], None, 10).unwrap();
888+
assert_eq!(arr2.len(), 10);
889+
841890
let arr = StructArray::new_empty_fields(10, Some(NullBuffer::new_null(10)));
842891
assert_eq!(arr.len(), 10);
843892
assert_eq!(arr.null_count(), 10);
844893
assert_eq!(arr.num_columns(), 0);
894+
895+
let arr2 = StructArray::try_new_with_length(
896+
Fields::empty(),
897+
vec![],
898+
Some(NullBuffer::new_null(10)),
899+
10,
900+
)
901+
.unwrap();
902+
assert_eq!(arr2.len(), 10);
845903
}
846904

847905
#[test]

0 commit comments

Comments
 (0)