#pod #data #encode #nue #binary-data #data-encoding #endian

nightly nue-macros

POD 和二进制数据编码 I/O 宏

7 个不稳定版本 (3 个重大更改)

使用旧的 Rust 2015

0.3.0 2015年8月9日
0.2.0 2015年7月30日
0.1.0 2015年7月22日
0.0.5 2015年7月21日

#4 in #nue

MIT 许可证

7KB

#[derive(..)] 属性用于 POD 和二进制可编码类型。

属性

#[packed]

应用 #[repr(Packed)] 属性,同时确保所有成员都可以安全地进行非对齐访问。

#![feature(plugin, custom_derive, custom_attribute)]
#![plugin(nue_macros)]

extern crate nue;
use nue::{Pod, Aligned, Un};

#[packed]
struct Data(u8, Un<u32>);

let data = Data(5, 5.unaligned());
assert_eq!(data.0, 5u8);
assert_eq!(u32::aligned(data.1), 5u32);

#[derive(Pod)]

将结构体标记为 pod::Pod。它只能包含其他 Pod 成员,并且类型必须是打包的。

#[derive(PodPacked)]

将结构体标记为 pod::Pod,并应用 #[packed] 属性到类型上。

示例

#![feature(plugin, custom_derive, custom_attribute)]
#![plugin(nue_macros)]

extern crate pod;
extern crate nue;
use pod::Pod;

#[derive(Pod)]
#[packed]
struct Data(u8);

assert_eq!(Data(5).as_slice(), &[5]);

#[derive(NueEncode,NueDecode)]

在结构体上实现 nue::Encodenue::Decode。所有字段也必须实现 Encode / Decode(或通过 nue 属性跳过)。

#[nue(...)]#[nue_enc(...)]#[nue_dec(...)]

每个字段都可能使用nue属性提供额外的编码选项。它们将影响父类型的编码或解码方式。这些属性接受任意的Rust表达式。可以通过self访问成员变量。

nue_enc仅适用于编码,nue_dec适用于解码,而nue适用于两者。尽管属性的顺序通常不重要,但alignskip的交互方式取决于哪个先定义。

assert

在继续操作之前,断言某些属性为真。

use nue::Decode;

#[derive(NueDecode)]
struct Data(
    #[nue(assert = "self.0 == 0")]
	u8
);

let data = &[1];
assert!(&Data::decode_slice(data).is_err());

let data = &[0];
assert!(&Data::decode_slice(data).is_ok());

align

将字段对齐到给定倍数的偏移量。

use nue::Encode;

#[derive(NueEncode)]
struct Data(
	u8,
	#[nue(align = "self.0 as u64 + 1")]
	&'static str
);

let data = Data(2, "hi");
let cmp = &[2, 0, 0, b'h', b'i'];
assert_eq!(&data.encode_vec().unwrap(), cmp);

skip

在编码/解码值之前丢弃指定数量的字节。

use nue::Encode;

#[derive(NueEncode)]
struct Data(
	u8,
	#[nue(skip = "1")]
	&'static str
);

let data = Data(2, "hi");
let cmp = &[2, 0, b'h', b'i'];
assert_eq!(&data.encode_vec().unwrap(), cmp);

cond

有条件地编码或解码字段。如果条件不满足,将使用Default::default()。使用false是静态保证忽略该字段。

use nue::Encode;

#[derive(NueEncode)]
struct Data<'a>(
	u8,
	#[nue(cond = "false")]
	&'a () // Note that this type does not implement `Encode`
);

let u = ();
let data = Data(2, &u);
let cmp = &[2];
assert_eq!(&data.encode_vec().unwrap(), cmp);

default

确定在cond评估为假时使用的默认值。

use nue::Decode;

#[derive(NueDecode, PartialEq, Debug)]
struct Data(
	u8,
	#[nue(cond = "self.0 == 1", default = "5")]
	u8
);

let data = &[2];
assert_eq!(&Data::decode_slice(data).unwrap(), &Data(2, 5));

let data = &[1, 2];
assert_eq!(&Data::decode_slice(data).unwrap(), &Data(1, 2));

limit

限制编码过程中可以消耗或写入的字节数量。

use nue::Decode;

#[derive(NueDecode)]
struct Data(
	#[nue(limit = "4")]
	String,
);

let data = b"hello";
assert_eq!(&Data::decode_slice(data).unwrap().0, "hell");

consume

当设置时,即使类型没有编码或解码整个字节区域,也会使用所有的limit

use nue::Decode;
use std::ffi::CString;

#[derive(NueDecode)]
struct Data(
	#[nue(limit = "8", consume = "true")]
	CString,
	u8
);

let data = b"hello\0\0\0\x05";
let data = Data::decode_slice(data).unwrap();
assert_eq!(data.0.to_bytes(), b"hello");
assert_eq!(data.1, 5);

依赖