plotnik_bytecode/bytecode/
effects.rs

1//! Effect operations for bytecode.
2
3#[derive(Clone, Copy, PartialEq, Eq, Debug)]
4#[repr(u8)]
5pub enum EffectOpcode {
6    Node = 0,
7    Arr = 1,
8    Push = 2,
9    EndArr = 3,
10    Obj = 4,
11    EndObj = 5,
12    Set = 6,
13    Enum = 7,
14    EndEnum = 8,
15    Text = 9,
16    Clear = 10,
17    Null = 11,
18    SuppressBegin = 12,
19    SuppressEnd = 13,
20}
21
22impl EffectOpcode {
23    fn from_u8(v: u8) -> Self {
24        match v {
25            0 => Self::Node,
26            1 => Self::Arr,
27            2 => Self::Push,
28            3 => Self::EndArr,
29            4 => Self::Obj,
30            5 => Self::EndObj,
31            6 => Self::Set,
32            7 => Self::Enum,
33            8 => Self::EndEnum,
34            9 => Self::Text,
35            10 => Self::Clear,
36            11 => Self::Null,
37            12 => Self::SuppressBegin,
38            13 => Self::SuppressEnd,
39            _ => panic!("invalid effect opcode: {v}"),
40        }
41    }
42}
43
44#[derive(Clone, Copy, PartialEq, Eq, Debug)]
45pub struct EffectOp {
46    pub opcode: EffectOpcode,
47    pub payload: usize,
48}
49
50impl EffectOp {
51    /// Create a new effect operation.
52    pub fn new(opcode: EffectOpcode, payload: usize) -> Self {
53        Self { opcode, payload }
54    }
55
56    pub fn from_bytes(bytes: [u8; 2]) -> Self {
57        let raw = u16::from_le_bytes(bytes);
58        let opcode = EffectOpcode::from_u8((raw >> 10) as u8);
59        let payload = (raw & 0x3FF) as usize;
60        Self { opcode, payload }
61    }
62
63    pub fn to_bytes(self) -> [u8; 2] {
64        assert!(
65            self.payload <= 0x3FF,
66            "effect payload exceeds 10-bit limit: {}",
67            self.payload
68        );
69        let raw = ((self.opcode as u16) << 10) | ((self.payload as u16) & 0x3FF);
70        raw.to_le_bytes()
71    }
72}