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