1use alloc::vec::Vec;
2use core::hint::cold_path;
3
4use super::{LinearMemory, checked_effective_addr};
5
6#[cfg_attr(feature = "debug", derive(Debug))]
14pub struct VecMemory {
15 data: Vec<u8>,
16}
17
18impl VecMemory {
19 pub fn try_new(len: usize) -> Result<Self, crate::Trap> {
23 let mut data = Vec::new();
24 match data.try_reserve_exact(len) {
25 Ok(()) => {}
26 Err(_) => {
27 cold_path();
28 return Err(crate::Trap::OutOfMemory);
29 }
30 }
31 data.resize(len, 0);
32 Ok(Self { data })
33 }
34}
35
36impl LinearMemory for VecMemory {
37 #[inline(always)]
38 fn len(&self) -> usize {
39 self.data.len()
40 }
41
42 #[inline(always)]
43 fn grow_to(&mut self, new_len: usize) -> Result<(), crate::Trap> {
44 if new_len < self.data.len() {
45 return Err(crate::Trap::MemoryOutOfBounds { offset: new_len, len: 0, max: self.data.len() });
46 }
47 match self.data.try_reserve_exact(new_len.saturating_sub(self.data.len())) {
48 Ok(()) => {}
49 Err(_) => {
50 cold_path();
51 return Err(crate::Trap::OutOfMemory);
52 }
53 }
54 self.data.resize(new_len, 0);
55 Ok(())
56 }
57
58 #[inline(always)]
59 fn read(&self, addr: usize, dst: &mut [u8]) -> usize {
60 if addr >= self.data.len() {
61 return 0;
62 }
63 let read_len = dst.len().min(self.data.len() - addr);
64 dst[..read_len].copy_from_slice(&self.data[addr..addr + read_len]);
65 read_len
66 }
67
68 #[inline(always)]
69 fn read_exact(&self, addr: usize, dst: &mut [u8]) -> Option<()> {
70 dst.copy_from_slice(self.data.get(addr..addr.checked_add(dst.len())?)?);
71 Some(())
72 }
73
74 #[inline(always)]
75 fn read_vec(&self, addr: usize, len: usize) -> Option<Vec<u8>> {
76 Some(self.data.get(addr..addr.checked_add(len)?)?.to_vec())
77 }
78
79 #[inline(always)]
80 fn write(&mut self, addr: usize, src: &[u8]) -> usize {
81 if addr >= self.data.len() {
82 return 0;
83 }
84
85 let write_len = src.len().min(self.data.len() - addr);
86 self.data[addr..addr + write_len].copy_from_slice(&src[..write_len]);
87 write_len
88 }
89
90 #[inline(always)]
91 fn write_all(&mut self, addr: usize, src: &[u8]) -> Option<()> {
92 let dst = self.data.get_mut(addr..addr.checked_add(src.len())?)?;
93 dst.copy_from_slice(src);
94 Some(())
95 }
96
97 #[inline(always)]
98 fn fill(&mut self, addr: usize, len: usize, val: u8) -> Option<()> {
99 self.data.get_mut(addr..addr.checked_add(len)?)?.fill(val);
100 Some(())
101 }
102
103 #[inline(always)]
104 fn copy_within(&mut self, dst: usize, src: usize, len: usize) -> Option<()> {
105 let src_end = src.checked_add(len)?;
106 let dst_end = dst.checked_add(len)?;
107 if src_end > self.data.len() || dst_end > self.data.len() {
108 return None;
109 }
110
111 self.data.copy_within(src..src_end, dst);
112 Some(())
113 }
114
115 #[inline(always)]
116 fn read_8(&self, base: u64, offset: u64) -> core::result::Result<u8, crate::Trap> {
117 Ok(self.data[checked_effective_addr::<1>(self.data.len(), base, offset)?])
118 }
119
120 #[inline(always)]
121 fn read_16(&self, base: u64, offset: u64) -> core::result::Result<[u8; 2], crate::Trap> {
122 let addr = checked_effective_addr::<2>(self.data.len(), base, offset)?;
123 match self.data[addr..addr + 2].try_into() {
124 Ok(bytes) => Ok(bytes),
125 Err(_) => {
126 cold_path();
127 unreachable!();
128 }
129 }
130 }
131
132 #[inline(always)]
133 fn read_32(&self, base: u64, offset: u64) -> core::result::Result<[u8; 4], crate::Trap> {
134 let addr = checked_effective_addr::<4>(self.data.len(), base, offset)?;
135 match self.data[addr..addr + 4].try_into() {
136 Ok(bytes) => Ok(bytes),
137 Err(_) => {
138 cold_path();
139 unreachable!();
140 }
141 }
142 }
143
144 #[inline(always)]
145 fn read_64(&self, base: u64, offset: u64) -> core::result::Result<[u8; 8], crate::Trap> {
146 let addr = checked_effective_addr::<8>(self.data.len(), base, offset)?;
147 match self.data[addr..addr + 8].try_into() {
148 Ok(bytes) => Ok(bytes),
149 Err(_) => {
150 cold_path();
151 unreachable!();
152 }
153 }
154 }
155
156 #[inline(always)]
157 fn read_128(&self, base: u64, offset: u64) -> core::result::Result<[u8; 16], crate::Trap> {
158 let addr = checked_effective_addr::<16>(self.data.len(), base, offset)?;
159 match self.data[addr..addr + 16].try_into() {
160 Ok(bytes) => Ok(bytes),
161 Err(_) => {
162 cold_path();
163 unreachable!();
164 }
165 }
166 }
167
168 #[inline(always)]
169 fn write_8(&mut self, base: u64, offset: u64, byte: u8) -> core::result::Result<(), crate::Trap> {
170 let addr = checked_effective_addr::<1>(self.data.len(), base, offset)?;
171 self.data[addr] = byte;
172 Ok(())
173 }
174
175 #[inline(always)]
176 fn write_16(&mut self, base: u64, offset: u64, bytes: [u8; 2]) -> core::result::Result<(), crate::Trap> {
177 let addr = checked_effective_addr::<2>(self.data.len(), base, offset)?;
178 self.data[addr..addr + 2].copy_from_slice(&bytes);
179 Ok(())
180 }
181
182 #[inline(always)]
183 fn write_32(&mut self, base: u64, offset: u64, bytes: [u8; 4]) -> core::result::Result<(), crate::Trap> {
184 let addr = checked_effective_addr::<4>(self.data.len(), base, offset)?;
185 self.data[addr..addr + 4].copy_from_slice(&bytes);
186 Ok(())
187 }
188
189 #[inline(always)]
190 fn write_64(&mut self, base: u64, offset: u64, bytes: [u8; 8]) -> core::result::Result<(), crate::Trap> {
191 let addr = checked_effective_addr::<8>(self.data.len(), base, offset)?;
192 self.data[addr..addr + 8].copy_from_slice(&bytes);
193 Ok(())
194 }
195
196 #[inline(always)]
197 fn write_128(&mut self, base: u64, offset: u64, bytes: [u8; 16]) -> core::result::Result<(), crate::Trap> {
198 let addr = checked_effective_addr::<16>(self.data.len(), base, offset)?;
199 self.data[addr..addr + 16].copy_from_slice(&bytes);
200 Ok(())
201 }
202}