2个不稳定版本

0.1.0 2024年3月20日
0.0.0-alpha.12024年3月19日

#2916 in 魔法豆

Download history 158/week @ 2024-04-05 167/week @ 2024-04-12 106/week @ 2024-04-19 79/week @ 2024-04-26 33/week @ 2024-05-03 16/week @ 2024-05-10 38/week @ 2024-05-17 66/week @ 2024-05-24 128/week @ 2024-05-31 171/week @ 2024-06-07 48/week @ 2024-06-14 34/week @ 2024-06-21 17/week @ 2024-06-28 23/week @ 2024-07-05 49/week @ 2024-07-12 59/week @ 2024-07-19

157 每月下载量
用于 3 crates

Apache-2.0

89KB
2K SLoC

将Rust值从VAA有效负载线格式进行序列化和反序列化。

截至本文写作时(2022年6月),VAA有效负载线格式没有合适的规范,因此此实现主要是从现有消息逆向工程得出的。虽然本文件其余部分讨论了各种类型在线上的表示,但这应被视为对本crate中实现方式的解释,而不是官方文档。在由本crate产生的负载序列化与wormhole合约使用的序列化不同的情况下,实际合约使用的序列化被视为规范序列化。

除非您想与现有的虫洞VAA有效负载进行交互,否则这个库可能不是您要找的。如果您只是使用虫洞桥来发送自己的有效负载,那么使用具有自动生成代码的模式(如protobufs或flatbuffers)可能是一个更好的选择。

线格式

VAA有效负载的线格式不是一个自描述格式(与json和toml不同)。因此,在反序列化字节流之前,必须知道需要生成的类型。

当前线格式支持以下原始类型

bool

编码为一个字节,其中值为0表示false,值为1表示true。所有其他值都是无效的。

整数

i8i16i32i64i128u8u16u32u64u128都是支持的,并作为全宽大端整数进行编码,即i16是2个字节,u64是8个字节,等等。

char

编码为大端u32,此外还必须是一个有效的Unicode Scalar Value

序列

可变长度异构序列被编码为一个字节长度,然后是序列中每个元素序列化形式的连接。请注意,这意味着序列不能有超过255个元素。此外,在序列化过程中,长度必须提前知道。

字节数组 - &[u8]Vec<u8>Cow<'a, [u8]>

字节数组被视为可变长度序列的子集,并以一个字节长度后跟相应数量的数据字节进行编码。同样,由于字节数组的长度必须适应一个字节,因此它不能超过255个字节。

&strString

字符串类型与&[u8]以相同的方式进行编码,额外的限制是字节数组必须是有效的UTF-8。

元组

元组是异构序列,其中长度是固定的且提前知道。在这种情况下,长度不会在线上编码,元组中每个元素的序列化会连接起来生成最终值。

Option<T>

线格式不支持可选值。在尝试序列化一个Option::None时,选项总是反序列化为Some(T),这会导致错误。

Structs

结构体以与元组相同的方式表示,结构体的序列化格式与具有相同字段顺序的元组的序列化格式相同。唯一的例外是没有字段的单元结构体(unit structs),它在序列化格式中根本不表示。

[T;N]

数组被视为具有相同字段的元组,并且具有相同的序列化格式。

枚举

枚举被编码为一个表示变体的单字节,随后是变体的序列化。

  • 单元变体 - 不编码任何额外数据。
  • 新类型变体 - 使用内部类型的序列化进行编码。
  • 元组变体 - 以常规元组的形式编码。
  • 结构体变体 - 以常规结构体的形式编码。

由于枚举变体是编码为一个单字节,而不是变体的名称本身,因此需要在每个枚举变体上使用 #[serde(rename = "<value>")] 来确保它们可以正确地序列化和反序列化。

示例

use std::borrow::Cow;

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
enum TestEnum<'a> {
    #[serde(rename = "19")]
    Unit,
    #[serde(rename = "235")]
    NewType(u64),
    #[serde(rename = "179")]
    Tuple(u32, u64, Vec<u16>),
    #[serde(rename = "97")]
    Struct {
        #[serde(borrow, with = "serde_bytes")]
        data: Cow<'a, [u8]>,
        footer: u32,
    },
}

assert!(matches!(serde_wormhole::from_slice(&[19]).unwrap(), TestEnum::Unit));

映射类型

映射类型被编码为一个 (key, value) 元组的序列。对于 Vec<(K, V)> 的编码与 BTreeMap<K, V> 的编码相同。在序列化过程中,必须事先知道映射中的元素数量。与其他序列一样,映射中的最大元素数量为255。

依赖关系

~0.7–1.3MB
~29K SLoC