1use crate::storable::bytes_to_store_size;
37use crate::{
38 read_u32, read_u64, safe_write, write_u32, write_u64, Address, BoundedStorable, GrowFailed,
39 Memory,
40};
41use std::borrow::{Borrow, Cow};
42use std::fmt;
43use std::marker::PhantomData;
44
45const LAYOUT_VERSION: u8 = 1;
46const DATA_OFFSET: u64 = 64;
48const LEN_OFFSET: u64 = 4;
50
51#[derive(Debug)]
52struct HeaderV1 {
53 magic: [u8; 3],
54 version: u8,
55 len: u64,
56 max_size: u32,
57 is_fixed_size: bool,
58}
59
60#[derive(PartialEq, Eq, Debug)]
61pub enum InitError {
62 BadMagic { actual: [u8; 3], expected: [u8; 3] },
65 IncompatibleVersion(u8),
68 IncompatibleElementType,
72 OutOfMemory,
74}
75
76impl fmt::Display for InitError {
77 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
78 match self {
79 Self::BadMagic{ actual, expected } => {
80 write!(fmt, "bad magic number {actual:?}, expected {expected:?}")
81 }
82 Self::IncompatibleVersion(version)
83 => write!(
84 fmt,
85 "unsupported layout version {version}; supported version numbers are 1..={LAYOUT_VERSION}"
86 ),
87 Self::IncompatibleElementType =>
88 write!(fmt, "either MAX_SIZE or IS_FIXED_SIZE of the element type do not match the persisted vector attributes"),
89 Self::OutOfMemory => write!(fmt, "failed to allocate memory for vector metadata"),
90 }
91 }
92}
93
94impl std::error::Error for InitError {}
95
96pub struct BaseVec<T: BoundedStorable, M: Memory> {
97 memory: M,
98 _marker: PhantomData<T>,
99}
100
101impl<T: BoundedStorable, M: Memory> BaseVec<T, M> {
102 pub fn new(memory: M, magic: [u8; 3]) -> Result<Self, GrowFailed> {
108 let header = HeaderV1 {
109 magic,
110 version: LAYOUT_VERSION,
111 len: 0,
112 max_size: T::MAX_SIZE,
113 is_fixed_size: T::IS_FIXED_SIZE,
114 };
115 Self::write_header(&header, &memory)?;
116 Ok(Self {
117 memory,
118 _marker: PhantomData,
119 })
120 }
121
122 pub fn init(memory: M, magic: [u8; 3]) -> Result<Self, InitError> {
129 if memory.size() == 0 {
130 return Self::new(memory, magic).map_err(|_| InitError::OutOfMemory);
131 }
132 let header = Self::read_header(&memory);
133 if header.magic != magic {
134 return Err(InitError::BadMagic {
135 actual: header.magic,
136 expected: magic,
137 });
138 }
139 if header.version != LAYOUT_VERSION {
140 return Err(InitError::IncompatibleVersion(header.version));
141 }
142 if header.max_size != T::MAX_SIZE || header.is_fixed_size != T::IS_FIXED_SIZE {
143 return Err(InitError::IncompatibleElementType);
144 }
145
146 Ok(Self {
147 memory,
148 _marker: PhantomData,
149 })
150 }
151
152 pub fn into_memory(self) -> M {
154 self.memory
155 }
156
157 pub fn is_empty(&self) -> bool {
161 self.len() == 0
162 }
163
164 pub fn len(&self) -> u64 {
168 read_u64(&self.memory, Address::from(LEN_OFFSET))
169 }
170
171 pub fn set(&self, index: u64, item: &T) {
177 assert!(index < self.len());
178
179 let offset = DATA_OFFSET + slot_size::<T>() as u64 * index;
180 let bytes = item.to_bytes();
181 let data_offset = self
182 .write_entry_size(offset, bytes.len() as u32)
183 .expect("unreachable: cannot fail to write to pre-allocated area");
184 self.memory.write(data_offset, bytes.borrow());
185 }
186
187 pub fn get(&self, index: u64) -> Option<T> {
191 if index < self.len() {
192 Some(self.read_entry(index))
193 } else {
194 None
195 }
196 }
197
198 pub fn push(&self, item: &T) -> Result<(), GrowFailed> {
202 let index = self.len();
203 let offset = DATA_OFFSET + slot_size::<T>() as u64 * index;
204 let bytes = item.to_bytes();
205 let data_offset = self.write_entry_size(offset, bytes.len() as u32)?;
206 safe_write(&self.memory, data_offset, bytes.borrow())?;
207 self.set_len(index + 1);
210 Ok(())
211 }
212
213 pub fn pop(&self) -> Option<T> {
217 let len = self.len();
218 if len == 0 {
219 return None;
220 }
221 let value = self.read_entry(len - 1);
222 self.set_len(len - 1);
223 Some(value)
224 }
225
226 pub fn iter(&self) -> Iter<'_, T, M> {
227 Iter {
228 vec: self,
229 buf: vec![],
230 pos: 0,
231 }
232 }
233
234 fn read_entry(&self, index: u64) -> T {
236 let mut data = std::vec::Vec::new();
237 self.read_entry_to(index, &mut data);
238 T::from_bytes(Cow::Owned(data))
239 }
240
241 fn read_entry_to(&self, index: u64, buf: &mut std::vec::Vec<u8>) {
243 let offset = DATA_OFFSET + slot_size::<T>() as u64 * index;
244 let (data_offset, data_size) = self.read_entry_size(offset);
245 buf.resize(data_size, 0);
246 self.memory.read(data_offset, &mut buf[..]);
247 }
248
249 fn set_len(&self, new_len: u64) {
251 write_u64(&self.memory, Address::from(LEN_OFFSET), new_len);
252 }
253
254 fn write_entry_size(&self, offset: u64, size: u32) -> Result<u64, GrowFailed> {
256 debug_assert!(size <= T::MAX_SIZE);
257
258 if T::IS_FIXED_SIZE {
259 Ok(offset)
260 } else if T::MAX_SIZE <= u8::MAX as u32 {
261 safe_write(&self.memory, offset, &[size as u8; 1])?;
262 Ok(offset + 1)
263 } else if T::MAX_SIZE <= u16::MAX as u32 {
264 safe_write(&self.memory, offset, &(size as u16).to_le_bytes())?;
265 Ok(offset + 2)
266 } else {
267 safe_write(&self.memory, offset, &size.to_le_bytes())?;
268 Ok(offset + 4)
269 }
270 }
271
272 fn read_entry_size(&self, offset: u64) -> (u64, usize) {
274 if T::IS_FIXED_SIZE {
275 (offset, T::MAX_SIZE as usize)
276 } else if T::MAX_SIZE <= u8::MAX as u32 {
277 let mut size = [0u8; 1];
278 self.memory.read(offset, &mut size);
279 (offset + 1, size[0] as usize)
280 } else if T::MAX_SIZE <= u16::MAX as u32 {
281 let mut size = [0u8; 2];
282 self.memory.read(offset, &mut size);
283 (offset + 2, u16::from_le_bytes(size) as usize)
284 } else {
285 let size = read_u32(&self.memory, Address::from(offset));
286 (offset + 4, size as usize)
287 }
288 }
289
290 fn write_header(header: &HeaderV1, memory: &M) -> Result<(), GrowFailed> {
292 safe_write(memory, 0, &header.magic)?;
293 memory.write(3, &[header.version; 1]);
294 write_u64(memory, Address::from(4), header.len);
295 write_u32(memory, Address::from(12), header.max_size);
296 memory.write(16, &[if header.is_fixed_size { 1u8 } else { 0u8 }; 1]);
297 Ok(())
298 }
299
300 fn read_header(memory: &M) -> HeaderV1 {
304 debug_assert!(memory.size() > 0);
305
306 let mut magic = [0u8; 3];
307 let mut version = [0u8; 1];
308 let mut is_fixed_size = [0u8; 1];
309 memory.read(0, &mut magic);
310 memory.read(3, &mut version);
311 let len = read_u64(memory, Address::from(LEN_OFFSET));
312 let max_size = read_u32(memory, Address::from(12));
313 memory.read(16, &mut is_fixed_size);
314
315 HeaderV1 {
316 magic,
317 version: version[0],
318 len,
319 max_size,
320 is_fixed_size: is_fixed_size[0] != 0,
321 }
322 }
323
324 pub fn to_vec(&self) -> Vec<T> {
325 self.iter().collect()
326 }
327}
328
329impl<T: BoundedStorable + fmt::Debug, M: Memory> fmt::Debug for BaseVec<T, M> {
330 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
331 self.to_vec().fmt(fmt)
332 }
333}
334
335fn slot_size<T: BoundedStorable>() -> u32 {
336 T::MAX_SIZE + bytes_to_store_size::<T>()
337}
338
339pub struct Iter<'a, T, M>
340where
341 T: BoundedStorable,
342 M: Memory,
343{
344 vec: &'a BaseVec<T, M>,
345 buf: std::vec::Vec<u8>,
346 pos: u64,
347}
348
349impl<T, M> Iterator for Iter<'_, T, M>
350where
351 T: BoundedStorable,
352 M: Memory,
353{
354 type Item = T;
355
356 fn next(&mut self) -> Option<T> {
357 if self.vec.len() <= self.pos {
358 return None;
359 }
360
361 self.vec.read_entry_to(self.pos, &mut self.buf);
362 self.pos = self.pos.saturating_add(1);
363 Some(T::from_bytes(Cow::Borrowed(&self.buf)))
364 }
365
366 fn size_hint(&self) -> (usize, Option<usize>) {
367 (self.vec.len().saturating_sub(self.pos) as usize, None)
368 }
369
370 fn count(self) -> usize {
371 let n = self.vec.len().saturating_sub(self.pos);
372 if n > usize::MAX as u64 {
373 panic!("The number of items in the vec {n} does not fit into usize");
374 }
375 n as usize
376 }
377
378 fn nth(&mut self, n: usize) -> Option<T> {
379 self.pos = self.pos.saturating_add(n as u64);
380 self.next()
381 }
382}