1use crate::__private::wasip1::*;
2#[cfg(target_os = "wasi")]
3use const_for::const_for;
4use const_struct::*;
5
6use crate::memory::WasmAccess;
7
8#[macro_export]
59macro_rules! plug_args {
60 (@embedded, $ty:ty, $($wasm:ident),* $(,)?) => {
61 $crate::__as_t!(@through, $($wasm),* => $crate::plug_args, @inner, @embedded, $ty);
62 };
63
64 (@dynamic, $state:expr, $($wasm:ident),* $(,)?) => {
65 $crate::__as_t!(@through, $($wasm),* => $crate::plug_args, @inner, @dynamic, $state);
66 };
67
68 (@inner, @embedded, $ty:ty, $($wasm:ident),*) => {
69 const _: () = {
70 type __TYPE = $ty;
71 };
72
73 $crate::__private::paste::paste! {
74 $(
75 #[unsafe(no_mangle)]
76 #[cfg(target_os = "wasi")]
77 pub unsafe extern "C" fn [<__wasip1_vfs_ $wasm _args_sizes_get>](
78 args_count: *mut $crate::__private::wasip1::Size,
79 args_buf_size: *mut $crate::__private::wasip1::Size,
80 ) -> $crate::__private::wasip1::Errno {
81 $crate::__as_t!(@as_t, $wasm);
82 $crate::__private::inner::args::args_sizes_get_embedded_inner::<$ty, T>(args_count, args_buf_size)
83 }
84
85 #[cfg(target_os = "wasi")]
86 #[unsafe(no_mangle)]
87 pub unsafe extern "C" fn [<__wasip1_vfs_ $wasm _args_get>](
88 args: *mut *const u8,
89 args_buf: *mut u8,
90 ) -> $crate::__private::wasip1::Errno {
91 $crate::__as_t!(@as_t, $wasm);
92 $crate::__private::inner::args::args_get_embedded_inner::<$ty, T>(args, args_buf)
93 }
94 )*
95 }
96 };
97
98 (@dynamic, $state:expr, $($wasm:ident),* $(,)?) => {
99 $crate::__as_t!(@through, $($wasm),* => $crate::plug_args, @inner, @dynamic, $state);
100 };
101
102 (@inner, @embedded, $ty:ty, $($wasm:ident),*) => {
103 const _: () = {
104 type __TYPE = $ty;
105 };
106
107 $crate::__private::paste::paste! {
108 $(
109 #[unsafe(no_mangle)]
110 #[cfg(target_os = "wasi")]
111 pub unsafe extern "C" fn [<__wasip1_vfs_ $wasm _args_sizes_get>](
112 args_count: *mut $crate::__private::wasip1::Size,
113 args_buf_size: *mut $crate::__private::wasip1::Size,
114 ) -> $crate::__private::wasip1::Errno {
115 $crate::__as_t!(@as_t, $wasm);
116 $crate::__private::inner::args::args_sizes_get_const_inner::<$ty, T>(args_count, args_buf_size)
117 }
118
119 #[cfg(target_os = "wasi")]
120 #[unsafe(no_mangle)]
121 pub unsafe extern "C" fn [<__wasip1_vfs_ $wasm _args_get>](
122 args: *mut *const u8,
123 args_buf: *mut u8,
124 ) -> $crate::__private::wasip1::Errno {
125 $crate::__as_t!(@as_t, $wasm);
126 $crate::__private::inner::args::args_get_const_inner::<$ty, T>(args, args_buf)
127 }
128 )*
129 }
130 };
131
132 (@inner, @dynamic, $state:expr, $($wasm:ident),*) => {
133 $crate::__private::paste::paste! {
134 $(
135 #[cfg(target_os = "wasi")]
136 #[unsafe(no_mangle)]
137 pub unsafe extern "C" fn [<__wasip1_vfs_ $wasm _args_sizes_get>](
138 args_count: *mut $crate::__private::wasip1::Size,
139 args_buf_size: *mut $crate::__private::wasip1::Size,
140 ) -> $crate::__private::wasip1::Errno {
141 $crate::__as_t!(@as_t, $wasm);
142 let state = $state;
143 $crate::__private::inner::args::args_sizes_get_inner::<T>(state, args_count, args_buf_size)
144 }
145
146 #[cfg(target_os = "wasi")]
147 #[unsafe(no_mangle)]
148 pub unsafe extern "C" fn [<__wasip1_vfs_ $wasm _args_get>](
149 args: *mut *const u8,
150 args_buf: *mut u8,
151 ) -> $crate::__private::wasip1::Errno {
152 $crate::__as_t!(@as_t, $wasm);
153 let state = $state;
154 $crate::__private::inner::args::args_get_inner::<T>(state, args, args_buf)
155 }
156 )*
157 }
158 };
159}
160
161#[const_struct]
163pub struct VirtualArgsEmbeddedState {
164 pub args: &'static [&'static str],
166}
167
168#[inline]
170#[cfg(target_os = "wasi")]
171pub fn args_sizes_get_embedded_inner<
172 T: PrimitiveTraits<DATATYPE = VirtualArgsEmbeddedState>,
173 Wasm: WasmAccess,
174>(
175 args_count: *mut Size,
176 args_buf_size: *mut Size,
177) -> Errno {
178 const fn inner<T: PrimitiveTraits<DATATYPE = VirtualArgsEmbeddedState>>() -> (Size, Size) {
179 let mut size = 0;
180 let mut count = 0;
181 const_for!(i in 0..T::__DATA.args.len() => {
182 let len = T::__DATA.args[i].len() + 1; size += len;
184 count += 1;
185 });
186
187 (size, count)
188 }
189
190 Wasm::store_le(args_buf_size, inner::<T>().0);
191 Wasm::store_le(args_count, inner::<T>().1);
192 ERRNO_SUCCESS
193}
194
195#[inline]
197#[cfg(target_os = "wasi")]
198pub fn args_get_embedded_inner<
199 T: PrimitiveTraits<DATATYPE = VirtualArgsEmbeddedState>,
200 Wasm: WasmAccess,
201>(
202 args: *mut *const u8,
203 args_buf: *mut u8,
204) -> Errno {
205 let mut args = args;
206 let mut args_buf = args_buf;
207
208 const_for!(i in 0..T::__DATA.args.len() => {
209 Wasm::store_le(args, args_buf as *const u8);
210
211 Wasm::memcpy(args_buf, T::__DATA.args[i].as_bytes());
212 Wasm::store_le(unsafe { args_buf.add(T::__DATA.args[i].len()) }, 0u8);
213
214 args = unsafe { args.add(1) };
215 args_buf = unsafe { args_buf.add(T::__DATA.args[i].len() + 1) };
216 });
217
218 ERRNO_SUCCESS
219}
220
221#[inline]
223#[cfg(target_os = "wasi")]
224pub fn args_sizes_get_const_inner<
225 T: PrimitiveTraits<DATATYPE = VirtualArgsEmbeddedState>,
226 Wasm: WasmAccess,
227>(
228 args_count: *mut Size,
229 args_buf_size: *mut Size,
230) -> Errno {
231 const fn inner<T: PrimitiveTraits<DATATYPE = VirtualArgsEmbeddedState>>() -> (Size, Size) {
232 let mut size = 0;
233 let mut count = 0;
234 const_for!(i in 0..T::__DATA.args.len() => {
235 let len = T::__DATA.args[i].len() + 1; size += len;
237 count += 1;
238 });
239
240 (size, count)
241 }
242
243 Wasm::store_le(args_buf_size, inner::<T>().0);
244 Wasm::store_le(args_count, inner::<T>().1);
245 ERRNO_SUCCESS
246}
247
248#[inline]
250#[cfg(target_os = "wasi")]
251pub fn args_get_const_inner<
252 T: PrimitiveTraits<DATATYPE = VirtualArgsEmbeddedState>,
253 Wasm: WasmAccess,
254>(
255 args: *mut *const u8,
256 args_buf: *mut u8,
257) -> Errno {
258 let mut args = args;
259 let mut args_buf = args_buf;
260
261 const_for!(i in 0..T::__DATA.args.len() => {
262 Wasm::store_le(args, args_buf as *const u8);
263
264 Wasm::memcpy(args_buf, T::__DATA.args[i].as_bytes());
265 Wasm::store_le(unsafe { args_buf.add(T::__DATA.args[i].len()) }, 0u8);
266
267 args = unsafe { args.add(1) };
268 args_buf = unsafe { args_buf.add(T::__DATA.args[i].len() + 1) };
269 });
270
271 ERRNO_SUCCESS
272}
273
274pub trait VirtualArgs<'a> {
276 type Str: AsRef<str>;
278
279 fn get_args(&'a mut self) -> &'a [Self::Str];
281
282 fn args_sizes_get(&'a mut self) -> (Size, Size) {
284 let args = self.get_args();
285 let mut size = 0;
286 let mut count = 0;
287 for arg in args {
288 let len = arg.as_ref().len() + 1; size += len;
290 count += 1;
291 }
292
293 (size, count)
294 }
295
296 fn args_get<Wasm: WasmAccess>(&'a mut self, args: *mut *const u8, args_buf: *mut u8) -> Errno {
298 let mut args = args;
299 let mut args_buf = args_buf;
300
301 for arg in self.get_args() {
302 Wasm::store_le(args, args_buf as *const u8);
303
304 Wasm::memcpy(args_buf, arg.as_ref().as_bytes());
305 Wasm::store_le(unsafe { args_buf.add(arg.as_ref().len()) as *mut u8 }, 0u8);
306
307 args = unsafe { args.add(1) };
308 args_buf = unsafe { args_buf.add(arg.as_ref().len() + 1) };
309 }
310
311 ERRNO_SUCCESS
312 }
313}
314
315impl<'a, T: core::ops::DerefMut<Target = U>, U: VirtualArgs<'a> + 'a> VirtualArgs<'a> for T {
316 type Str = U::Str;
317
318 fn get_args(&'a mut self) -> &'a [Self::Str] {
319 self.deref_mut().get_args()
320 }
321
322 fn args_sizes_get(&'a mut self) -> (Size, Size) {
323 self.deref_mut().args_sizes_get()
324 }
325}
326
327#[cfg(target_os = "wasi")]
329pub fn args_sizes_get_inner<'a, Wasm: WasmAccess>(
330 state: &'a mut impl VirtualArgs<'a>,
331 args_count: *mut Size,
332 args_buf_size: *mut Size,
333) -> Errno {
334 let (size, count) = state.args_sizes_get();
335
336 Wasm::store_le(args_buf_size, size);
337 Wasm::store_le(args_count, count);
338
339 ERRNO_SUCCESS
340}
341
342#[inline]
344#[cfg(target_os = "wasi")]
345pub fn args_get_inner<'a, Wasm: WasmAccess>(
346 state: &'a mut impl VirtualArgs<'a>,
347 args: *mut *const u8,
348 args_buf: *mut u8,
349) -> Errno {
350 state.args_get::<Wasm>(args, args_buf)
351}