1use std::mem::MaybeUninit;
2
3use crate::mem_access::{WasmRef, WasmSlice};
4
5pub(super) enum SliceCow<'a, T> {
6 #[allow(dead_code)]
7 Borrowed(&'a mut [T]),
8 #[allow(dead_code)]
9 Owned(Vec<T>, bool),
10}
11
12impl<'a, T> AsRef<[T]> for SliceCow<'a, T> {
13 fn as_ref(&self) -> &[T] {
14 match self {
15 Self::Borrowed(buf) => buf,
16 Self::Owned(buf, _) => buf,
17 }
18 }
19}
20
21impl<'a, T> AsMut<[T]> for SliceCow<'a, T> {
22 fn as_mut(&mut self) -> &mut [T] {
23 match self {
27 Self::Borrowed(buf) => buf,
28 Self::Owned(buf, modified) => {
29 *modified = true;
30 buf.as_mut()
31 }
32 }
33 }
34}
35
36pub struct WasmSliceAccess<'a, T>
39where
40 T: wasmer_types::ValueType,
41{
42 pub(super) slice: WasmSlice<'a, T>,
43 pub(super) buf: SliceCow<'a, T>,
44}
45
46impl<'a, T> AsRef<[T]> for WasmSliceAccess<'a, T>
47where
48 T: wasmer_types::ValueType,
49{
50 fn as_ref(&self) -> &[T] {
51 self.buf.as_ref()
52 }
53}
54
55impl<'a, T> AsMut<[T]> for WasmSliceAccess<'a, T>
56where
57 T: wasmer_types::ValueType,
58{
59 fn as_mut(&mut self) -> &mut [T] {
60 self.buf.as_mut()
61 }
62}
63
64impl<'a, T> WasmSliceAccess<'a, T>
65where
66 T: wasmer_types::ValueType,
67{
68 pub fn iter(&'a self) -> std::slice::Iter<'a, T> {
70 self.as_ref().iter()
71 }
72
73 pub fn iter_mut(&'a mut self) -> std::slice::IterMut<'a, T> {
75 self.buf.as_mut().iter_mut()
76 }
77
78 pub fn len(&self) -> usize {
80 self.buf.as_ref().len()
81 }
82
83 pub fn is_empty(&self) -> bool {
85 self.buf.as_ref().is_empty()
86 }
87}
88
89impl<'a> WasmSliceAccess<'a, u8> {
90 #[inline]
92 pub fn copy_from_slice(&mut self, src: &[u8]) {
93 let dst = self.buf.as_mut();
94 dst.copy_from_slice(src);
95 }
96
97 #[inline]
104 pub fn copy_from_slice_min(&mut self, src: &[u8]) -> usize {
105 let dst = self.buf.as_mut();
106 let amt = dst.len().min(src.len());
107 dst[..amt].copy_from_slice(&src[..amt]);
108 amt
109 }
110}
111
112impl<'a, T> Drop for WasmSliceAccess<'a, T>
113where
114 T: wasmer_types::ValueType,
115{
116 fn drop(&mut self) {
117 if let SliceCow::Owned(buf, modified) = &self.buf {
118 if *modified {
119 self.slice.write_slice(buf.as_ref()).ok();
120 }
121 }
122 }
123}
124
125pub(super) enum RefCow<'a, T> {
126 #[allow(dead_code)]
127 Borrowed(&'a mut T),
128 #[allow(dead_code)]
129 Owned(T, bool),
130}
131
132impl<'a, T> AsRef<T> for RefCow<'a, T> {
133 fn as_ref(&self) -> &T {
134 match self {
135 Self::Borrowed(val) => val,
136 Self::Owned(val, _) => val,
137 }
138 }
139}
140
141impl<'a, T> AsMut<T> for RefCow<'a, T> {
142 fn as_mut(&mut self) -> &mut T {
143 match self {
147 Self::Borrowed(val) => val,
148 Self::Owned(val, modified) => {
149 *modified = true;
150 val
151 }
152 }
153 }
154}
155
156pub struct WasmRefAccess<'a, T>
159where
160 T: wasmer_types::ValueType,
161{
162 pub(super) ptr: WasmRef<'a, T>,
163 pub(super) buf: RefCow<'a, T>,
164}
165
166impl<'a, T> AsRef<T> for WasmRefAccess<'a, T>
167where
168 T: wasmer_types::ValueType,
169{
170 fn as_ref(&self) -> &T {
171 self.buf.as_ref()
172 }
173}
174
175impl<'a, T> AsMut<T> for WasmRefAccess<'a, T>
176where
177 T: wasmer_types::ValueType,
178{
179 fn as_mut(&mut self) -> &mut T {
180 self.buf.as_mut()
181 }
182}
183
184impl<'a, T> Drop for WasmRefAccess<'a, T>
185where
186 T: wasmer_types::ValueType,
187{
188 fn drop(&mut self) {
189 if let RefCow::Owned(val, modified) = &self.buf {
190 if *modified {
191 self.ptr.write(*val).ok();
192 }
193 }
194 }
195}
196
197impl<'a, T> WasmSliceAccess<'a, T>
198where
199 T: wasmer_types::ValueType,
200{
201 pub fn as_mut_uninit(&mut self) -> &mut [MaybeUninit<T>] {
203 let ret: &mut [T] = self.buf.as_mut();
204 let ret: &mut [MaybeUninit<T>] = unsafe { std::mem::transmute(ret) };
205 ret
206 }
207}
208
209impl<'a, T> WasmRefAccess<'a, T>
210where
211 T: wasmer_types::ValueType,
212{
213 pub fn as_mut_uninit(&mut self) -> &mut MaybeUninit<T> {
215 let ret: &mut T = self.buf.as_mut();
216 let ret: &mut MaybeUninit<T> = unsafe { std::mem::transmute(ret) };
217 ret
218 }
219}