#epee #monero #binary-format #no-std

无std epee-encoding-derive

Epee二进制格式推导库

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

MIT 许可证

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