4个版本 (重大变更)
0.4.0 | 2023年7月22日 |
---|---|
0.3.0 | 2023年7月14日 |
0.2.0 | 2023年7月5日 |
0.1.0 | 2023年7月5日 |
#26 in #monero
每月37次下载
用于 epee-encoding
18KB
268 行
Epee编码
是什么
此crate实现了Monero中发现的epee二进制格式;与其它crate不同,此crate不使用serde,这不是因为serde不好,而是为了减轻维护者的负担,因为此库中的所有特性都是针对epee而不是通用目的。
功能
默认
默认功能启用了推导功能。
推导
此功能启用了用于创建epee对象的推导宏,例如
use epee_encoding::EpeeObject;
#[derive(EpeeObject)]
struct Test {
val: u8
}
使用方法
无推导的示例
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();
有推导的示例
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
此crate是无std的。
选项
要有一个可选字段,你应该用Option
包裹类型,并使用epee_default
属性。所以它看起来会是这样的
#[derive(EpeeObject)]
struct T {
#[epee_default(None)]
val: Option<u8>,
}
依赖项
~260–710KB
~17K SLoC