From bf4f4df9861881522ce9ee01fbea3b505059bfbb Mon Sep 17 00:00:00 2001 From: "Jorge C. Leitao" Date: Tue, 1 Mar 2022 16:28:59 +0000 Subject: [PATCH] try_new_unchecked for ListArray --- src/array/list/mod.rs | 81 +++++++++++++++++++++++++++++++++++++- tests/it/array/list/mod.rs | 2 +- 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/array/list/mod.rs b/src/array/list/mod.rs index 4e9038abcd8..b34ce2b0c32 100644 --- a/src/array/list/mod.rs +++ b/src/array/list/mod.rs @@ -7,7 +7,11 @@ use crate::{ error::ArrowError, }; -use super::{new_empty_array, specification::try_check_offsets, Array, Offset}; +use super::{ + new_empty_array, + specification::{try_check_offsets, try_check_offsets_bounds}, + Array, Offset, +}; mod ffi; pub(super) mod fmt; @@ -35,6 +39,8 @@ impl ListArray { /// * the validity's length is not equal to `offsets.len() - 1`. /// * The `data_type`'s [`crate::datatypes::PhysicalType`] is not equal to either [`crate::datatypes::PhysicalType::List`] or [`crate::datatypes::PhysicalType::LargeList`]. /// * The `data_type`'s inner field's data type is not equal to `values.data_type`. + /// # Implementation + /// This function is `O(N)` - checking monotinicity is `O(N)` pub fn try_new( data_type: DataType, offsets: Buffer, @@ -77,6 +83,8 @@ impl ListArray { /// * the validity's length is not equal to `offsets.len() - 1`. /// * The `data_type`'s [`crate::datatypes::PhysicalType`] is not equal to either [`crate::datatypes::PhysicalType::List`] or [`crate::datatypes::PhysicalType::LargeList`]. /// * The `data_type`'s inner field's data type is not equal to `values.data_type`. + /// # Implementation + /// This function is `O(N)` - checking monotinicity is `O(N)` pub fn new( data_type: DataType, offsets: Buffer, @@ -115,6 +123,77 @@ impl ListArray { } } +// unsafe construtors +impl ListArray { + /// Creates a new [`ListArray`]. + /// + /// # Errors + /// This function returns an error iff: + /// * The last offset is not equal to the values' length. + /// * the validity's length is not equal to `offsets.len() - 1`. + /// * The `data_type`'s [`crate::datatypes::PhysicalType`] is not equal to either [`crate::datatypes::PhysicalType::List`] or [`crate::datatypes::PhysicalType::LargeList`]. + /// * The `data_type`'s inner field's data type is not equal to `values.data_type`. + /// # Safety + /// This function is unsafe iff: + /// * the offsets are not monotonically increasing + /// # Implementation + /// This function is `O(1)` + pub unsafe fn try_new_unchecked( + data_type: DataType, + offsets: Buffer, + values: Arc, + validity: Option, + ) -> Result { + try_check_offsets_bounds(&offsets, values.len())?; + + if validity + .as_ref() + .map_or(false, |validity| validity.len() != offsets.len() - 1) + { + return Err(ArrowError::oos( + "validity mask length must match the number of values", + )); + } + + let child_data_type = Self::try_get_child(&data_type)?.data_type(); + let values_data_type = values.data_type(); + if child_data_type != values_data_type { + return Err(ArrowError::oos( + format!("ListArray's child's DataType must match. However, the expected DataType is {child_data_type:?} while it got {values_data_type:?}."), + )); + } + + Ok(Self { + data_type, + offsets, + values, + validity, + }) + } + + /// Creates a new [`ListArray`]. + /// + /// # Panics + /// This function panics iff: + /// * The last offset is not equal to the values' length. + /// * the validity's length is not equal to `offsets.len() - 1`. + /// * The `data_type`'s [`crate::datatypes::PhysicalType`] is not equal to either [`crate::datatypes::PhysicalType::List`] or [`crate::datatypes::PhysicalType::LargeList`]. + /// * The `data_type`'s inner field's data type is not equal to `values.data_type`. + /// # Safety + /// This function is unsafe iff: + /// * the offsets are not monotonically increasing + /// # Implementation + /// This function is `O(1)` + pub unsafe fn new_unchecked( + data_type: DataType, + offsets: Buffer, + values: Arc, + validity: Option, + ) -> Self { + Self::try_new_unchecked(data_type, offsets, values, validity).unwrap() + } +} + impl ListArray { /// Returns a slice of this [`ListArray`]. /// # Panics diff --git a/tests/it/array/list/mod.rs b/tests/it/array/list/mod.rs index 78bc8dcd719..2a4e1feca4e 100644 --- a/tests/it/array/list/mod.rs +++ b/tests/it/array/list/mod.rs @@ -23,7 +23,7 @@ fn debug() { } #[test] -#[should_panic(expected = "The child's datatype must match the inner type of the \'data_type\'")] +#[should_panic] fn test_nested_panic() { let values = Buffer::from_slice([1, 2, 3, 4, 5]); let values = PrimitiveArray::::from_data(DataType::Int32, values, None);