12 次重大发布
0.13.1 | 2024年6月7日 |
---|---|
0.12.0 | 2024年4月29日 |
0.11.1 | 2024年2月16日 |
0.10.0 | 2023年11月10日 |
0.3.0 | 2022年7月28日 |
#14 in #parity
159,326 每月下载量
在 106 个 crate (10 directly) 中使用
180KB
3K SLoC
scale-decode
此 crate 通过使用 TypeResolver
(其中一个为 scale_info::PortableRegistry
)简化了将 SCALE 编码的字节解码为自定义数据结构的操作。通过使用此类型信息来指导解码(而不是仅仅根据目标类型的形状尝试解码字节),可以更灵活地解码数据并将其映射到某些目标类型。
用于解码类型的主要特质是 Visitor
特质(以下为示例)。通过实现此特质,您可以描述如何将 SCALE 解码的值映射到您选择的某些自定义类型(无论是动态形状的类型还是您想要解码到的一些静态类型)。标准库中许多现有的 Rust 类型都有 Visitor
特质的实现。
还存在一个 IntoVisitor
特质,它被许多现有的 rust 类型实现,并将给定类型映射到能够解码到该类型的某个访问者实现。
最后,一个包装特质 DecodeAsType
,为所有具有 IntoVisitor
实现的类型自动实现,并且其访问者错误可以被转换为标准 crate::Error
。
对于自定义的结构体和枚举,可以使用 DecodeAsType
derive 宏来自动生成 DecodeAsType
实现。
以下是一个实现 Visitor
以将字节解码为自定义 Value
类型的示例
use std::marker::PhantomData;
use scale_decode::TypeResolver;
use scale_decode::visitor::{
self,
types::{Array, BitSequence, Composite, Sequence, Str, Tuple, Variant},
TypeIdFor,
};
// A custom type we'd like to decode into:
#[derive(Debug, PartialEq)]
enum Value {
Bool(bool),
Char(char),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
U128(u128),
U256([u8; 32]),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
I128(i128),
I256([u8; 32]),
Sequence(Vec<Value>),
Composite(Vec<(String, Value)>),
Tuple(Vec<Value>),
Str(String),
Array(Vec<Value>),
Variant(String, Vec<(String, Value)>),
BitSequence(scale_bits::Bits),
}
// Implement the `Visitor` trait to define how to go from SCALE
// values into this type. Here, we are choosing to be generic over
// how types are resolved, which is a good default choice when creating
// a visitor unless you rely on a specific type resolver/ID type.
struct ValueVisitor<R>(PhantomData<R>);
impl<R> ValueVisitor<R> {
fn new() -> Self {
Self(PhantomData)
}
}
impl<R: TypeResolver> visitor::Visitor for ValueVisitor<R> {
type Value<'scale, 'resolver> = Value;
type Error = visitor::DecodeError;
type TypeResolver = R;
fn visit_bool<'scale, 'resolver>(
self,
value: bool,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::Bool(value))
}
fn visit_char<'scale, 'resolver>(
self,
value: char,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::Char(value))
}
fn visit_u8<'scale, 'resolver>(
self,
value: u8,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::U8(value))
}
fn visit_u16<'scale, 'resolver>(
self,
value: u16,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::U16(value))
}
fn visit_u32<'scale, 'resolver>(
self,
value: u32,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::U32(value))
}
fn visit_u64<'scale, 'resolver>(
self,
value: u64,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::U64(value))
}
fn visit_u128<'scale, 'resolver>(
self,
value: u128,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::U128(value))
}
fn visit_u256<'scale, 'resolver>(
self,
value: &'scale [u8; 32],
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::U256(*value))
}
fn visit_i8<'scale, 'resolver>(
self,
value: i8,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::I8(value))
}
fn visit_i16<'scale, 'resolver>(
self,
value: i16,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::I16(value))
}
fn visit_i32<'scale, 'resolver>(
self,
value: i32,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::I32(value))
}
fn visit_i64<'scale, 'resolver>(
self,
value: i64,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::I64(value))
}
fn visit_i128<'scale, 'resolver>(
self,
value: i128,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::I128(value))
}
fn visit_i256<'scale, 'resolver>(
self,
value: &'scale [u8; 32],
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::I256(*value))
}
fn visit_sequence<'scale, 'resolver>(
self,
value: &mut Sequence<'scale, 'resolver, Self::TypeResolver>,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
let mut vals = vec![];
while let Some(val) = value.decode_item(ValueVisitor::new()) {
let val = val?;
vals.push(val);
}
Ok(Value::Sequence(vals))
}
fn visit_composite<'scale, 'resolver>(
self,
value: &mut Composite<'scale, 'resolver, Self::TypeResolver>,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
let mut vals = vec![];
for item in value.by_ref() {
let item = item?;
let val = item.decode_with_visitor(ValueVisitor::new())?;
let name = item.name().unwrap_or("").to_owned();
vals.push((name, val));
}
Ok(Value::Composite(vals))
}
fn visit_tuple<'scale, 'resolver>(
self,
value: &mut Tuple<'scale, 'resolver, Self::TypeResolver>,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
let mut vals = vec![];
while let Some(val) = value.decode_item(ValueVisitor::new()) {
let val = val?;
vals.push(val);
}
Ok(Value::Tuple(vals))
}
fn visit_str<'scale, 'resolver>(
self,
value: &mut Str<'scale>,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
Ok(Value::Str(value.as_str()?.to_owned()))
}
fn visit_variant<'scale, 'resolver>(
self,
value: &mut Variant<'scale, 'resolver, Self::TypeResolver>,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
let mut vals = vec![];
let fields = value.fields();
for item in fields.by_ref() {
let item = item?;
let val = item.decode_with_visitor(ValueVisitor::new())?;
let name = item.name().unwrap_or("").to_owned();
vals.push((name, val));
}
Ok(Value::Variant(value.name().to_owned(), vals))
}
fn visit_array<'scale, 'resolver>(
self,
value: &mut Array<'scale, 'resolver, Self::TypeResolver>,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
let mut vals = vec![];
while let Some(val) = value.decode_item(ValueVisitor::new()) {
let val = val?;
vals.push(val);
}
Ok(Value::Array(vals))
}
fn visit_bitsequence<'scale, 'resolver>(
self,
value: &mut BitSequence<'scale>,
_type_id: &TypeIdFor<Self>,
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
let bools: Result<scale_bits::Bits, _> = value.decode()?.collect();
Ok(Value::BitSequence(bools?))
}
}
然后可以将其传递给解码函数,如下所示
let value: Value = scale_decode::visitor::decode_with_visitor(scale_bytes, &type_id, &types, ValueVisitor::new())?;
其中 scale_bytes
是要解码的字节,type_id
是存储在 types
注册表中的类型,您希望将其解码成字节,而 types
是一个包含有关使用中各种类型信息的 scale_type_resolver::TypeResolver
(其具体实现为 scale_info::PortableRegistry
)。
如果我们随后编写一个类似于下面的 IntoVisitor
实现
impl scale_decode::IntoVisitor for Value {
type AnyVisitor<R: TypeResolver> = ValueVisitor<R>;
fn into_visitor<R: TypeResolver>() -> Self::AnyVisitor<R> {
ValueVisitor::new()
}
}
然后我们也可以通过自动的 DecodeAsType
实现如下解码
use scale_decode::DecodeAsType;
let value = Value::decode_as_type(scale_bytes, type_id, types)?;
有了 IntoVisitor
实现,您还可以受益于以相同的方式解码类似 Vec<Value>
、(Value, bool)
、Arc<Value>
等内容。
依赖关系
~3.5MB
~75K SLoC