7 个版本 (4 个重大更改)
0.5.0 | 2023年5月9日 |
---|---|
0.4.2 | 2023年2月12日 |
0.3.2 | 2022年9月30日 |
0.3.0 | 2022年8月25日 |
0.1.0 | 2022年3月3日 |
#139 in #arrow
10,269 monthly downloads
在 arrow2_convert 中使用
61KB
1K SLoC
arrow2_convert
在 arrow2
之上提供API,用于在Rust类型和Arrow之间进行转换。
Arrow生态系统提供了多种方法,用于在Arrow与其他几种语言中的流行格式之间进行转换。本项目旨在满足以Rust为中心的数据管道轻松地在Arrow之间进行转换的需求,支持强类型和任意嵌套。
示例
以下示例执行了一个具有单个字段的结构的往返转换。
有关完整功能的用法,请参阅 complex_example.rs。
/// Simple example
use arrow2::array::Array;
use arrow2_convert::{deserialize::TryIntoCollection, serialize::TryIntoArrow, ArrowField, ArrowSerialize, ArrowDeserialize};
#[derive(Debug, Clone, PartialEq, ArrowField, ArrowSerialize, ArrowDeserialize)]
pub struct Foo {
name: String,
}
fn main() {
// an item
let original_array = [
Foo { name: "hello".to_string() },
Foo { name: "one more".to_string() },
Foo { name: "good bye".to_string() },
];
// serialize to an arrow array. try_into_arrow() is enabled by the TryIntoArrow trait
let arrow_array: Box<dyn Array> = 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 `arrow2`
let struct_array= arrow_array.as_any().downcast_ref::<arrow2::array::StructArray>().unwrap();
assert_eq!(struct_array.len(), 3);
// deserialize back to our original vector via TryIntoCollection trait.
let round_trip_array: Vec<Foo> = arrow_array.try_into_collection().unwrap();
assert_eq!(round_trip_array, original_array);
}
API
实现了 ArrowField
、ArrowSerialize
和 ArrowDeserialize
特性的类型可以通过 try_into_arrow
和 try_into_collection
方法转换为/从 Arrow。
可以使用 ArrowField
、ArrowSerialize
和 ArrowDeserialize
derive宏为结构和枚举生成这些特性的实现。也可以为需要手动实现这些特性的任何类型定义自定义实现,以进行到/从 Arrow的转换。
要将序列化为箭头格式,可以使用 TryIntoArrow::try_into_arrow
来将任何可迭代序列序列化为 arrow2::Array
或 arrow2::Chunk
。其中,arrow2::Array
表示内存中的箭头布局。而 arrow2::Chunk
表示列组,可以与 arrow2
API 结合使用,实现其他功能,例如转换为 Parquet 和箭头飞行 RPC。
从箭头格式反序列化时,可以使用 TryIntoCollection::try_into_collection
将 arrow2::Array
表示形式反序列化为实现了 FromIterator
的任何容器。
默认实现
为以下内容提供了上述特质的默认实现:
- 数值类型
- 其他类型
- 时间类型
- 如果 T 实现
ArrowField
,则使用 Option - 如果 T 实现
ArrowField
,则使用 Vec - 大箭头类型
LargeBinary
、LargeString
、LargeList
通过type
属性支持。有关使用方法,请参阅 complex_example.rs。 - 固定大小类型
FixedSizeBinary
、FixedSizeList
通过FixedSizeVec
类型覆盖支持。- 注意:不支持
FixedSizeList
的嵌套。
- 注意:不支持
枚举类型
枚举类型仍然是实验性功能,需要集成测试。Rust 枚举数组转换为 Arrow::UnionArray
。有关枚举的一些附加说明
- Rust 单元变体使用
bool
数据类型表示。
128i
128i 表示一个十进制数,在使用作为 Arrow 数据类型时需要指定精度和小数点位置。可以通过使用类型覆盖通过 I128
类型来指定精度和小数点位置。
例如,要将 i128
作为结构体中的字段使用
use arrow2_convert::field::I128;
use arrow2_convert::ArrowField;
#[derive(Debug, ArrowField)]
struct S {
#[arrow_field(type = "I128<32, 32>")]
field: i128,
}
可以使用 arrow_serialize_to_mutable_array
和 arrow_array_deserialize_iterator_as_type
方法将 vec<i128>
转换为/从箭头格式。
use arrow2::array::{Array, MutableArray};
use arrow2_convert::serialize::arrow_serialize_to_mutable_array;
use arrow2_convert::deserialize::arrow_array_deserialize_iterator_as_type;
use arrow2_convert::field::I128;
use std::borrow::Borrow;
fn convert_i128() {
let original_array = vec![1 as i128, 2, 3];
let b: Box<dyn Array> = arrow_serialize_to_mutable_array::<_, I128<32,32>, _>(
&original_array).unwrap().as_box();
let round_trip: Vec<i128> = arrow_array_deserialize_iterator_as_type::<_, I128<32,32>>(
b.borrow()).unwrap().collect();
assert_eq!(original_array, round_trip);
}
嵌套选项类型
由于 Arrow 格式仅支持一层有效性,嵌套选项类型,如 Option<Option<T>>
,在序列化为 Arrow 后,将丢失任何中间的 None 值嵌套。例如,Some(None)
将序列化为 None
。
缺少的功能
- 目前尚不支持泛型、切片和引用。
这并不是一个详尽无遗的列表。如果您需要功能,请提出问题。
内存
透传转换只进行一次内存复制。反序列化从 arrow2 到目标进行复制。序列化从源到 arrow2 进行复制。就地反序列化在理论上可能,但目前不支持。
内部结构
与 Serde 的相似之处
设计灵感来源于 serde。 ArrowSerialize
和 ArrowDeserialize
分别是 serde 的 Serialize
和 Deserialize
的类似物。
然而,与 serde 的特性提供了对 serde 数据模型的详尽和灵活映射不同,arrow2_convert 的特性提供了对 arrow2 数据结构的更窄映射。
具体来说,ArrowSerialize
特性提供了将类型序列化为相应的 arrow2::array::MutableArray
的逻辑。 ArrowDeserialize
特性从相应的 arrow2::array::ArrowArray
反序列化类型。
解决方案
部分实现特化和泛型关联类型(目前仅在夜间构建中可用)等功能可以极大地简化底层实现。
例如,需要显式启用 Vec 序列化,通过在原始类型上使用 arrow_enable_vec_for_type
宏。这是必要的,因为 Vec 是 Arrow 中的特殊类型,但没有实现特化就无法进行特殊处理。
泛型关联类型的可用性将简化大型和固定类型实现,因为可以定义泛型 MutableArray。理想情况下,为了代码的可重用性,我们不需要为大型和固定大小类型重新实现 ArrowSerialize
和 ArrowDeserialize
,因为原始类型是相同的。然而,这需要将泛型界限作为关联类型的一部分传递给特质的函数,而没有泛型关联类型这是不可能的。
因此,我们不得不牺牲代码的可重用性,通过提供占位符结构来分别实现大类型和固定大小类型的ArrowSerialize
和ArrowDeserialize
,从而引入一点复杂性。这也需要将相关的Type
关联类型引入到ArrowField
中,以便箭头类型可以通过宏字段属性进行覆盖,而不会影响实际类型。
许可
根据以下任一许可进行许可:
- Apache License,版本 2.0 (LICENSE-APACHE或https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT或http://opensource.org/licenses/MIT)
由您选择。
贡献
除非您明确说明,否则根据Apache-2.0许可中定义的,您提交给作品中的任何有意贡献,都应双许可,如上所述,没有任何额外条款或条件。
依赖关系
~1.5MB
~36K SLoC