#traits #serde #serializer-deserializer #erasure #erased #generic #object

不依赖std erased-serde

类型擦除的Serialize和Serializer特性

44次发布

0.4.5 2024年5月14日
0.4.4 2024年3月10日
0.4.3 2024年2月19日
0.4.1 2023年12月14日
0.1.3 2016年9月26日

#15 in 编码

Download history 387852/week @ 2024-05-02 396894/week @ 2024-05-09 417256/week @ 2024-05-16 423514/week @ 2024-05-23 448197/week @ 2024-05-30 439333/week @ 2024-06-06 435675/week @ 2024-06-13 408626/week @ 2024-06-20 460261/week @ 2024-06-27 415023/week @ 2024-07-04 453602/week @ 2024-07-11 456118/week @ 2024-07-18 478456/week @ 2024-07-25 461318/week @ 2024-08-01 531378/week @ 2024-08-08 417883/week @ 2024-08-15

1,974,436 每月下载量
用于 2,510 个crate(直接使用202个)

MIT/Apache

145KB
3K SLoC

Erased Serde

github crates.io docs.rs build status

这个crate提供了Serde的SerializeSerializerDeserializer特性的类型擦除版本,可以用作特性对象

由于Rust的"对象安全"规则,常规的Serde SerializeSerializerDeserializer特性不能用作特性对象如&dyn Serialize或boxed特性对象如Box<dyn Serialize>,因为这三个特性都包含泛型方法,无法成为特性对象。

这个库应该被视为与Serde API进行对象安全交互的低级构建块。大多数用例将需要更高级的功能,例如typetag提供,它内部使用这个crate。

这个crate中的特性可以与任何现有的Serde SerializeDeserialize类型以及任何现有的Serde SerializerDeserializer格式无缝工作。

[dependencies]
serde = "1.0"
erased-serde = "0.4"

序列化

use erased_serde::{Serialize, Serializer};
use std::collections::BTreeMap as Map;
use std::io;

fn main() {
    // Construct some serializers.
    let json = &mut serde_json::Serializer::new(io::stdout());
    let cbor = &mut serde_cbor::Serializer::new(serde_cbor::ser::IoWrite::new(io::stdout()));

    // The values in this map are boxed trait objects. Ordinarily this would not
    // be possible with serde::Serializer because of object safety, but type
    // erasure makes it possible with erased_serde::Serializer.
    let mut formats: Map<&str, Box<dyn Serializer>> = Map::new();
    formats.insert("json", Box::new(<dyn Serializer>::erase(json)));
    formats.insert("cbor", Box::new(<dyn Serializer>::erase(cbor)));

    // These are boxed trait objects as well. Same thing here - type erasure
    // makes this possible.
    let mut values: Map<&str, Box<dyn Serialize>> = Map::new();
    values.insert("vec", Box::new(vec!["a", "b"]));
    values.insert("int", Box::new(65536));

    // Pick a Serializer out of the formats map.
    let format = formats.get_mut("json").unwrap();

    // Pick a Serialize out of the values map.
    let value = values.get("vec").unwrap();

    // This line prints `["a","b"]` to stdout.
    value.erased_serialize(format).unwrap();
}

反序列化

use erased_serde::Deserializer;
use std::collections::BTreeMap as Map;

fn main() {
    static JSON: &[u8] = br#"{"A": 65, "B": 66}"#;
    static CBOR: &[u8] = &[162, 97, 65, 24, 65, 97, 66, 24, 66];

    // Construct some deserializers.
    let json = &mut serde_json::Deserializer::from_slice(JSON);
    let cbor = &mut serde_cbor::Deserializer::from_slice(CBOR);

    // The values in this map are boxed trait objects, which is not possible
    // with the normal serde::Deserializer because of object safety.
    let mut formats: Map<&str, Box<dyn Deserializer>> = Map::new();
    formats.insert("json", Box::new(<dyn Deserializer>::erase(json)));
    formats.insert("cbor", Box::new(<dyn Deserializer>::erase(cbor)));

    // Pick a Deserializer out of the formats map.
    let format = formats.get_mut("json").unwrap();

    let data: Map<String, usize> = erased_serde::deserialize(format).unwrap();

    println!("{}", data["A"] + data["B"]);
}

工作原理

这个crate基于构建具有泛型方法的特性(如所有Serde的特性)的特性对象的一般技术。以下示例代码演示了将这种技术应用于具有单个泛型方法的简化情况。 这是一个示例代码在playground中尝试

在erased-serde中,事情比示例复杂一些,但基本思想是相同的。

  • 我们需要处理以值传递的方式接收 self 的特质方法——实际上是通过实现 Option<T> 的对象安全特质,其中 T 实现了真正的特质。
  • 我们需要处理具有关联类型如 Serializer::OkVisitor::Value 的特质——通过小心地将事物短期存储在指针后面。
  • 我们需要支持具有泛型返回类型但没有任何参数类型的特质方法,如 SeqAccess::next_element ——这可以被翻转成一个回调风格,其中返回值被传递到一个泛型参数。

将来,Rust 编译器可能能够自动将这项技术应用于任何按照当前规则尚未对象安全的任何特质。


许可证

根据您的选择,在 Apache License, Version 2.0MIT 许可证 下许可。
除非您明确表示,否则根据 Apache-2.0 许可证定义,您提交给此软件包的任何有意贡献,将按照上述方式双重许可,不附加任何其他条款或条件。

依赖关系

~120–360KB