wasui_memory/preview1/
mod.rs1mod backends;
6mod guest_type;
7pub use guest_type::{GuestErrorType, GuestType};
8
9#[derive(Debug, thiserror::Error)]
10pub enum GuestError {
11 #[error("Pointer overflow")]
12 PtrOverflow,
13 #[error("Invalid pointer")]
14 InvalidPointer,
15 #[error("Invalid data")]
16 InvalidData,
17 #[error("Invalid memory")]
18 InvalidMemory,
19}
20
21pub trait Memory: Sized {
22 fn copy_to_slice(&self, ptr: GuestPtr<[u8]>, dst: &mut [u8]) -> Result<(), GuestError>;
23
24 fn copy_to_vec(&self, ptr: GuestPtr<[u8]>) -> Result<Vec<u8>, GuestError> {
25 let mut data = vec![0; ptr.len() as usize];
26 self.copy_to_slice(ptr, &mut data)?;
27 Ok(data)
28 }
29
30 fn read<T>(&self, ptr: GuestPtr<T>) -> Result<T, GuestError>
31 where
32 T: GuestType,
33 {
34 T::read(self, ptr)
35 }
36}
37
38pub trait MemoryMut: Sized {
39 fn copy_from_slice(&mut self, ptr: GuestPtr<[u8]>, src: &[u8]) -> Result<(), GuestError>;
40 fn write<T>(&mut self, ptr: GuestPtr<T>, value: T) -> Result<(), GuestError>
41 where
42 T: GuestType,
43 {
44 T::write(self, ptr, value)
45 }
46}
47
48pub trait GuestMemory: Memory + MemoryMut {}
49
50#[repr(transparent)]
51#[derive(Copy, Clone, PartialEq)]
52pub struct GuestPtr<T: ?Sized + Pointee> {
53 pointer: T::Pointer,
54}
55
56impl<T: ?Sized + Pointee> GuestPtr<T> {
57 pub fn new(pointer: T::Pointer) -> Self {
58 Self { pointer }
59 }
60
61 pub fn offset(&self) -> T::Pointer {
62 self.pointer
63 }
64
65 pub fn cast<U>(&self) -> GuestPtr<U>
72 where
73 U: Pointee<Pointer = T::Pointer> + ?Sized,
74 {
75 GuestPtr::new(self.pointer)
76 }
77
78 pub fn add(&self, amt: u32) -> Result<GuestPtr<T>, GuestError>
85 where
86 T: GuestType + Pointee<Pointer = u32>,
87 {
88 let offset = amt
89 .checked_mul(T::guest_size())
90 .and_then(|o| self.pointer.checked_add(o));
91 let offset = match offset {
92 Some(o) => o,
93 None => return Err(GuestError::PtrOverflow),
94 };
95 Ok(GuestPtr::new(offset))
96 }
97
98 pub fn as_array(&self, elems: u32) -> GuestPtr<[T]>
101 where
102 T: GuestType + Pointee<Pointer = u32>,
103 {
104 GuestPtr::new((self.pointer, elems))
105 }
106}
107
108impl<T> GuestPtr<[T]> {
109 pub fn offset_base(&self) -> u32 {
110 self.pointer.0
111 }
112
113 #[allow(clippy::len_without_is_empty)]
114 pub fn len(&self) -> u32 {
115 self.pointer.1
116 }
117
118 pub fn iter(&self) -> impl ExactSizeIterator<Item = Result<GuestPtr<T>, GuestError>> + '_
119 where
120 T: GuestType,
121 {
122 let base = self.as_ptr();
123 (0..self.len()).map(move |i| base.add(i))
124 }
125
126 pub fn as_ptr(&self) -> GuestPtr<T> {
127 GuestPtr::new(self.pointer.0)
128 }
129}
130
131impl GuestPtr<str> {
132 pub fn as_bytes(&self) -> GuestPtr<[u8]> {
133 GuestPtr::new((self.pointer.0, self.pointer.1))
134 }
135}
136
137mod private {
138 pub trait Sealed {}
139 impl<T> Sealed for T {}
140 impl<T> Sealed for [T] {}
141 impl Sealed for str {}
142}
143
144pub trait Pointee: private::Sealed {
145 #[doc(hidden)]
146 type Pointer: Copy + PartialEq;
147}
148
149impl<T> Pointee for T {
150 type Pointer = u32;
151}
152
153impl<T> Pointee for [T] {
154 type Pointer = (u32, u32);
155}
156
157impl Pointee for str {
158 type Pointer = (u32, u32);
159}