truthlinked_axiom/
bytecode.rs1use crate::error::AxiomError;
7use alloc::vec::Vec;
8
9pub const MAGIC: [u8; 4] = [0x41, 0x58, 0x49, 0x4F];
11pub const VERSION: u8 = 2;
12
13pub const MAX_CONST_POOL_ENTRIES: usize = 65_535;
15pub const MAX_CONST_ENTRY_BYTES: usize = 65_536; pub const MAX_CODE_BYTES: usize = 1_048_576; pub struct CellBytecode {
20 pub const_pool: Vec<Vec<u8>>,
22 pub code: Vec<u8>,
24}
25
26impl CellBytecode {
27 pub fn decode(raw: &[u8]) -> Result<Self, AxiomError> {
29 let mut pos = 0;
30
31 if raw.len() < 6 {
33 return Err(AxiomError::InvalidMagic);
34 }
35 if &raw[0..4] != &MAGIC {
36 return Err(AxiomError::InvalidMagic);
37 }
38 pos += 4;
39
40 if raw[pos] != VERSION {
42 return Err(AxiomError::InvalidBytecode);
43 }
44 pos += 1;
45
46 if raw[pos] != 0 {
48 return Err(AxiomError::InvalidBytecode);
49 }
50 pos += 1;
51
52 if pos + 2 > raw.len() {
54 return Err(AxiomError::InvalidBytecode);
55 }
56 let pool_count = u16::from_le_bytes([raw[pos], raw[pos + 1]]) as usize;
57 pos += 2;
58 if pool_count > MAX_CONST_POOL_ENTRIES {
59 return Err(AxiomError::InvalidBytecode);
60 }
61
62 let mut const_pool = Vec::with_capacity(pool_count);
64 for _ in 0..pool_count {
65 if pos + 4 > raw.len() {
66 return Err(AxiomError::InvalidBytecode);
67 }
68 let entry_len =
69 u32::from_le_bytes([raw[pos], raw[pos + 1], raw[pos + 2], raw[pos + 3]]) as usize;
70 pos += 4;
71 if entry_len > MAX_CONST_ENTRY_BYTES {
72 return Err(AxiomError::InvalidBytecode);
73 }
74 if pos + entry_len > raw.len() {
75 return Err(AxiomError::InvalidBytecode);
76 }
77 const_pool.push(raw[pos..pos + entry_len].to_vec());
78 pos += entry_len;
79 }
80
81 if pos + 4 > raw.len() {
83 return Err(AxiomError::InvalidBytecode);
84 }
85 let code_len =
86 u32::from_le_bytes([raw[pos], raw[pos + 1], raw[pos + 2], raw[pos + 3]]) as usize;
87 pos += 4;
88 if code_len > MAX_CODE_BYTES {
89 return Err(AxiomError::InvalidBytecode);
90 }
91 if pos + code_len > raw.len() {
92 return Err(AxiomError::InvalidBytecode);
93 }
94
95 let code = raw[pos..pos + code_len].to_vec();
96
97 Ok(Self { const_pool, code })
98 }
99
100 pub fn encode(&self) -> Vec<u8> {
102 let mut out = Vec::new();
103 out.extend_from_slice(&MAGIC);
104 out.push(VERSION);
105 out.push(0); out.extend_from_slice(&(self.const_pool.len() as u16).to_le_bytes());
107 for entry in &self.const_pool {
108 out.extend_from_slice(&(entry.len() as u32).to_le_bytes());
109 out.extend_from_slice(entry);
110 }
111 out.extend_from_slice(&(self.code.len() as u32).to_le_bytes());
112 out.extend_from_slice(&self.code);
113 out
114 }
115
116 pub fn is_axiom(raw: &[u8]) -> bool {
118 raw.len() >= 4 && &raw[0..4] == &MAGIC
119 }
120}