ic_stable_structures/
vec_mem.rs

1use crate::{Memory, WASM_PAGE_SIZE};
2use std::cell::RefCell;
3use std::ops::Deref;
4use std::rc::Rc;
5
6const MAX_PAGES: u64 = i64::MAX as u64 / WASM_PAGE_SIZE;
7
8/// A `Memory` that is based on a vector.
9pub type VectorMemory = Rc<RefCell<Vec<u8>>>;
10
11impl Memory for RefCell<Vec<u8>> {
12    fn size(&self) -> u64 {
13        self.borrow().len() as u64 / WASM_PAGE_SIZE
14    }
15
16    fn grow(&self, pages: u64) -> i64 {
17        let size = self.size();
18        match size.checked_add(pages) {
19            Some(n) => {
20                if n > MAX_PAGES {
21                    return -1;
22                }
23                self.borrow_mut().resize((n * WASM_PAGE_SIZE) as usize, 0);
24                size as i64
25            }
26            None => -1,
27        }
28    }
29
30    fn read(&self, offset: u64, dst: &mut [u8]) {
31        let n = offset
32            .checked_add(dst.len() as u64)
33            .expect("read: out of bounds");
34
35        if n as usize > self.borrow().len() {
36            panic!("read: out of bounds");
37        }
38
39        dst.copy_from_slice(&self.borrow()[offset as usize..n as usize]);
40    }
41
42    unsafe fn read_unsafe(&self, offset: u64, dst: *mut u8, count: usize) {
43        let n = offset
44            .checked_add(count as u64)
45            .expect("read: out of bounds");
46
47        if n as usize > self.borrow().len() {
48            panic!("read: out of bounds");
49        }
50
51        // SAFETY:
52        //  - we just checked that self is long enough
53        //  - the caller guarantees that there are at least count byte space after dst
54        //  - we are copying bytes so the pointers are automatically aligned
55        std::ptr::copy(self.borrow().as_ptr().add(offset as usize), dst, count);
56    }
57
58    fn write(&self, offset: u64, src: &[u8]) {
59        let n = offset
60            .checked_add(src.len() as u64)
61            .expect("write: out of bounds");
62
63        if n as usize > self.borrow().len() {
64            panic!("write: out of bounds");
65        }
66        self.borrow_mut()[offset as usize..n as usize].copy_from_slice(src);
67    }
68}
69
70impl<M: Memory> Memory for Rc<M> {
71    fn size(&self) -> u64 {
72        self.deref().size()
73    }
74    fn grow(&self, pages: u64) -> i64 {
75        self.deref().grow(pages)
76    }
77    fn read(&self, offset: u64, dst: &mut [u8]) {
78        self.deref().read(offset, dst)
79    }
80    unsafe fn read_unsafe(&self, offset: u64, dst: *mut u8, count: usize) {
81        self.deref().read_unsafe(offset, dst, count)
82    }
83    fn write(&self, offset: u64, src: &[u8]) {
84        self.deref().write(offset, src)
85    }
86}