1个不稳定版本
0.3.23 | 2022年9月6日 |
---|
#1129 在 编码
在 pink-web3 中使用
135KB
2.5K SLoC
pink-erased-serde
移除浮点运算以在 ink!
中运行
擦除Serde
该软件包提供了Serde的Serialize
、Serializer
和Deserializer
特性的类型擦除版本,可以作为特性对象使用。
由于Rust的"对象安全"规则,常规的Serde Serialize
、Serializer
和Deserializer
特性不能用作类似于&dyn Serialize
的特性对象,或者boxed特性对象如Box<dyn Serialize>
,因为所有三个特性都包含泛型方法,这些方法不能转换为特性对象。
应将此库视为以对象安全方式与Serde API交互的低级构建块。大多数用例将需要由typetag
提供的高级功能,该库内部使用此软件包。
该库中的特性可以与任何现有的Serde Serialize
和Deserialize
类型以及任何现有的Serde Serializer
和Deserializer
格式无缝工作。
[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::Ok
和Visitor::Value
的特性 -- 通过小心地在指针后短期存储东西。 - 我们需要支持那些返回类型具有泛型类型但没有任何参数类型的特性方法,例如
SeqAccess::next_element
-- 这可以被转换成回调风格,其中返回值被传递到一个泛型参数。
未来,Rust 编译器可能会自动将这种技术应用于任何根据当前规则尚未对象安全的特性。
许可协议
根据您的选择,在以下任一协议下获得许可:Apache License, Version 2.0 或 MIT 许可证。除非您明确声明,否则根据 Apache-2.0 许可证定义的任何有意提交以包含在此软件包中的贡献,均将按照上述方式双重许可,不附加任何其他条款或条件。
依赖项
约110-355KB