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 日 |
#202 在 Rust 模式
每月 10,264 次下载
用于 8 个 crate(4 个直接使用)
52KB
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。
对于序列化为 arrow,可以使用 TryIntoArrow::try_into_arrow
将任何可迭代表序列化为 arrow2::Array
或 arrow2::Chunk
。 arrow2::Array
代表内存中的 Arrow 布局。 arrow2::Chunk
代表一个列组,可以与 arrow2
API 一起使用,例如将数据转换为 parquet 和 arrow flight RPC。
从arrow反序列化时,可以使用TryIntoCollection::try_into_collection
将arrow2::Array
表示形式反序列化为实现了FromIterator
接口的任何容器。
默认实现
以下类型提供了上述特质的默认实现:
- 数值类型
- 其他类型
- 时间类型
- 如果T实现了
ArrowField
,则为Option - 如果T实现了
ArrowField
,则为Vec - 支持大型Arrow类型
LargeBinary
,LargeString
,LargeList
,可通过type
属性支持。请参阅complex_example.rs以获取使用方法。 - 支持固定大小类型
FixedSizeBinary
,FixedSizeList
,可通过FixedSizeVec
类型覆盖支持。- 注意:不支持
FixedSizeList
的嵌套。
- 注意:不支持
枚举
枚举仍然是一个实验性功能,需要集成测试。Rust枚举数组转换为Arrow::UnionArray
。关于枚举的一些额外说明
- Rust单元变体使用
bool
数据类型表示。
i128
i128表示一个十进制数,需要指定精度和比例才能作为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>
转换为/from 箭头。
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
,
缺失的功能
- 目前尚未支持泛型、切片和引用。
这不是一个详尽的列表。如果您需要功能,请提交一个 issue。
内存
透传转换执行单次内存复制。反序列化从 arrow2 复制到目标位置。序列化从源位置复制到 arrow2。就地反序列化在理论上可行,但当前不支持。
内部
与 Serde 的相似之处
设计灵感来自 serde。 ArrowSerialize
和 ArrowDeserialize
分别是 serde 的 Serialize
和 Deserialize
的类似物。
然而,与 serde 的 trait 提供了详尽且灵活的数据模型映射不同,arrow2_convert 的 trait 提供了对 arrow2 数据结构更窄的映射。
具体来说,ArrowSerialize
trait 提供了将类型序列化为相应的 arrow2::array::MutableArray
的逻辑。 ArrowDeserialize
trait 从相应的 arrow2::array::ArrowArray
反序列化类型。
解决方案
部分实现特殊化和泛型关联类型(目前仅在 nightly 版本中可用)等功能可以极大地简化底层实现。
例如,自定义类型需要显式启用 Vec 序列化,方法是在原始类型上使用 arrow_enable_vec_for_type
宏。这是必需的,因为 Vec 在 Arrow 中是一种特殊类型,但没有实现特殊化,就没有方法来特殊情况化它。
泛型关联类型的可用性将简化大型和固定类型实现,因为可以定义一个泛型 MutableArray。理想情况下,为了代码重用,我们不需要为大型和固定大小类型重新实现 ArrowSerialize
和 ArrowDeserialize
,因为原始类型是相同的。然而,这要求 trait 函数接受一个泛型有界可变数组作为参数,而不是单个数组类型。这要求 ArrowSerialize
和 ArrowDeserialize
实现将界限作为关联类型的一部分来指定,这是没有泛型关联类型无法实现的。
因此,我们不得不牺牲代码重用并引入一点复杂性,通过提供通过占位符结构为大型和固定大小类型提供单独的 ArrowSerialize
和 ArrowDeserialize
实现来解决问题。这也要求引入 Type
关联类型到 ArrowField
,以便可以通过宏字段属性覆盖箭头类型,而不影响实际类型。
许可
根据以下任一项获得许可
- Apache许可证,版本2.0(LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可证(LICENSE-MIT 或 http://opensource.org/licenses/MIT)
由您选择。
贡献
除非您明确声明,否则根据Apache-2.0许可证定义的任何有意提交以包含在作品中的贡献,应按上述方式双许可,不附加任何额外条款或条件。
依赖关系
~7MB
~140K SLoC