use anyhow::Result;
use arrow_array::builder::ArrayBuilder;
use arrow_array::Array;
use std::sync::Arc;
pub trait RowBuilder<'a, T> {
fn add_row(&mut self, msg: &T) -> Result<()>;
fn add_raw_row(&mut self, msg: &[u8]) -> Result<()>;
fn to_arc_arrays(&mut self) -> Vec<Arc<dyn Array>>;
}
pub trait ArrowSupport<'a> {
type RowBuilderType;
type FlatRowBuilderType;
fn schema_name() -> &'static str;
fn new_row_builder(arrow_fields: Vec<&'a arrow_schema::Field>) -> Self::RowBuilderType;
fn new_flat_row_builder(arrow_fields: Vec<&'a arrow_schema::Field>)
-> Self::FlatRowBuilderType;
fn arrow_fields(include_msg_struct: bool) -> Vec<arrow_schema::Field>;
fn arrow_schema(include_msg_struct: bool) -> arrow_schema::Schema;
fn flat_arrow_fields(include_msg_struct: bool) -> Vec<arrow_schema::Field>;
fn flat_arrow_schema(include_msg_struct: bool) -> arrow_schema::Schema;
}
#[cfg(feature = "default")]
include!(concat!(env!("OUT_DIR"), "/generated_arrow_mappers.rs"));
#[cfg(test)]
mod tests {
use super::ArrowSupport;
use super::RowBuilder;
use r2r::builtin_interfaces::msg::Time;
use r2r::std_msgs::msg::Header;
#[test]
fn test_append_and_to_array() {
let mut v = Vec::with_capacity(100);
for _ in 0..100 {
v.push(Header {
stamp: Time { sec: 0, nanosec: 0 },
frame_id: "test_frame".to_string(),
});
}
let fields = Header::arrow_fields(true);
let fields = fields.iter().filter(|f| f.name() == "stamp").collect();
let mut row_builder = Header::new_row_builder(fields);
for msg in v.iter() {
assert!(row_builder.add_row(msg).is_ok());
}
let arrays = row_builder.to_arc_arrays();
assert_eq!(arrays.len(), 1);
assert_eq!(arrays[0].len(), 100);
assert_eq!(arrays[0].null_count(), 0);
let is_correct_struct = match arrays[0].data_type() {
arrow_schema::DataType::Struct(fields) => {
fields.len() == 2
&& fields.get(0).unwrap().name() == "sec"
&& fields.get(0).unwrap().data_type() == &arrow_schema::DataType::Int32
&& fields.get(1).unwrap().name() == "nanosec"
&& fields.get(1).unwrap().data_type() == &arrow_schema::DataType::UInt32
}
_ => false,
};
assert!(is_correct_struct);
}
#[test]
fn test_append_and_to_array_flat() {
let mut v = Vec::with_capacity(100);
for _ in 0..100 {
v.push(Header {
stamp: Time { sec: 0, nanosec: 0 },
frame_id: "test_frame".to_string(),
});
}
let fields = Header::flat_arrow_fields(true);
let fields = fields
.iter()
.filter(|f| f.name() == "stamp_sec" || f.name() == "message_struct")
.collect();
let mut row_builder = Header::new_flat_row_builder(fields);
for msg in v.iter() {
assert!(row_builder.add_row(msg).is_ok());
}
let arrays = row_builder.to_arc_arrays();
assert_eq!(arrays.len(), 2);
assert_eq!(arrays[0].len(), 100);
assert_eq!(arrays[0].null_count(), 0);
assert!(arrays[0].data_type() == &arrow_schema::DataType::Int32);
let is_correct_struct = match arrays[1].data_type() {
arrow_schema::DataType::Struct(fields) => {
assert!(fields.get(0).unwrap().name() == "stamp");
match fields.get(0).unwrap().data_type() {
arrow_schema::DataType::Struct(fields) => {
fields.len() == 2
&& fields.get(0).unwrap().name() == "sec"
&& fields.get(0).unwrap().data_type() == &arrow_schema::DataType::Int32
&& fields.get(1).unwrap().name() == "nanosec"
&& fields.get(1).unwrap().data_type() == &arrow_schema::DataType::UInt32
}
_ => false,
}
}
_ => false,
};
assert!(is_correct_struct);
}
}