4 个版本 (重大变更)
0.5.0 | 2023年7月22日 |
---|---|
0.4.0 | 2023年7月14日 |
0.3.0 | 2023年7月14日 |
0.2.0 | 2023年7月5日 |
0.1.0 |
|
10 在 #monero
每月23次 下载
35KB
709 代码行
Epee 编码
是什么
此包实现了 Monero 中使用的 epee 二进制格式;与其他包不同,此包不使用 serde,这并不是因为 serde 很差,而是为了减少维护者的负担,因为这个库中的所有特质都是针对 epee 的,而不是通用的。
特性
默认
默认功能启用了 derive 功能。
派生
此功能启用了 derive 宏,用于创建 epee 对象,例如
use epee_encoding::EpeeObject;
#[derive(EpeeObject)]
struct Test {
val: u8
}
用法
无 derive 的示例
use epee_encoding::{EpeeObject, EpeeObjectBuilder, read_epee_value, write_field, to_bytes, from_bytes};
use epee_encoding::io::{Read, Write};
pub struct Test {
val: u64
}
#[derive(Default)]
pub struct __TestEpeeBuilder {
val: Option<u64>,
}
impl EpeeObjectBuilder<Test> for __TestEpeeBuilder {
fn add_field<R: Read>(&mut self, name: &str, r: &mut R) -> epee_encoding::error::Result<bool> {
match name {
"val" => {self.val = Some(read_epee_value(r)?);}
_ => return Ok(false),
}
Ok(true)
}
fn finish(self) -> epee_encoding::error::Result<Test> {
Ok(
Test {
val: self.val.ok_or_else(|| epee_encoding::error::Error::Format("Required field was not found!"))?
}
)
}
}
impl EpeeObject for Test {
type Builder = __TestEpeeBuilder;
fn number_of_fields(&self) -> u64 {
1
}
fn write_fields<W: Write>(&self, w: &mut W) -> epee_encoding::error::Result<()> {
// write the fields
write_field(&self.val, "val", w)
}
}
let data = [1, 17, 1, 1, 1, 1, 2, 1, 1, 4, 3, 118, 97, 108, 5, 4, 0, 0, 0, 0, 0, 0, 0]; // the data to decode;
let val: Test = from_bytes(&data).unwrap();
let data = to_bytes(&val).unwrap();
带 derive 的示例
use epee_encoding::{EpeeObject, from_bytes, to_bytes};
#[derive(EpeeObject)]
struct Test {
val: u64
}
let data = [1, 17, 1, 1, 1, 1, 2, 1, 1, 4, 3, 118, 97, 108, 5, 4, 0, 0, 0, 0, 0, 0, 0]; // the data to decode;
let val: Test = from_bytes(&data).unwrap();
let data = to_bytes(&val).unwrap();
派生属性
EpeeObject
派生宏有几个属性,对应于特定的 C/C++ 宏字段。
epee_flatten
这相当于 KV_SERIALIZE_PARENT
,它将对象中的所有字段扁平化到父对象中。
在 C/C++ 中是这样的
struct request_t: public rpc_request_base
{
uint8_t major_version;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_PARENT(rpc_request_base)
KV_SERIALIZE(major_version)
END_KV_SERIALIZE_MAP()
};
在 Rust 中看起来是这样的
#[derive(EpeeObject)]
struct RequestT {
#[epee_flatten]
rpc_request_base: RequestBase,
major_version: u8,
}
epee_alt_name
这允许您在编码时重新命名字段,尽管这与 C/C++ 中的特定宏无关,但这被包含在内,因为 Monero 有一些奇特的名称。
示例
#[derive(EpeeObject)]
pub struct HandshakeR {
#[epee_alt_name("node_data")]
pub node_daa: BasicNodeData,
}
epee_default
这相当于 KV_SERIALIZE_OPT
,允许您指定字段的默认值,当指定默认值时,如果数据中不包含该值,则使用该值,如果值是默认值,则不会编码该字段。
在 C/C++ 中是这样的
struct request_t
{
std::vector<blobdata> txs;
std::string _; // padding
bool dandelionpp_fluff; //zero initialization defaults to stem mode
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(txs)
KV_SERIALIZE(_)
KV_SERIALIZE_OPT(dandelionpp_fluff, true) // backwards compatible mode is fluff
END_KV_SERIALIZE_MAP()
};
在 Rust 中看起来是这样的
#[derive(EpeeObject)]
struct RequestT {
txs: Vec<Vec<u8>>,
#[epee_alt_name("_")]
padding: Vec<u8>,
#[epee_default(true)]
dandelionpp_fluff: bool,
}
无 std
此包是无 std 的。
选项
要有一个可选字段,您应使用 Option
包装类型,并使用 epee_default
属性。因此,它将看起来像这样
#[derive(EpeeObject)]
struct T {
#[epee_default(None)]
val: Option<u8>,
}
依赖项
~285–740KB
~17K SLoC