plotnik_bytecode/bytecode/
aligned_vec.rs1use std::ops::Deref;
8
9pub const ALIGN: usize = 64;
11
12#[repr(C, align(64))]
14#[derive(Clone, Copy)]
15struct Block([u8; 64]);
16
17pub struct AlignedVec {
22 blocks: Vec<Block>,
23 len: usize,
24}
25
26impl AlignedVec {
27 pub fn copy_from_slice(bytes: &[u8]) -> Self {
29 if bytes.is_empty() {
30 return Self {
31 blocks: Vec::new(),
32 len: 0,
33 };
34 }
35
36 let num_blocks = bytes.len().div_ceil(64);
37 let mut blocks = vec![Block([0; 64]); num_blocks];
38
39 for (i, chunk) in bytes.chunks(64).enumerate() {
41 blocks[i].0[..chunk.len()].copy_from_slice(chunk);
42 }
43
44 Self {
45 blocks,
46 len: bytes.len(),
47 }
48 }
49
50 pub fn from_file(path: impl AsRef<std::path::Path>) -> std::io::Result<Self> {
52 let bytes = std::fs::read(path)?;
53 Ok(Self::copy_from_slice(&bytes))
54 }
55
56 pub fn len(&self) -> usize {
58 self.len
59 }
60
61 pub fn is_empty(&self) -> bool {
63 self.len == 0
64 }
65
66 pub fn as_slice(&self) -> &[u8] {
68 if self.blocks.is_empty() {
69 return &[];
70 }
71 if self.len > self.blocks.len() * 64 {
72 panic!(
73 "AlignedVec invariant violated: len {} exceeds capacity {}",
74 self.len,
75 self.blocks.len() * 64
76 );
77 }
78 unsafe { std::slice::from_raw_parts(self.blocks.as_ptr() as *const u8, self.len) }
81 }
82}
83
84impl Deref for AlignedVec {
85 type Target = [u8];
86
87 fn deref(&self) -> &[u8] {
88 self.as_slice()
89 }
90}
91
92impl Clone for AlignedVec {
93 fn clone(&self) -> Self {
94 Self {
95 blocks: self.blocks.clone(),
96 len: self.len,
97 }
98 }
99}
100
101impl std::fmt::Debug for AlignedVec {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 f.debug_struct("AlignedVec")
104 .field("len", &self.len)
105 .field("aligned", &(self.blocks.as_ptr() as usize).is_multiple_of(ALIGN))
106 .finish()
107 }
108}