Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix field accesses serializing when using names like min and max and support arrays #2

Merged
merged 2 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,15 @@ members = [
"arrow_convert_derive",
"examples/simple"
]

[workspace.package]
version = "0.6.1"
authors = [
"Swoorup Joshi <[email protected]>",
"Jorge Leitao <[email protected]>",
"Chandra Penke <[email protected]>",
]
edition = "2021"
license = "Apache-2.0 OR MIT"
keywords = ["Arrow", "arrow"]
repository = "https://github.com/Swoorup/arrow-convert"
16 changes: 6 additions & 10 deletions arrow_convert/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
[package]
name = "arrow_convert"
version = "0.6.0"
authors = [
"Swoorup Joshi <[email protected]>",
"Jorge Leitao <[email protected]>",
"Chandra Penke <[email protected]>",
]
edition = "2021"
license = "Apache-2.0 OR MIT"
keywords = ["Arrow", "arrow"]
repository = "https://github.com/Swoorup/arrow-convert"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
keywords.workspace = true
repository.workspace = true
description = "Convert between nested rust types and Arrow with arrow"

[dependencies]
Expand Down
24 changes: 23 additions & 1 deletion arrow_convert/src/deserialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,6 @@ where
arrow_deserialize_vec_helper::<T>(v)
}
}

impl<'a, OffsetSize: OffsetSizeTrait> IntoArrowArrayIterator for &'a GenericListArray<OffsetSize> {
type Item = Option<Arc<dyn Array>>;

Expand Down Expand Up @@ -432,6 +431,29 @@ where
arrow_deserialize_vec_helper::<T>(v)
}
}
impl<T, const SIZE: usize> ArrowDeserialize for [T; SIZE]
where
T: ArrowDeserialize + ArrowEnableVecForType + 'static,
<T as ArrowDeserialize>::ArrayType: 'static,
for<'b> &'b <T as ArrowDeserialize>::ArrayType: IntoArrowArrayIterator,
{
type ArrayType = FixedSizeListArray;

fn arrow_deserialize(v: Option<Arc<dyn Array>>) -> Option<<Self as ArrowField>::Type> {
let result = arrow_deserialize_vec_helper::<T>(v)?;
let length = result.len();

match <[<T as ArrowField>::Type; SIZE]>::try_from(result).ok() {
None => panic!(
"Expected size of {} deserializing array of type `{}`, got {}",
std::any::type_name::<T>(),
SIZE,
length
),
array => array,
}
}
}

impl_arrow_array!(BooleanArray);
impl_arrow_array!(StringArray);
Expand Down
14 changes: 14 additions & 0 deletions arrow_convert/src/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,20 @@ where
}
}

impl<T, const SIZE: usize> ArrowField for [T; SIZE]
where
T: ArrowField + ArrowEnableVecForType,
{
type Type = [<T as ArrowField>::Type; SIZE];
type Native = [<T as ArrowField>::Native; SIZE];

#[inline]
fn data_type() -> arrow::datatypes::DataType {
let field = Field::new("item", <T as ArrowField>::data_type(), true);
arrow::datatypes::DataType::FixedSizeList(Arc::new(field), SIZE as i32)
}
}

arrow_enable_vec_for_type!(String);
arrow_enable_vec_for_type!(LargeString);
arrow_enable_vec_for_type!(bool);
Expand Down
25 changes: 25 additions & 0 deletions arrow_convert/src/serialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,31 @@ where
}
}

impl<T, const SIZE: usize> ArrowSerialize for [T; SIZE]
where
T: ArrowSerialize + ArrowEnableVecForType + 'static,
<T as ArrowSerialize>::ArrayBuilderType: Default,
{
type ArrayBuilderType = FixedSizeListBuilder<<T as ArrowSerialize>::ArrayBuilderType>;

#[inline]
fn new_array() -> Self::ArrayBuilderType {
Self::ArrayBuilderType::new(<T as ArrowSerialize>::new_array(), SIZE as i32)
}

fn arrow_serialize(
v: &<Self as ArrowField>::Type,
array: &mut Self::ArrayBuilderType,
) -> arrow::error::Result<()> {
let values = array.values();
for i in v.iter() {
<T as ArrowSerialize>::arrow_serialize(i, values)?;
}
array.append(true);
Ok(())
}
}

// internal helper method to extend a mutable array
fn arrow_serialize_extend_internal<
'a,
Expand Down
68 changes: 68 additions & 0 deletions arrow_convert/tests/test_array.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use arrow::array::Array;
use arrow::array::ArrayRef;
use arrow_convert::deserialize::TryIntoCollection;
use arrow_convert::serialize::TryIntoArrow;
/// Simple example
use arrow_convert::{ArrowDeserialize, ArrowField, ArrowSerialize};

#[derive(Debug, PartialEq, Clone, Copy, ArrowField, ArrowSerialize, ArrowDeserialize)]
pub struct QuadPoints {
points: [Point; 4],
}

#[derive(Clone, Copy, ArrowField, ArrowSerialize, ArrowDeserialize)]
pub struct AABB {
min: Point,
max: Point,
}

#[derive(Debug, PartialEq, Clone, Copy, ArrowField, ArrowSerialize, ArrowDeserialize)]
pub struct Point {
x: f64,
y: f64,
}

#[test]
fn test_simple_roundtrip() {
let original_array = vec![
QuadPoints {
points: [
Point { x: 0.0, y: 0.0 },
Point { x: 1.0, y: 0.0 },
Point { x: 1.0, y: 1.0 },
Point { x: 0.0, y: 1.0 },
],
},
QuadPoints {
points: [
Point { x: 0.0, y: 0.0 },
Point { x: 2.0, y: 0.0 },
Point { x: 2.0, y: 2.0 },
Point { x: 0.0, y: 2.0 },
],
},
QuadPoints {
points: [
Point { x: 0.0, y: 0.0 },
Point { x: 3.0, y: 0.0 },
Point { x: 3.0, y: 3.0 },
Point { x: 0.0, y: 3.0 },
],
},
];

// serialize to an arrow array. try_into_arrow() is enabled by the TryIntoArrow trait
let arrow_array: ArrayRef = original_array.try_into_arrow().unwrap();

// which can be cast to an Arrow StructArray and be used for all kinds of IPC, FFI, etc.
// supported by `arrow`
let struct_array = arrow_array
.as_any()
.downcast_ref::<arrow::array::StructArray>()
.unwrap();
assert_eq!(struct_array.len(), 3);

// deserialize back to our original vector via TryIntoCollection trait.
let round_trip_array: Vec<QuadPoints> = arrow_array.try_into_collection().unwrap();
assert_eq!(round_trip_array, original_array);
}
16 changes: 6 additions & 10 deletions arrow_convert_derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
[package]
name = "arrow_convert_derive"
version = "0.6.0"
authors = [
"Swoorup Joshi <[email protected]>",
"Jorge Leitao <[email protected]>",
"Chandra Penke <[email protected]>"
]
edition = "2021"
license = "Apache-2.0 OR MIT"
keywords = ["Arrow", "arrow"]
repository = "https://github.com/Swoorup/arrow-convert"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
keywords.workspace = true
repository.workspace = true
description = "Proc macros for arrow_convert"

[lib]
Expand Down
13 changes: 7 additions & 6 deletions arrow_convert_derive/src/derive_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct Common<'a> {
field_idents: Vec<syn::Ident>,
skipped_field_names: Vec<syn::Member>,
field_indices: Vec<syn::LitInt>,
field_types: Vec<&'a syn::TypePath>,
field_types: Vec<&'a syn::Type>,
}

impl<'a> From<&'a DeriveStruct> for Common<'a> {
Expand Down Expand Up @@ -73,13 +73,14 @@ impl<'a> From<&'a DeriveStruct> for Common<'a> {
})
.collect::<Vec<_>>();

let field_types: Vec<&syn::TypePath> = fields
let field_types: Vec<&syn::Type> = fields
.iter()
.map(|field| match &field.field_type {
syn::Type::Path(path) => path,
_ => panic!("Only types are supported atm"),
syn::Type::Path(_) => &field.field_type,
syn::Type::Array(_) => &field.field_type,
x => panic!("Only types are supported atm: {:#?}", x),
})
.collect::<Vec<&syn::TypePath>>();
.collect::<Vec<&syn::Type>>();

Self {
original_name,
Expand Down Expand Up @@ -204,7 +205,7 @@ pub fn expand_serialize(input: DeriveStruct) -> TokenStream {

match item {
Some(i) => {
let i = i.borrow();
let i = i.borrow() as &#original_name;
#(
<#field_types as arrow_convert::serialize::ArrowSerialize>::arrow_serialize(i.#field_names.borrow(), &mut self.#field_idents)?;
)*;
Expand Down
Loading