@@ -7,6 +7,7 @@ use std::io;
77use std:: ops:: Deref ;
88use std:: path:: Path ;
99
10+ use super :: aligned_vec:: AlignedVec ;
1011use super :: header:: { Header , SectionOffsets } ;
1112use super :: ids:: { StringId , TypeId } ;
1213use super :: instructions:: { Call , Match , Opcode , Return , Trampoline } ;
@@ -31,28 +32,69 @@ fn read_u32_le(bytes: &[u8], offset: usize) -> u32 {
3132 ] )
3233}
3334
34- /// Storage for bytecode bytes.
35- #[ derive( Debug ) ]
36- pub struct ByteStorage ( Vec < u8 > ) ;
35+ /// Storage for bytecode bytes with guaranteed 64-byte alignment.
36+ ///
37+ /// All bytecode must be 64-byte aligned for DFA deserialization and cache
38+ /// efficiency. This enum ensures alignment through two paths:
39+ /// - `Static`: Pre-aligned via `include_query_aligned!` macro
40+ /// - `Aligned`: Allocated with 64-byte alignment via `AlignedVec`
41+ pub enum ByteStorage {
42+ /// Static bytes from `include_query_aligned!` (zero-copy, pre-aligned).
43+ Static ( & ' static [ u8 ] ) ,
44+ /// Owned bytes with guaranteed 64-byte alignment.
45+ Aligned ( AlignedVec ) ,
46+ }
3747
3848impl Deref for ByteStorage {
3949 type Target = [ u8 ] ;
4050
4151 fn deref ( & self ) -> & Self :: Target {
42- & self . 0
52+ match self {
53+ ByteStorage :: Static ( s) => s,
54+ ByteStorage :: Aligned ( v) => v,
55+ }
56+ }
57+ }
58+
59+ impl std:: fmt:: Debug for ByteStorage {
60+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
61+ match self {
62+ ByteStorage :: Static ( s) => f. debug_tuple ( "Static" ) . field ( & s. len ( ) ) . finish ( ) ,
63+ ByteStorage :: Aligned ( v) => f. debug_tuple ( "Aligned" ) . field ( & v. len ( ) ) . finish ( ) ,
64+ }
4365 }
4466}
4567
4668impl ByteStorage {
47- /// Create from owned bytes.
48- pub fn from_vec ( bytes : Vec < u8 > ) -> Self {
49- Self ( bytes)
69+ /// Create from static bytes (zero-copy).
70+ ///
71+ /// The bytes must be 64-byte aligned. Use `include_query_aligned!` macro.
72+ ///
73+ /// # Panics
74+ /// Panics if bytes are not 64-byte aligned.
75+ pub fn from_static ( bytes : & ' static [ u8 ] ) -> Self {
76+ assert ! (
77+ ( bytes. as_ptr( ) as usize ) . is_multiple_of( 64 ) ,
78+ "static bytes must be 64-byte aligned; use include_query_aligned! macro"
79+ ) ;
80+ Self :: Static ( bytes)
81+ }
82+
83+ /// Create from an aligned vector (from compiler or file read).
84+ pub fn from_aligned ( vec : AlignedVec ) -> Self {
85+ Self :: Aligned ( vec)
86+ }
87+
88+ /// Create by copying bytes into aligned storage.
89+ ///
90+ /// Use this when receiving bytes from unknown sources (e.g., network).
91+ pub fn copy_from_slice ( bytes : & [ u8 ] ) -> Self {
92+ Self :: Aligned ( AlignedVec :: copy_from_slice ( bytes) )
5093 }
5194
52- /// Read a file into memory .
95+ /// Read a file into aligned storage .
5396 pub fn from_file ( path : impl AsRef < Path > ) -> io:: Result < Self > {
54- let bytes = std:: fs:: read ( path) ?;
55- Ok ( Self ( bytes) )
97+ Ok ( Self :: Aligned ( AlignedVec :: from_file ( path) ?) )
5698 }
5799}
58100
@@ -118,15 +160,46 @@ pub struct Module {
118160}
119161
120162impl Module {
121- /// Load a module from owned bytes.
122- pub fn from_bytes ( bytes : Vec < u8 > ) -> Result < Self , ModuleError > {
123- Self :: from_storage ( ByteStorage :: from_vec ( bytes) )
163+ /// Load a module from an aligned vector (compiler output).
164+ ///
165+ /// This is the primary constructor for bytecode produced by the compiler.
166+ pub fn from_aligned ( vec : AlignedVec ) -> Result < Self , ModuleError > {
167+ Self :: from_storage ( ByteStorage :: from_aligned ( vec) )
168+ }
169+
170+ /// Load a module from static bytes (zero-copy).
171+ ///
172+ /// Use with `include_query_aligned!` to embed aligned bytecode:
173+ /// ```ignore
174+ /// use plotnik_lib::include_query_aligned;
175+ ///
176+ /// let module = Module::from_static(include_query_aligned!("query.ptk.bin"))?;
177+ /// ```
178+ ///
179+ /// # Panics
180+ /// Panics if bytes are not 64-byte aligned.
181+ pub fn from_static ( bytes : & ' static [ u8 ] ) -> Result < Self , ModuleError > {
182+ Self :: from_storage ( ByteStorage :: from_static ( bytes) )
124183 }
125184
126185 /// Load a module from a file path.
186+ ///
187+ /// Reads the file into 64-byte aligned storage.
127188 pub fn from_path ( path : impl AsRef < Path > ) -> Result < Self , ModuleError > {
128- let storage = ByteStorage :: from_file ( & path) ?;
129- Self :: from_storage ( storage)
189+ Self :: from_storage ( ByteStorage :: from_file ( & path) ?)
190+ }
191+
192+ /// Load a module from arbitrary bytes (copies into aligned storage).
193+ ///
194+ /// Use this for bytes from unknown sources (network, etc.). Always copies.
195+ pub fn load ( bytes : & [ u8 ] ) -> Result < Self , ModuleError > {
196+ Self :: from_storage ( ByteStorage :: copy_from_slice ( bytes) )
197+ }
198+
199+ /// Load a module from owned bytes (copies into aligned storage).
200+ #[ deprecated( since = "0.1.0" , note = "use `Module::from_aligned` for AlignedVec or `Module::load` for copying" ) ]
201+ pub fn from_bytes ( bytes : Vec < u8 > ) -> Result < Self , ModuleError > {
202+ Self :: load ( & bytes)
130203 }
131204
132205 /// Load a module from storage.
0 commit comments