1use crate::WASM_PAGE_SIZE_BYTES as PAGE;
3use std::{cell::RefCell, rc::Rc};
4
5pub trait Memory {
14 fn size(&self) -> u64;
16 fn grow(&self, pages: u64) -> i64;
18 fn read(&self, offset: u64, bytes: &mut [u8]);
20 fn write(&self, offset: u64, bytes: &[u8]);
22}
23
24impl<M: Memory + ?Sized> Memory for Rc<M> {
25 fn size(&self) -> u64 {
26 self.as_ref().size()
27 }
28 fn grow(&self, pages: u64) -> i64 {
29 self.as_ref().grow(pages)
30 }
31 fn read(&self, offset: u64, bytes: &mut [u8]) {
32 self.as_ref().read(offset, bytes);
33 }
34 fn write(&self, offset: u64, bytes: &[u8]) {
35 self.as_ref().write(offset, bytes);
36 }
37}
38impl<M: Memory + ?Sized> Memory for &M {
39 fn size(&self) -> u64 {
40 (**self).size()
41 }
42 fn grow(&self, pages: u64) -> i64 {
43 (**self).grow(pages)
44 }
45 fn read(&self, offset: u64, bytes: &mut [u8]) {
46 (**self).read(offset, bytes);
47 }
48 fn write(&self, offset: u64, bytes: &[u8]) {
49 (**self).write(offset, bytes);
50 }
51}
52
53pub type VectorMemory = Rc<RefCell<Vec<u8>>>;
55impl Memory for RefCell<Vec<u8>> {
56 fn size(&self) -> u64 {
57 self.borrow().len() as u64 / PAGE
58 }
59 fn grow(&self, pages: u64) -> i64 {
60 let previous = self.size();
61 let Some(length) = previous
62 .checked_add(pages)
63 .and_then(|value| value.checked_mul(PAGE))
64 .and_then(|value| usize::try_from(value).ok())
65 else {
66 return -1;
67 };
68 let mut bytes = self.borrow_mut();
69 let additional = length - bytes.len();
70 if bytes.try_reserve(additional).is_err() {
71 return -1;
72 }
73 bytes.resize(length, 0);
74 i64::try_from(previous).expect("native page count")
75 }
76 fn read(&self, offset: u64, bytes: &mut [u8]) {
77 let start = usize::try_from(offset).expect("native offset");
78 let end = start
79 .checked_add(bytes.len())
80 .expect("native range overflow");
81 bytes.copy_from_slice(&self.borrow()[start..end]);
82 }
83 fn write(&self, offset: u64, bytes: &[u8]) {
84 let start = usize::try_from(offset).expect("native offset");
85 let end = start
86 .checked_add(bytes.len())
87 .expect("native range overflow");
88 self.borrow_mut()[start..end].copy_from_slice(bytes);
89 }
90}
91
92#[cfg(not(target_arch = "wasm32"))]
94pub type DefaultMemoryImpl = VectorMemory;
95
96#[cfg(target_arch = "wasm32")]
102#[derive(Clone, Copy, Default)]
103pub struct DefaultMemoryImpl {
104 _private: (),
105}
106#[cfg(target_arch = "wasm32")]
107impl Memory for DefaultMemoryImpl {
108 fn size(&self) -> u64 {
109 ic_platform_runtime::ic0::stable64_size()
110 }
111 fn grow(&self, pages: u64) -> i64 {
112 ic_platform_runtime::cdk::stable::stable_grow(pages).map_or(-1, |previous| {
113 i64::try_from(previous).expect("IC page count")
114 })
115 }
116 fn read(&self, offset: u64, bytes: &mut [u8]) {
117 ic_platform_runtime::cdk::stable::stable_read(offset, bytes);
118 }
119 fn write(&self, offset: u64, bytes: &[u8]) {
120 ic_platform_runtime::cdk::stable::stable_write(offset, bytes);
121 }
122}