1 //! Functions to go back and forth between WASI types in host and wasm32 representations.
2 //!
3 //! This module is an adaptation of the `wasmtime-wasi` module
4 //! [`translate.rs`](https://github.com/CraneStation/wasmtime-wasi/blob/1a6ecf3a0378d71f3fc1ba25ce76a2b43e4166b8/lib/wasi/src/translate.rs);
5 //! its license file `LICENSE.wasmtime-wasi` is included in this project.
6 //!
7 //! Any of these functions that take a `Vmctx` argument are only meant to be called from within a
8 //! hostcall.
9 //!
10 //! This sort of manual encoding will hopefully be obsolete once the IDL is developed.
11 
12 use crate::{host, wasm32};
13 use cast;
14 use cast::From as _0;
15 use lucet_runtime::vmctx::Vmctx;
16 use std::mem::{align_of, size_of};
17 use std::slice;
18 
19 macro_rules! bail_errno {
20     ( $errno:ident ) => {
21         return Err(host::$errno as host::__wasi_errno_t);
22     };
23 }
24 
dec_ptr( vmctx: &Vmctx, ptr: wasm32::uintptr_t, len: usize, ) -> Result<*const u8, host::__wasi_errno_t>25 pub fn dec_ptr(
26     vmctx: &Vmctx,
27     ptr: wasm32::uintptr_t,
28     len: usize,
29 ) -> Result<*const u8, host::__wasi_errno_t> {
30     let heap = vmctx.heap();
31 
32     // check for overflow
33     let checked_len = (ptr as usize)
34         .checked_add(len)
35         .ok_or(host::__WASI_EFAULT as host::__wasi_errno_t)?;
36     if checked_len > heap.len() {
37         bail_errno!(__WASI_EFAULT);
38     }
39     // translate the pointer
40     Ok(unsafe { heap.as_ptr().offset(ptr as isize) })
41 }
42 
dec_ptr_mut( vmctx: &Vmctx, ptr: wasm32::uintptr_t, len: usize, ) -> Result<*mut u8, host::__wasi_errno_t>43 pub fn dec_ptr_mut(
44     vmctx: &Vmctx,
45     ptr: wasm32::uintptr_t,
46     len: usize,
47 ) -> Result<*mut u8, host::__wasi_errno_t> {
48     let mut heap = vmctx.heap_mut();
49 
50     // check for overflow
51     let checked_len = (ptr as usize)
52         .checked_add(len)
53         .ok_or(host::__WASI_EFAULT as host::__wasi_errno_t)?;
54     if checked_len > heap.len() {
55         bail_errno!(__WASI_EFAULT);
56     }
57     // translate the pointer
58     Ok(unsafe { heap.as_mut_ptr().offset(ptr as isize) })
59 }
60 
dec_ptr_to<T>( vmctx: &Vmctx, ptr: wasm32::uintptr_t, ) -> Result<*const T, host::__wasi_errno_t>61 pub fn dec_ptr_to<T>(
62     vmctx: &Vmctx,
63     ptr: wasm32::uintptr_t,
64 ) -> Result<*const T, host::__wasi_errno_t> {
65     // check that the ptr is aligned
66     if ptr as usize % align_of::<T>() != 0 {
67         bail_errno!(__WASI_EINVAL);
68     }
69     dec_ptr(vmctx, ptr, size_of::<T>()).map(|p| p as *const T)
70 }
71 
dec_ptr_to_mut<T>( vmctx: &Vmctx, ptr: wasm32::uintptr_t, ) -> Result<*mut T, host::__wasi_errno_t>72 pub fn dec_ptr_to_mut<T>(
73     vmctx: &Vmctx,
74     ptr: wasm32::uintptr_t,
75 ) -> Result<*mut T, host::__wasi_errno_t> {
76     // check that the ptr is aligned
77     if ptr as usize % align_of::<T>() != 0 {
78         bail_errno!(__WASI_EINVAL);
79     }
80     dec_ptr_mut(vmctx, ptr, size_of::<T>()).map(|p| p as *mut T)
81 }
82 
dec_pointee<T>(vmctx: &Vmctx, ptr: wasm32::uintptr_t) -> Result<T, host::__wasi_errno_t>83 pub fn dec_pointee<T>(vmctx: &Vmctx, ptr: wasm32::uintptr_t) -> Result<T, host::__wasi_errno_t> {
84     dec_ptr_to::<T>(vmctx, ptr).map(|p| unsafe { p.read() })
85 }
86 
enc_pointee<T>( vmctx: &Vmctx, ptr: wasm32::uintptr_t, t: T, ) -> Result<(), host::__wasi_errno_t>87 pub fn enc_pointee<T>(
88     vmctx: &Vmctx,
89     ptr: wasm32::uintptr_t,
90     t: T,
91 ) -> Result<(), host::__wasi_errno_t> {
92     dec_ptr_to_mut::<T>(vmctx, ptr).map(|p| unsafe { p.write(t) })
93 }
94 
check_slice_of<T>( ptr: wasm32::uintptr_t, len: wasm32::size_t, ) -> Result<(usize, usize), host::__wasi_errno_t>95 fn check_slice_of<T>(
96     ptr: wasm32::uintptr_t,
97     len: wasm32::size_t,
98 ) -> Result<(usize, usize), host::__wasi_errno_t> {
99     // check alignment, and that length doesn't overflow
100     if ptr as usize % align_of::<T>() != 0 {
101         bail_errno!(__WASI_EINVAL);
102     }
103     let len = dec_usize(len);
104     let len_bytes = if let Some(len) = size_of::<T>().checked_mul(len) {
105         len
106     } else {
107         bail_errno!(__WASI_EOVERFLOW);
108     };
109     Ok((len, len_bytes))
110 }
111 
dec_slice_of<'vmctx, T>( vmctx: &'vmctx Vmctx, ptr: wasm32::uintptr_t, len: wasm32::size_t, ) -> Result<&'vmctx [T], host::__wasi_errno_t>112 pub fn dec_slice_of<'vmctx, T>(
113     vmctx: &'vmctx Vmctx,
114     ptr: wasm32::uintptr_t,
115     len: wasm32::size_t,
116 ) -> Result<&'vmctx [T], host::__wasi_errno_t> {
117     let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
118     let ptr = dec_ptr(vmctx, ptr, len_bytes)? as *const T;
119     Ok(unsafe { slice::from_raw_parts(ptr, len) })
120 }
121 
dec_slice_of_mut<'vmctx, T>( vmctx: &'vmctx Vmctx, ptr: wasm32::uintptr_t, len: wasm32::size_t, ) -> Result<&'vmctx mut [T], host::__wasi_errno_t>122 pub fn dec_slice_of_mut<'vmctx, T>(
123     vmctx: &'vmctx Vmctx,
124     ptr: wasm32::uintptr_t,
125     len: wasm32::size_t,
126 ) -> Result<&'vmctx mut [T], host::__wasi_errno_t> {
127     let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
128     let ptr = dec_ptr_mut(vmctx, ptr, len_bytes)? as *mut T;
129     Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
130 }
131 
enc_slice_of<T>( vmctx: &Vmctx, slice: &[T], ptr: wasm32::uintptr_t, ) -> Result<(), host::__wasi_errno_t>132 pub fn enc_slice_of<T>(
133     vmctx: &Vmctx,
134     slice: &[T],
135     ptr: wasm32::uintptr_t,
136 ) -> Result<(), host::__wasi_errno_t> {
137     // check alignment
138     if ptr as usize % align_of::<T>() != 0 {
139         return Err(host::__WASI_EINVAL as host::__wasi_errno_t);
140     }
141     // check that length doesn't overflow
142     let len_bytes = if let Some(len) = size_of::<T>().checked_mul(slice.len()) {
143         len
144     } else {
145         return Err(host::__WASI_EOVERFLOW as host::__wasi_errno_t);
146     };
147 
148     // get the pointer into guest memory, and copy the bytes
149     let ptr = dec_ptr(vmctx, ptr, len_bytes)? as *mut libc::c_void;
150     unsafe { std::ptr::copy_nonoverlapping(slice.as_ptr() as *const libc::c_void, ptr, len_bytes) };
151 
152     Ok(())
153 }
154 
155 macro_rules! dec_enc_scalar {
156     ( $ty:ident, $dec:ident, $dec_byref:ident, $enc:ident, $enc_byref:ident) => {
157         pub fn $dec(x: wasm32::$ty) -> host::$ty {
158             host::$ty::from_le(x)
159         }
160 
161         pub fn $dec_byref(
162             vmctx: &Vmctx,
163             ptr: wasm32::uintptr_t,
164         ) -> Result<host::$ty, host::__wasi_errno_t> {
165             dec_pointee::<wasm32::$ty>(vmctx, ptr).map($dec)
166         }
167 
168         pub fn $enc(x: host::$ty) -> wasm32::$ty {
169             x.to_le()
170         }
171 
172         pub fn $enc_byref(
173             vmctx: &Vmctx,
174             ptr: wasm32::uintptr_t,
175             x: host::$ty,
176         ) -> Result<(), host::__wasi_errno_t> {
177             enc_pointee::<wasm32::$ty>(vmctx, ptr, $enc(x))
178         }
179     };
180 }
181 
dec_ciovec( vmctx: &Vmctx, ciovec: &wasm32::__wasi_ciovec_t, ) -> Result<host::__wasi_ciovec_t, host::__wasi_errno_t>182 pub fn dec_ciovec(
183     vmctx: &Vmctx,
184     ciovec: &wasm32::__wasi_ciovec_t,
185 ) -> Result<host::__wasi_ciovec_t, host::__wasi_errno_t> {
186     let len = dec_usize(ciovec.buf_len);
187     Ok(host::__wasi_ciovec_t {
188         buf: dec_ptr(vmctx, ciovec.buf, len)? as *const host::void,
189         buf_len: len,
190     })
191 }
192 
dec_ciovec_slice( vmctx: &Vmctx, ptr: wasm32::uintptr_t, len: wasm32::size_t, ) -> Result<Vec<host::__wasi_ciovec_t>, host::__wasi_errno_t>193 pub fn dec_ciovec_slice(
194     vmctx: &Vmctx,
195     ptr: wasm32::uintptr_t,
196     len: wasm32::size_t,
197 ) -> Result<Vec<host::__wasi_ciovec_t>, host::__wasi_errno_t> {
198     let slice = dec_slice_of::<wasm32::__wasi_ciovec_t>(vmctx, ptr, len)?;
199     slice.iter().map(|iov| dec_ciovec(vmctx, iov)).collect()
200 }
201 
dec_iovec( vmctx: &Vmctx, iovec: &wasm32::__wasi_iovec_t, ) -> Result<host::__wasi_iovec_t, host::__wasi_errno_t>202 pub fn dec_iovec(
203     vmctx: &Vmctx,
204     iovec: &wasm32::__wasi_iovec_t,
205 ) -> Result<host::__wasi_iovec_t, host::__wasi_errno_t> {
206     let len = dec_usize(iovec.buf_len);
207     Ok(host::__wasi_iovec_t {
208         buf: dec_ptr(vmctx, iovec.buf, len)? as *mut host::void,
209         buf_len: len,
210     })
211 }
212 
dec_iovec_slice( vmctx: &Vmctx, ptr: wasm32::uintptr_t, len: wasm32::size_t, ) -> Result<Vec<host::__wasi_iovec_t>, host::__wasi_errno_t>213 pub fn dec_iovec_slice(
214     vmctx: &Vmctx,
215     ptr: wasm32::uintptr_t,
216     len: wasm32::size_t,
217 ) -> Result<Vec<host::__wasi_iovec_t>, host::__wasi_errno_t> {
218     let slice = dec_slice_of::<wasm32::__wasi_iovec_t>(vmctx, ptr, len)?;
219     slice.iter().map(|iov| dec_iovec(vmctx, iov)).collect()
220 }
221 
222 dec_enc_scalar!(
223     __wasi_clockid_t,
224     dec_clockid,
225     dec_clockid_byref,
226     enc_clockid,
227     enc_clockid_byref
228 );
229 dec_enc_scalar!(
230     __wasi_errno_t,
231     dec_errno,
232     dec_errno_byref,
233     enc_errno,
234     enc_errno_byref
235 );
236 dec_enc_scalar!(
237     __wasi_exitcode_t,
238     dec_exitcode,
239     dec_exitcode_byref,
240     enc_exitcode,
241     enc_exitcode_byref
242 );
243 dec_enc_scalar!(__wasi_fd_t, dec_fd, dec_fd_byref, enc_fd, enc_fd_byref);
244 dec_enc_scalar!(
245     __wasi_fdflags_t,
246     dec_fdflags,
247     dec_fdflags_byref,
248     enc_fdflags,
249     enc_fdflags_byref
250 );
251 dec_enc_scalar!(
252     __wasi_device_t,
253     dec_device,
254     dev_device_byref,
255     enc_device,
256     enc_device_byref
257 );
258 dec_enc_scalar!(
259     __wasi_inode_t,
260     dec_inode,
261     dev_inode_byref,
262     enc_inode,
263     enc_inode_byref
264 );
265 dec_enc_scalar!(
266     __wasi_linkcount_t,
267     dec_linkcount,
268     dev_linkcount_byref,
269     enc_linkcount,
270     enc_linkcount_byref
271 );
272 
dec_filestat(filestat: wasm32::__wasi_filestat_t) -> host::__wasi_filestat_t273 pub fn dec_filestat(filestat: wasm32::__wasi_filestat_t) -> host::__wasi_filestat_t {
274     host::__wasi_filestat_t {
275         st_dev: dec_device(filestat.st_dev),
276         st_ino: dec_inode(filestat.st_ino),
277         st_filetype: dec_filetype(filestat.st_filetype),
278         st_nlink: dec_linkcount(filestat.st_nlink),
279         st_size: dec_filesize(filestat.st_size),
280         st_atim: dec_timestamp(filestat.st_atim),
281         st_mtim: dec_timestamp(filestat.st_mtim),
282         st_ctim: dec_timestamp(filestat.st_ctim),
283     }
284 }
285 
dec_filestat_byref( vmctx: &Vmctx, filestat_ptr: wasm32::uintptr_t, ) -> Result<host::__wasi_filestat_t, host::__wasi_errno_t>286 pub fn dec_filestat_byref(
287     vmctx: &Vmctx,
288     filestat_ptr: wasm32::uintptr_t,
289 ) -> Result<host::__wasi_filestat_t, host::__wasi_errno_t> {
290     dec_pointee::<wasm32::__wasi_filestat_t>(vmctx, filestat_ptr).map(dec_filestat)
291 }
292 
enc_filestat(filestat: host::__wasi_filestat_t) -> wasm32::__wasi_filestat_t293 pub fn enc_filestat(filestat: host::__wasi_filestat_t) -> wasm32::__wasi_filestat_t {
294     wasm32::__wasi_filestat_t {
295         st_dev: enc_device(filestat.st_dev),
296         st_ino: enc_inode(filestat.st_ino),
297         st_filetype: enc_filetype(filestat.st_filetype),
298         st_nlink: enc_linkcount(filestat.st_nlink),
299         st_size: enc_filesize(filestat.st_size),
300         st_atim: enc_timestamp(filestat.st_atim),
301         st_mtim: enc_timestamp(filestat.st_mtim),
302         st_ctim: enc_timestamp(filestat.st_ctim),
303     }
304 }
305 
enc_filestat_byref( vmctx: &Vmctx, filestat_ptr: wasm32::uintptr_t, host_filestat: host::__wasi_filestat_t, ) -> Result<(), host::__wasi_errno_t>306 pub fn enc_filestat_byref(
307     vmctx: &Vmctx,
308     filestat_ptr: wasm32::uintptr_t,
309     host_filestat: host::__wasi_filestat_t,
310 ) -> Result<(), host::__wasi_errno_t> {
311     let filestat = enc_filestat(host_filestat);
312     enc_pointee::<wasm32::__wasi_filestat_t>(vmctx, filestat_ptr, filestat)
313 }
314 
dec_fdstat(fdstat: wasm32::__wasi_fdstat_t) -> host::__wasi_fdstat_t315 pub fn dec_fdstat(fdstat: wasm32::__wasi_fdstat_t) -> host::__wasi_fdstat_t {
316     host::__wasi_fdstat_t {
317         fs_filetype: dec_filetype(fdstat.fs_filetype),
318         fs_flags: dec_fdflags(fdstat.fs_flags),
319         fs_rights_base: dec_rights(fdstat.fs_rights_base),
320         fs_rights_inheriting: dec_rights(fdstat.fs_rights_inheriting),
321     }
322 }
323 
dec_fdstat_byref( vmctx: &Vmctx, fdstat_ptr: wasm32::uintptr_t, ) -> Result<host::__wasi_fdstat_t, host::__wasi_errno_t>324 pub fn dec_fdstat_byref(
325     vmctx: &Vmctx,
326     fdstat_ptr: wasm32::uintptr_t,
327 ) -> Result<host::__wasi_fdstat_t, host::__wasi_errno_t> {
328     dec_pointee::<wasm32::__wasi_fdstat_t>(vmctx, fdstat_ptr).map(dec_fdstat)
329 }
330 
enc_fdstat(fdstat: host::__wasi_fdstat_t) -> wasm32::__wasi_fdstat_t331 pub fn enc_fdstat(fdstat: host::__wasi_fdstat_t) -> wasm32::__wasi_fdstat_t {
332     wasm32::__wasi_fdstat_t {
333         fs_filetype: enc_filetype(fdstat.fs_filetype),
334         fs_flags: enc_fdflags(fdstat.fs_flags),
335         __bindgen_padding_0: 0,
336         fs_rights_base: enc_rights(fdstat.fs_rights_base),
337         fs_rights_inheriting: enc_rights(fdstat.fs_rights_inheriting),
338     }
339 }
340 
enc_fdstat_byref( vmctx: &Vmctx, fdstat_ptr: wasm32::uintptr_t, host_fdstat: host::__wasi_fdstat_t, ) -> Result<(), host::__wasi_errno_t>341 pub fn enc_fdstat_byref(
342     vmctx: &Vmctx,
343     fdstat_ptr: wasm32::uintptr_t,
344     host_fdstat: host::__wasi_fdstat_t,
345 ) -> Result<(), host::__wasi_errno_t> {
346     let fdstat = enc_fdstat(host_fdstat);
347     enc_pointee::<wasm32::__wasi_fdstat_t>(vmctx, fdstat_ptr, fdstat)
348 }
349 
350 dec_enc_scalar!(
351     __wasi_filedelta_t,
352     dec_filedelta,
353     dec_filedelta_byref,
354     enc_filedelta,
355     enc_filedelta_byref
356 );
357 dec_enc_scalar!(
358     __wasi_filesize_t,
359     dec_filesize,
360     dec_filesize_byref,
361     enc_filesize,
362     enc_filesize_byref
363 );
364 
365 dec_enc_scalar!(
366     __wasi_filetype_t,
367     dec_filetype,
368     dec_filetype_byref,
369     enc_filetype,
370     enc_filetype_byref
371 );
372 
373 dec_enc_scalar!(
374     __wasi_lookupflags_t,
375     dec_lookupflags,
376     dec_lookupflags_byref,
377     enc_lookupflags,
378     enc_lookupflags_byref
379 );
380 
381 dec_enc_scalar!(
382     __wasi_oflags_t,
383     dec_oflags,
384     dec_oflags_byref,
385     enc_oflags,
386     enc_oflags_byref
387 );
388 
dec_prestat( prestat: wasm32::__wasi_prestat_t, ) -> Result<host::__wasi_prestat_t, host::__wasi_errno_t>389 pub fn dec_prestat(
390     prestat: wasm32::__wasi_prestat_t,
391 ) -> Result<host::__wasi_prestat_t, host::__wasi_errno_t> {
392     match prestat.pr_type {
393         wasm32::__WASI_PREOPENTYPE_DIR => {
394             let u = host::__wasi_prestat_t___wasi_prestat_u {
395                 dir: host::__wasi_prestat_t___wasi_prestat_u___wasi_prestat_u_dir_t {
396                     pr_name_len: dec_usize(unsafe { prestat.u.dir.pr_name_len }),
397                 },
398             };
399             Ok(host::__wasi_prestat_t {
400                 pr_type: host::__WASI_PREOPENTYPE_DIR as host::__wasi_preopentype_t,
401                 u,
402             })
403         }
404         _ => Err(host::__WASI_EINVAL as host::__wasi_errno_t),
405     }
406 }
407 
dec_prestat_byref( vmctx: &Vmctx, prestat_ptr: wasm32::uintptr_t, ) -> Result<host::__wasi_prestat_t, host::__wasi_errno_t>408 pub fn dec_prestat_byref(
409     vmctx: &Vmctx,
410     prestat_ptr: wasm32::uintptr_t,
411 ) -> Result<host::__wasi_prestat_t, host::__wasi_errno_t> {
412     dec_pointee::<wasm32::__wasi_prestat_t>(vmctx, prestat_ptr).and_then(dec_prestat)
413 }
414 
enc_prestat( prestat: host::__wasi_prestat_t, ) -> Result<wasm32::__wasi_prestat_t, host::__wasi_errno_t>415 pub fn enc_prestat(
416     prestat: host::__wasi_prestat_t,
417 ) -> Result<wasm32::__wasi_prestat_t, host::__wasi_errno_t> {
418     match u32::from(prestat.pr_type) {
419         host::__WASI_PREOPENTYPE_DIR => {
420             let u = wasm32::__wasi_prestat_t___wasi_prestat_u {
421                 dir: wasm32::__wasi_prestat_t___wasi_prestat_u___wasi_prestat_u_dir_t {
422                     pr_name_len: enc_usize(unsafe { prestat.u.dir.pr_name_len }),
423                 },
424             };
425             Ok(wasm32::__wasi_prestat_t {
426                 pr_type: wasm32::__WASI_PREOPENTYPE_DIR as wasm32::__wasi_preopentype_t,
427                 u,
428             })
429         }
430         _ => Err(host::__WASI_EINVAL as host::__wasi_errno_t),
431     }
432 }
433 
enc_prestat_byref( vmctx: &Vmctx, prestat_ptr: wasm32::uintptr_t, host_prestat: host::__wasi_prestat_t, ) -> Result<(), host::__wasi_errno_t>434 pub fn enc_prestat_byref(
435     vmctx: &Vmctx,
436     prestat_ptr: wasm32::uintptr_t,
437     host_prestat: host::__wasi_prestat_t,
438 ) -> Result<(), host::__wasi_errno_t> {
439     let prestat = enc_prestat(host_prestat)?;
440     enc_pointee::<wasm32::__wasi_prestat_t>(vmctx, prestat_ptr, prestat)
441 }
442 
443 dec_enc_scalar!(
444     __wasi_rights_t,
445     dec_rights,
446     dec_rights_byref,
447     enc_rights,
448     enc_rights_byref
449 );
450 
451 dec_enc_scalar!(
452     __wasi_timestamp_t,
453     dec_timestamp,
454     dec_timestamp_byref,
455     enc_timestamp,
456     enc_timestamp_byref
457 );
458 
dec_u32(x: u32) -> u32459 pub fn dec_u32(x: u32) -> u32 {
460     u32::from_le(x)
461 }
462 
enc_u32(x: u32) -> u32463 pub fn enc_u32(x: u32) -> u32 {
464     x.to_le()
465 }
466 
dec_usize(size: wasm32::size_t) -> usize467 pub fn dec_usize(size: wasm32::size_t) -> usize {
468     cast::usize(u32::from_le(size))
469 }
470 
enc_usize(size: usize) -> wasm32::size_t471 pub fn enc_usize(size: usize) -> wasm32::size_t {
472     wasm32::size_t::cast(size).unwrap()
473 }
474 
enc_usize_byref( vmctx: &Vmctx, usize_ptr: wasm32::uintptr_t, host_usize: usize, ) -> Result<(), host::__wasi_errno_t>475 pub fn enc_usize_byref(
476     vmctx: &Vmctx,
477     usize_ptr: wasm32::uintptr_t,
478     host_usize: usize,
479 ) -> Result<(), host::__wasi_errno_t> {
480     enc_pointee::<wasm32::size_t>(vmctx, usize_ptr, enc_usize(host_usize))
481 }
482 
483 dec_enc_scalar!(
484     __wasi_whence_t,
485     dec_whence,
486     dec_whence_byref,
487     enc_whence,
488     enc_whence_byref
489 );
490 
491 dec_enc_scalar!(
492     __wasi_subclockflags_t,
493     dec_subclockflags,
494     dec_subclockflags_byref,
495     enc_subclockflags,
496     enc_subclockflags_byref
497 );
498 
499 dec_enc_scalar!(
500     __wasi_eventrwflags_t,
501     dec_eventrwflags,
502     dec_eventrwflags_byref,
503     enc_eventrwflags,
504     enc_eventrwflags_byref
505 );
506 
507 dec_enc_scalar!(
508     __wasi_eventtype_t,
509     dec_eventtype,
510     dec_eventtype_byref,
511     enc_eventtype,
512     enc_eventtype_byref
513 );
514 
515 dec_enc_scalar!(
516     __wasi_userdata_t,
517     dec_userdata,
518     dec_userdata_byref,
519     enc_userdata,
520     enc_userdata_byref
521 );
522 
dec_subscription( subscription: &wasm32::__wasi_subscription_t, ) -> Result<host::__wasi_subscription_t, host::__wasi_errno_t>523 pub fn dec_subscription(
524     subscription: &wasm32::__wasi_subscription_t,
525 ) -> Result<host::__wasi_subscription_t, host::__wasi_errno_t> {
526     let userdata = dec_userdata(subscription.userdata);
527     let type_ = dec_eventtype(subscription.type_);
528     let u_orig = subscription.__bindgen_anon_1;
529     let u = match type_ {
530         wasm32::__WASI_EVENTTYPE_CLOCK => host::__wasi_subscription_t___wasi_subscription_u {
531             clock: unsafe {
532                 host::__wasi_subscription_t___wasi_subscription_u___wasi_subscription_u_clock_t {
533                     identifier: dec_userdata(u_orig.clock.identifier),
534                     clock_id: dec_clockid(u_orig.clock.clock_id),
535                     timeout: dec_timestamp(u_orig.clock.timeout),
536                     precision: dec_timestamp(u_orig.clock.precision),
537                     flags: dec_subclockflags(u_orig.clock.flags),
538                 }
539             },
540         },
541         wasm32::__WASI_EVENTTYPE_FD_READ | wasm32::__WASI_EVENTTYPE_FD_WRITE =>  host::__wasi_subscription_t___wasi_subscription_u {
542             fd_readwrite:  host::__wasi_subscription_t___wasi_subscription_u___wasi_subscription_u_fd_readwrite_t {
543                 fd: dec_fd(unsafe{u_orig.fd_readwrite.fd})
544             }
545         },
546         _  => return Err(wasm32::__WASI_EINVAL)
547     };
548     Ok(host::__wasi_subscription_t { userdata, type_, u })
549 }
550 
enc_event(event: host::__wasi_event_t) -> wasm32::__wasi_event_t551 pub fn enc_event(event: host::__wasi_event_t) -> wasm32::__wasi_event_t {
552     let fd_readwrite = unsafe { event.u.fd_readwrite };
553     wasm32::__wasi_event_t {
554         userdata: enc_userdata(event.userdata),
555         type_: enc_eventtype(event.type_),
556         error: enc_errno(event.error),
557         __bindgen_anon_1: wasm32::__wasi_event_t__bindgen_ty_1 {
558             fd_readwrite: wasm32::__wasi_event_t__bindgen_ty_1__bindgen_ty_1 {
559                 nbytes: enc_filesize(fd_readwrite.nbytes),
560                 flags: enc_eventrwflags(fd_readwrite.flags),
561                 __bindgen_padding_0: [0; 3],
562             },
563         },
564         __bindgen_padding_0: 0,
565     }
566 }
567 
568 dec_enc_scalar!(
569     __wasi_advice_t,
570     dec_advice,
571     dec_advice_byref,
572     enc_advice,
573     enc_advice_byref
574 );
575 
576 dec_enc_scalar!(
577     __wasi_fstflags_t,
578     dec_fstflags,
579     dec_fstflags_byref,
580     enc_fstflags,
581     enc_fstflags_byref
582 );
583 
584 dec_enc_scalar!(
585     __wasi_dircookie_t,
586     dec_dircookie,
587     dec_dircookie_byref,
588     enc_dircookie,
589     enc_dircookie_byref
590 );
591 
592 #[cfg(target_os = "linux")]
dirent_from_host( host_entry: &nix::libc::dirent, ) -> Result<wasm32::__wasi_dirent_t, host::__wasi_errno_t>593 pub fn dirent_from_host(
594     host_entry: &nix::libc::dirent,
595 ) -> Result<wasm32::__wasi_dirent_t, host::__wasi_errno_t> {
596     let mut entry = unsafe { std::mem::zeroed::<wasm32::__wasi_dirent_t>() };
597     let d_namlen = unsafe { std::ffi::CStr::from_ptr(host_entry.d_name.as_ptr()) }
598         .to_bytes()
599         .len();
600     if d_namlen > u32::max_value() as usize {
601         return Err(host::__WASI_EIO as host::__wasi_errno_t);
602     }
603     entry.d_ino = enc_inode(host_entry.d_ino);
604     entry.d_next = enc_dircookie(host_entry.d_off as u64);
605     entry.d_namlen = enc_u32(d_namlen as u32);
606     entry.d_type = enc_filetype(host_entry.d_type);
607     Ok(entry)
608 }
609 
610 #[cfg(not(target_os = "linux"))]
dirent_from_host( host_entry: &nix::libc::dirent, ) -> Result<wasm32::__wasi_dirent_t, host::__wasi_errno_t>611 pub fn dirent_from_host(
612     host_entry: &nix::libc::dirent,
613 ) -> Result<wasm32::__wasi_dirent_t, host::__wasi_errno_t> {
614     let mut entry = unsafe { std::mem::zeroed::<wasm32::__wasi_dirent_t>() };
615     entry.d_ino = enc_inode(host_entry.d_ino);
616     entry.d_next = enc_dircookie(host_entry.d_seekoff);
617     entry.d_namlen = enc_u32(u32::from(host_entry.d_namlen));
618     entry.d_type = enc_filetype(host_entry.d_type);
619     Ok(entry)
620 }
621