1个不稳定版本

0.3.23 2022年9月6日

#1129编码


pink-web3 中使用

MIT/Apache

135KB
2.5K SLoC

pink-erased-serde

移除浮点运算以在 ink! 中运行

擦除Serde

github crates.io docs.rs build status

该软件包提供了Serde的SerializeSerializerDeserializer特性的类型擦除版本,可以作为特性对象使用。

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

应将此库视为以对象安全方式与Serde API交互的低级构建块。大多数用例将需要由typetag提供的高级功能,该库内部使用此软件包。

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

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

序列化

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"]);
}

工作原理

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

在erased-serde中,由于以下三个原因,事情比示例复杂,但原理相同。

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

未来,Rust 编译器可能会自动将这种技术应用于任何根据当前规则尚未对象安全的特性。


许可协议

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

依赖项

约110-355KB