#指令 #编解码器 #字节码 #解码 #操作数 # #枚举

bytecoding

用于将指令和操作数编码和解码为字节码的派生宏

2 个不稳定版本

0.1.0 2022 年 3 月 15 日
0.0.1 2022 年 3 月 8 日

#1581 in Rust 模式


3 个 crate 中使用 (通过 pk_compiler)

Apache-2.0 OR MIT

13KB
117 代码行

bytecoding

Crate Docs License

用于将指令和操作数编码和解码为字节码的派生宏。

文档

许可

许可协议为 Apache License, Version 2.0 或 MIT License,任选其一。

除非您明确声明,否则任何有意提交给此 crate 的贡献,根据 Apache-2.0 许可协议,将按照上述方式双许可,不附加任何额外条款或条件。


lib.rs:

用于将指令和操作数编码和解码为字节码的派生宏。

派生宏

枚举属性

可以用于枚举的属性。

  • type = ... (必需)

    设置用于指令代码的类型。可能的值有 u8u16u32u64

变体属性

可以用于枚举变体的属性。

  • code= ...

    设置此枚举变体的指令代码。每个变体生成的指令都需要指定一个代码。如果变体只生成一个指令,则可以使用单个数字作为 code 属性(而不是数字列表)。

变体字段属性

可以用于枚举变体字段的属性。

  • flatten= [...]

    将字段展平为每指定值的指令代码。此属性旨在用于优化某些值,对于任何未指定的值则回退到使用操作数。如果您想展平所有值,请使用 flatten_all 属性。

    请参阅下面的 示例 了解如何使用此属性。

  • flatten_all= [...]

    将枚举变体展平为每指定值的指令代码。请注意,必须指定所有可能的值。如果您只想展平某些值,请使用 flatten 属性。

    请参阅下面的 示例 了解如何使用此属性。

字段属性

可以用于结构字段或枚举变体字段的属性。

  • skip

    跳过字段的编码和解码。解码时使用std::default::Default的值。

示例

use bytecoding::Bytecode;

#[derive(Debug, PartialEq, Eq, Bytecode)]
struct Operand {
    value1: u8,
    value2: u16,
}

#[derive(Debug, PartialEq, Eq, Bytecode)]
#[bytecode(type = u8)]
enum Instruction {
    Add,
    Sub,
    Jump(u8),
    Foo(Operand),

    // This generates four instruction codes without an operand for the values 0 to 3, and one
    // instruction code with an operand for all remaining values
    Const {
        #[bytecode(flatten = [0, 1, 2, 3])]
        index: u16,
    },

    // This generates two instruction codes (without an operand):
    // - The first code is for the value `true`
    // - The second code is for the value `false`
    Bool(#[bytecode(flatten_all = [true, false])] bool),
}

let instructions = vec![
    Instruction::Sub,
    Instruction::Add,
    Instruction::Foo(Operand { value1: 20, value2: 30 }),
    Instruction::Jump(42),
    Instruction::Const { index: 0 },
    Instruction::Const { index: 4 },
    Instruction::Bool(true),
    Instruction::Bool(false),
];

// Encoding
let mut buf = Vec::new();
for instruction in &instructions {
    instruction.encode(&mut buf);
}
assert_eq!(buf, vec![
    1, // Sub
    0, // Add
    3, 20, 0, 30, // Foo(Operand { value1: 20, value2: 30 })
    2, 42, // Jump(42)
    4, // Const { index: 0 }
    8, 0, 4, // Const { index: 4 }
    9, // Bool(true)
    10, // Bool(false)
]);

// Decoding
let mut buf: &[u8] = &buf;
let mut decoded_instructions = Vec::new();
while !buf.is_empty() {
    decoded_instructions.push(Instruction::decode(&mut buf)?);
}
assert_eq!(decoded_instructions, instructions);

依赖项

~2.5MB
~51K SLoC