From 412631b6705257f571518a4bb2133a5a4d9cb7d3 Mon Sep 17 00:00:00 2001 From: Matthijs Brobbel Date: Thu, 5 Sep 2024 16:03:33 +0200 Subject: [PATCH 1/2] feat!: make `StructArray` generic over child array `OffsetElement` and `UnionType` --- narrow-derive/src/struct.rs | 2 +- src/array/struct.rs | 178 +++++++++++++++++++++++++----------- src/arrow/array/struct.rs | 116 ++++++++++++++--------- 3 files changed, 202 insertions(+), 94 deletions(-) diff --git a/narrow-derive/src/struct.rs b/narrow-derive/src/struct.rs index aa55de1..3340435 100644 --- a/narrow-derive/src/struct.rs +++ b/narrow-derive/src/struct.rs @@ -246,7 +246,7 @@ impl Struct<'_> { let array_struct_ident = self.array_struct_ident(); let tokens = quote! { impl #impl_generics #narrow::array::StructArrayType for #ident #ty_generics #where_clause { - type Array = #array_struct_ident #array_ty_generics; + type Array = #array_struct_ident #array_ty_generics; } }; parse2(tokens).expect("struct_array_type_impl") diff --git a/src/array/struct.rs b/src/array/struct.rs index af03cb7..5f0cd5c 100644 --- a/src/array/struct.rs +++ b/src/array/struct.rs @@ -1,10 +1,11 @@ //! Array for product types. -use super::{Array, ArrayType}; +use super::{union, Array, ArrayType, UnionType}; use crate::{ bitmap::{Bitmap, BitmapRef, BitmapRefMut, ValidityBitmap}, buffer::{BufferType, VecBuffer}, nullable::Nullable, + offset::{self, OffsetElement}, validity::{Nullability, Validity}, Length, }; @@ -15,7 +16,7 @@ pub trait StructArrayType: ArrayType { /// the [`ArrayType`] array because that wraps this array. Also note that this /// has no [`Array`] bound. // TODO(mbrobbe): add offset and union generics - type Array; // into this then requires all arraytype impls to provide a field + type Array; // into this then requires all arraytype impls to provide a field } /// Array for product types. @@ -23,13 +24,21 @@ pub struct StructArray< T: StructArrayType, const NULLABLE: bool = false, Buffer: BufferType = VecBuffer, ->(pub <::Array as Validity>::Storage) + OffsetItem: OffsetElement = offset::NA, + UnionLayout: UnionType = union::NA, +>(pub <::Array as Validity>::Storage) where - ::Array: Validity; - -impl StructArray + ::Array: Validity; + +impl< + T: StructArrayType, + const NULLABLE: bool, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > StructArray where - ::Array: Validity, + ::Array: Validity, for<'a> &'a Self: IntoIterator, { /// Returns an iterator over the items in this [`StructArray`]. @@ -38,105 +47,155 @@ where } } -impl Array - for StructArray +impl< + T: StructArrayType, + const NULLABLE: bool, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > Array for StructArray where - ::Array: Validity, + ::Array: Validity, T: Nullability, { type Item = >::Item; } -impl Clone - for StructArray +impl< + T: StructArrayType, + const NULLABLE: bool, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > Clone for StructArray where - ::Array: Validity, - <::Array as Validity>::Storage: Clone, + ::Array: Validity, + <::Array as Validity>::Storage< + Buffer, + >: Clone, { fn clone(&self) -> Self { Self(self.0.clone()) } } -impl Default - for StructArray +impl< + T: StructArrayType, + const NULLABLE: bool, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > Default for StructArray where - ::Array: Validity, - <::Array as Validity>::Storage: Default, + ::Array: Validity, + <::Array as Validity>::Storage< + Buffer, + >: Default, { fn default() -> Self { Self(Default::default()) } } -impl From> - for StructArray +impl + From> + for StructArray where - ::Array: Length, + ::Array: Length, Bitmap: FromIterator, { - fn from(value: StructArray) -> Self { + fn from(value: StructArray) -> Self { Self(Nullable::from(value.0)) } } -impl FromIterator - for StructArray +impl< + T: StructArrayType, + U, + const NULLABLE: bool, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > FromIterator for StructArray where - ::Array: Validity, - <::Array as Validity>::Storage: FromIterator, + ::Array: Validity, + <::Array as Validity>::Storage< + Buffer, + >: FromIterator, { fn from_iter>(iter: I) -> Self { Self(iter.into_iter().collect()) } } -impl Extend for StructArray +impl< + T: StructArrayType, + U, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > Extend for StructArray where - ::Array: Extend, + ::Array: Extend, { fn extend>(&mut self, iter: I) { self.0.extend(iter); } } -impl Extend> for StructArray +impl< + T: StructArrayType, + U, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > Extend> for StructArray where - Nullable<::Array, Buffer>: Extend>, + Nullable<::Array, Buffer>: + Extend>, { fn extend>>(&mut self, iter: I) { self.0.extend(iter); } } -impl IntoIterator - for StructArray +impl< + T: StructArrayType, + const NULLABLE: bool, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > IntoIterator for StructArray where T: Nullability, - ::Array: Validity, - <::Array as Validity>::Storage: IntoIterator, + ::Array: Validity, + <::Array as Validity>::Storage< + Buffer, + >: IntoIterator, { - type Item = <<::Array as Validity>::Storage as - IntoIterator>::Item; - type IntoIter = <<::Array as Validity>::Storage as - IntoIterator>::IntoIter; + type Item = <<::Array as Validity< + NULLABLE, + >>::Storage as IntoIterator>::Item; + type IntoIter = <<::Array as Validity< + NULLABLE, + >>::Storage as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } -impl<'a, T: StructArrayType, const NULLABLE: bool, Buffer: BufferType> IntoIterator - for &'a StructArray +impl<'a, T: StructArrayType, const NULLABLE: bool, Buffer: BufferType, OffsetItem: OffsetElement, UnionLayout: UnionType> IntoIterator + for &'a StructArray where T: Nullability, - ::Array: Validity, - &'a <::Array as Validity>::Storage: + ::Array: Validity, + &'a <::Array as Validity>::Storage: IntoIterator, { - type Item = <&'a <::Array as Validity>::Storage as + type Item = <&'a <::Array as Validity>::Storage as IntoIterator>::Item; - type IntoIter = <&'a <::Array as Validity>::Storage< + type IntoIter = <&'a <::Array as Validity>::Storage< Buffer, > as IntoIterator>::IntoIter; @@ -145,18 +204,27 @@ where } } -impl Length - for StructArray +impl< + T: StructArrayType, + const NULLABLE: bool, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > Length for StructArray where - ::Array: Validity, - <::Array as Validity>::Storage: Length, + ::Array: Validity, + <::Array as Validity>::Storage< + Buffer, + >: Length, { fn len(&self) -> usize { self.0.len() } } -impl BitmapRef for StructArray { +impl + BitmapRef for StructArray +{ type Buffer = Buffer; fn bitmap_ref(&self) -> &Bitmap { @@ -164,13 +232,18 @@ impl BitmapRef for StructArray BitmapRefMut for StructArray { +impl + BitmapRefMut for StructArray +{ fn bitmap_ref_mut(&mut self) -> &mut Bitmap { self.0.bitmap_ref_mut() } } -impl ValidityBitmap for StructArray {} +impl + ValidityBitmap for StructArray +{ +} #[cfg(test)] mod tests { @@ -312,7 +385,8 @@ mod tests { } } impl<'a> StructArrayType for Foo<'a> { - type Array = FooArray<'a, Buffer>; + type Array = + FooArray<'a, Buffer>; } impl<'a, Buffer: BufferType> Length for FooArray<'a, Buffer> diff --git a/src/arrow/array/struct.rs b/src/arrow/array/struct.rs index e2da246..cab81d2 100644 --- a/src/arrow/array/struct.rs +++ b/src/arrow/array/struct.rs @@ -6,10 +6,11 @@ use arrow_buffer::NullBuffer; use arrow_schema::{DataType, Field, Fields}; use crate::{ - array::{StructArray, StructArrayType}, + array::{StructArray, StructArrayType, UnionType}, bitmap::Bitmap, buffer::BufferType, nullable::Nullable, + offset::OffsetElement, validity::{Nullability, Validity}, Length, }; @@ -20,10 +21,16 @@ pub trait StructArrayTypeFields { fn fields() -> Fields; } -impl crate::arrow::Array - for StructArray +impl< + T: StructArrayType, + const NULLABLE: bool, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > crate::arrow::Array for StructArray where - ::Array: Validity + StructArrayTypeFields, + ::Array: + Validity + StructArrayTypeFields, T: Nullability, { type Array = arrow_array::StructArray; @@ -31,18 +38,26 @@ where fn as_field(name: &str) -> arrow_schema::Field { Field::new( name, - DataType::Struct( - <::Array as StructArrayTypeFields>::fields(), - ), + DataType::Struct(<::Array< + Buffer, + OffsetItem, + UnionLayout, + > as StructArrayTypeFields>::fields()), NULLABLE, ) } } -impl From> - for StructArray +impl< + T: StructArrayType, + const NULLABLE: bool, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > From> + for StructArray where - ::Array: Validity, + ::Array: Validity, Self: From, { fn from(value: Arc) -> Self { @@ -50,29 +65,35 @@ where } } -impl - From> for Arc +impl< + T: StructArrayType, + const NULLABLE: bool, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > From> + for Arc where - ::Array: Validity, - arrow_array::StructArray: From>, + ::Array: Validity, + arrow_array::StructArray: From>, { - fn from(value: StructArray) -> Self { + fn from(value: StructArray) -> Self { Arc::new(arrow_array::StructArray::from(value)) } } -impl From> - for arrow_array::StructArray +impl + From> for arrow_array::StructArray where - ::Array: + ::Array: StructArrayTypeFields + Into>>, { - fn from(value: StructArray) -> Self { + fn from(value: StructArray) -> Self { // Safety: // - struct arrays are valid by construction unsafe { arrow_array::StructArray::new_unchecked( - <::Array as StructArrayTypeFields>::fields(), + <::Array as StructArrayTypeFields>::fields(), value.0.into(), None, ) @@ -80,19 +101,19 @@ where } } -impl From> - for arrow_array::StructArray +impl + From> for arrow_array::StructArray where - ::Array: + ::Array: StructArrayTypeFields + Into>>, Bitmap: Into, { - fn from(value: StructArray) -> Self { + fn from(value: StructArray) -> Self { // Safety: // - struct arrays are valid by construction unsafe { arrow_array::StructArray::new_unchecked( - <::Array as StructArrayTypeFields>::fields(), + <::Array as StructArrayTypeFields>::fields(), value.0.data.into(), Some(value.0.validity.into()), ) @@ -101,10 +122,11 @@ where } /// Panics when there are nulls -impl From - for StructArray +impl + From for StructArray where - ::Array: From>>, + ::Array: + From>>, { fn from(value: arrow_array::StructArray) -> Self { let (_fields, arrays, nulls_opt) = value.into_parts(); @@ -115,10 +137,11 @@ where } } -impl From - for StructArray +impl + From for StructArray where - ::Array: From>> + Length, + ::Array: + From>> + Length, Bitmap: From + FromIterator, { fn from(value: arrow_array::StructArray) -> Self { @@ -129,26 +152,36 @@ where data, validity: null_buffer.into(), }), - None => StructArray::(data).into(), + None => StructArray::(data).into(), } } } -impl - From> for arrow_array::RecordBatch +impl< + T: StructArrayType, + const NULLABLE: bool, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > From> for arrow_array::RecordBatch where - ::Array: Validity, - arrow_array::StructArray: From>, + ::Array: Validity, + arrow_array::StructArray: From>, { - fn from(value: StructArray) -> Self { + fn from(value: StructArray) -> Self { Self::from(arrow_array::StructArray::from(value)) } } -impl From - for StructArray +impl< + T: StructArrayType, + const NULLABLE: bool, + Buffer: BufferType, + OffsetItem: OffsetElement, + UnionLayout: UnionType, + > From for StructArray where - ::Array: Validity, + ::Array: Validity, Self: From, { fn from(value: arrow_array::RecordBatch) -> Self { @@ -250,7 +283,8 @@ mod tests { } } impl StructArrayType for Foo { - type Array = FooArray; + type Array = + FooArray; } impl StructArrayTypeFields for FooArray { fn fields() -> Fields { From 61b400feaf482a1c88222adbc3fded77eeec9a86 Mon Sep 17 00:00:00 2001 From: Matthijs Brobbel Date: Thu, 5 Sep 2024 16:06:04 +0200 Subject: [PATCH 2/2] Update macrotest output --- .../expand/struct/named/generic.expanded.rs | 6 +++++- .../struct/named/generic_option.expanded.rs | 6 +++++- .../expand/struct/named/simple.expanded.rs | 6 +++++- .../struct/unit/const_generic.expanded.rs | 6 +++++- .../unit/const_generic_default.expanded.rs | 6 +++++- .../tests/expand/struct/unit/self.expanded.rs | 6 +++++- .../expand/struct/unit/simple.expanded.rs | 6 +++++- .../struct/unit/where_clause.expanded.rs | 6 +++++- .../expand/struct/unnamed/generic.expanded.rs | 12 ++++++++++-- .../expand/struct/unnamed/lifetime.expanded.rs | 6 +++++- .../expand/struct/unnamed/multiple.expanded.rs | 6 +++++- .../expand/struct/unnamed/nested.expanded.rs | 12 ++++++++++-- .../struct/unnamed/nested_generic.expanded.rs | 18 +++++++++++++++--- .../expand/struct/unnamed/simple.expanded.rs | 6 +++++- 14 files changed, 90 insertions(+), 18 deletions(-) diff --git a/narrow-derive/tests/expand/struct/named/generic.expanded.rs b/narrow-derive/tests/expand/struct/named/generic.expanded.rs index d90b08b..285b7d0 100644 --- a/narrow-derive/tests/expand/struct/named/generic.expanded.rs +++ b/narrow-derive/tests/expand/struct/named/generic.expanded.rs @@ -30,7 +30,11 @@ impl<'a, T: narrow::array::ArrayType> narrow::array::StructArrayType for Foo< where T: Copy, { - type Array = FooArray<'a, T, Buffer>; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooArray<'a, T, Buffer>; } struct FooArray<'a, T: narrow::array::ArrayType, Buffer: narrow::buffer::BufferType> where diff --git a/narrow-derive/tests/expand/struct/named/generic_option.expanded.rs b/narrow-derive/tests/expand/struct/named/generic_option.expanded.rs index 6a869d5..deb9cb0 100644 --- a/narrow-derive/tests/expand/struct/named/generic_option.expanded.rs +++ b/narrow-derive/tests/expand/struct/named/generic_option.expanded.rs @@ -19,7 +19,11 @@ for ::std::option::Option> { > = narrow::array::StructArray, true, Buffer>; } impl> narrow::array::StructArrayType for Bar { - type Array = BarArray; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = BarArray; } struct BarArray, Buffer: narrow::buffer::BufferType> { a: for ::std::option::Option { > = narrow::array::StructArray; } impl narrow::array::StructArrayType for Foo { - type Array = FooArray; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooArray; } struct FooArray { a: narrow::array::ArrayType> for ::std::option::Option< > = narrow::array::StructArray, true, Buffer>; } impl narrow::array::StructArrayType for Foo { - type Array = FooArray; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooArray; } pub struct FooArray( pub narrow::array::NullArray, false, Buffer>, diff --git a/narrow-derive/tests/expand/struct/unit/const_generic_default.expanded.rs b/narrow-derive/tests/expand/struct/unit/const_generic_default.expanded.rs index 972f2f0..a9e699c 100644 --- a/narrow-derive/tests/expand/struct/unit/const_generic_default.expanded.rs +++ b/narrow-derive/tests/expand/struct/unit/const_generic_default.expanded.rs @@ -19,7 +19,11 @@ impl narrow::array::ArrayType> for ::std::option::Option< > = narrow::array::StructArray, true, Buffer>; } impl narrow::array::StructArrayType for Foo { - type Array = FooArray; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooArray; } pub struct FooArray( pub narrow::array::NullArray, false, Buffer>, diff --git a/narrow-derive/tests/expand/struct/unit/self.expanded.rs b/narrow-derive/tests/expand/struct/unit/self.expanded.rs index 61da210..f0bb5d3 100644 --- a/narrow-derive/tests/expand/struct/unit/self.expanded.rs +++ b/narrow-derive/tests/expand/struct/unit/self.expanded.rs @@ -33,7 +33,11 @@ impl narrow::array::StructArrayType for Foo where Self: Debug, { - type Array = FooArray; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooArray; } struct FooArray( narrow::array::NullArray, diff --git a/narrow-derive/tests/expand/struct/unit/simple.expanded.rs b/narrow-derive/tests/expand/struct/unit/simple.expanded.rs index e34b02f..6853eef 100644 --- a/narrow-derive/tests/expand/struct/unit/simple.expanded.rs +++ b/narrow-derive/tests/expand/struct/unit/simple.expanded.rs @@ -19,7 +19,11 @@ impl narrow::array::ArrayType for ::std::option::Option { > = narrow::array::StructArray; } impl narrow::array::StructArrayType for Foo { - type Array = FooArray; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooArray; } struct FooArray( narrow::array::NullArray, diff --git a/narrow-derive/tests/expand/struct/unit/where_clause.expanded.rs b/narrow-derive/tests/expand/struct/unit/where_clause.expanded.rs index 2dd37ca..d6d2917 100644 --- a/narrow-derive/tests/expand/struct/unit/where_clause.expanded.rs +++ b/narrow-derive/tests/expand/struct/unit/where_clause.expanded.rs @@ -38,7 +38,11 @@ where Self: Sized, (): From, { - type Array = FooArray; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooArray; } pub(super) struct FooArray( pub(super) narrow::array::NullArray, false, Buffer>, diff --git a/narrow-derive/tests/expand/struct/unnamed/generic.expanded.rs b/narrow-derive/tests/expand/struct/unnamed/generic.expanded.rs index 18d3b4a..d43309e 100644 --- a/narrow-derive/tests/expand/struct/unnamed/generic.expanded.rs +++ b/narrow-derive/tests/expand/struct/unnamed/generic.expanded.rs @@ -34,7 +34,11 @@ where Self: Sized, >::Output: Debug, { - type Array = FooArray<'a, T, Buffer>; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooArray<'a, T, Buffer>; } struct FooArray< 'a, @@ -227,7 +231,11 @@ for ::std::option::Option> { > = narrow::array::StructArray, true, Buffer>; } impl> narrow::array::StructArrayType for FooBar { - type Array = FooBarArray; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooBarArray; } struct FooBarArray, Buffer: narrow::buffer::BufferType>( > { > = narrow::array::StructArray, true, Buffer>; } impl<'a, T: narrow::array::ArrayType> narrow::array::StructArrayType for Foo<'a, T> { - type Array = FooArray<'a, T, Buffer>; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooArray<'a, T, Buffer>; } struct FooArray<'a, T: narrow::array::ArrayType, Buffer: narrow::buffer::BufferType>( <&'a T as narrow::array::ArrayType< diff --git a/narrow-derive/tests/expand/struct/unnamed/multiple.expanded.rs b/narrow-derive/tests/expand/struct/unnamed/multiple.expanded.rs index 702782c..254575c 100644 --- a/narrow-derive/tests/expand/struct/unnamed/multiple.expanded.rs +++ b/narrow-derive/tests/expand/struct/unnamed/multiple.expanded.rs @@ -14,7 +14,11 @@ impl narrow::array::ArrayType for ::std::option::Option { > = narrow::array::StructArray; } impl narrow::array::StructArrayType for Bar { - type Array = BarArray; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = BarArray; } struct BarArray( for ::std::option::Option { > = narrow::array::StructArray; } impl narrow::array::StructArrayType for Foo { - type Array = FooArray; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooArray; } struct FooArray( for ::std::option::Option { > = narrow::array::StructArray; } impl narrow::array::StructArrayType for Bar { - type Array = BarArray; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = BarArray; } struct BarArray( > narrow::array::StructArrayType for Foo where T: Copy, { - type Array = FooArray; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooArray; } struct FooArray, Buffer: narrow::buffer::BufferType>( > { > = narrow::array::StructArray, true, Buffer>; } impl<'a, T: narrow::array::ArrayType> narrow::array::StructArrayType for Bar<'a, T> { - type Array = BarArray<'a, T, Buffer>; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = BarArray<'a, T, Buffer>; } struct BarArray<'a, T: narrow::array::ArrayType, Buffer: narrow::buffer::BufferType>( <&'a Foo< @@ -385,7 +393,11 @@ impl<'a> narrow::array::ArrayType> for ::std::option::Option = narrow::array::StructArray, true, Buffer>; } impl<'a> narrow::array::StructArrayType for FooBar<'a> { - type Array = FooBarArray<'a, Buffer>; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooBarArray<'a, Buffer>; } struct FooBarArray<'a, Buffer: narrow::buffer::BufferType>( > { > = narrow::array::StructArray, true, Buffer>; } impl> narrow::array::StructArrayType for Foo { - type Array = FooArray; + type Array< + Buffer: narrow::buffer::BufferType, + OffsetItem: narrow::offset::OffsetElement, + UnionLayout: narrow::array::union::UnionType, + > = FooArray; } struct FooArray< T: Sized + narrow::array::ArrayType,