1use spin_factors::anyhow::{self, Result};
2use std::mem;
3use wasmtime::component::{Linker, Resource};
4use wasmtime_wasi::p2::{DynPollable, IoView, WasiImpl, WasiView};
5use wasmtime_wasi::TrappableError;
6
7mod latest {
8 pub use wasmtime_wasi::p2::bindings::*;
9}
10
11mod bindings {
12 use super::latest;
13 pub use super::UdpSocket;
14
15 wasmtime::component::bindgen!({
16 path: "../../wit",
17 world: "wasi:cli/reactor@0.2.0-rc-2023-10-18",
18 async: {
19 only_imports: [
20 "[drop]output-stream",
21 "[drop]input-stream",
22 "[method]descriptor.access-at",
23 "[method]descriptor.advise",
24 "[method]descriptor.change-directory-permissions-at",
25 "[method]descriptor.change-file-permissions-at",
26 "[method]descriptor.create-directory-at",
27 "[method]descriptor.get-flags",
28 "[method]descriptor.get-type",
29 "[method]descriptor.is-same-object",
30 "[method]descriptor.link-at",
31 "[method]descriptor.lock-exclusive",
32 "[method]descriptor.lock-shared",
33 "[method]descriptor.metadata-hash",
34 "[method]descriptor.metadata-hash-at",
35 "[method]descriptor.open-at",
36 "[method]descriptor.read",
37 "[method]descriptor.read-directory",
38 "[method]descriptor.readlink-at",
39 "[method]descriptor.remove-directory-at",
40 "[method]descriptor.rename-at",
41 "[method]descriptor.set-size",
42 "[method]descriptor.set-times",
43 "[method]descriptor.set-times-at",
44 "[method]descriptor.stat",
45 "[method]descriptor.stat-at",
46 "[method]descriptor.symlink-at",
47 "[method]descriptor.sync",
48 "[method]descriptor.sync-data",
49 "[method]descriptor.try-lock-exclusive",
50 "[method]descriptor.try-lock-shared",
51 "[method]descriptor.unlink-file-at",
52 "[method]descriptor.unlock",
53 "[method]descriptor.write",
54 "[method]input-stream.blocking-read",
55 "[method]input-stream.blocking-skip",
56 "[method]output-stream.forward",
57 "[method]output-stream.blocking-splice",
58 "[method]output-stream.blocking-flush",
59 "[method]output-stream.blocking-write",
60 "[method]output-stream.blocking-write-and-flush",
61 "[method]output-stream.blocking-write-zeroes-and-flush",
62 "[method]directory-entry-stream.read-directory-entry",
63 "poll-list",
64 "poll-one",
65
66 "[method]tcp-socket.start-bind",
67 "[method]tcp-socket.start-connect",
68 "[method]udp-socket.finish-connect",
69 "[method]udp-socket.receive",
70 "[method]udp-socket.send",
71 "[method]udp-socket.start-bind",
72 "[method]udp-socket.stream",
73 "[method]outgoing-datagram-stream.send",
74 ],
75 },
76 with: {
77 "wasi:io/poll/pollable": latest::io::poll::Pollable,
78 "wasi:io/streams/input-stream": latest::io::streams::InputStream,
79 "wasi:io/streams/output-stream": latest::io::streams::OutputStream,
80 "wasi:io/streams/error": latest::io::streams::Error,
81 "wasi:filesystem/types/directory-entry-stream": latest::filesystem::types::DirectoryEntryStream,
82 "wasi:filesystem/types/descriptor": latest::filesystem::types::Descriptor,
83 "wasi:cli/terminal-input/terminal-input": latest::cli::terminal_input::TerminalInput,
84 "wasi:cli/terminal-output/terminal-output": latest::cli::terminal_output::TerminalOutput,
85 "wasi:sockets/tcp/tcp-socket": latest::sockets::tcp::TcpSocket,
86 "wasi:sockets/udp/udp-socket": UdpSocket,
87 "wasi:sockets/network/network": latest::sockets::network::Network,
88 "wasi:sockets/ip-name-lookup/resolve-address-stream": latest::sockets::ip_name_lookup::ResolveAddressStream,
89 },
90 trappable_imports: true,
91 });
92}
93
94mod wasi {
95 pub use super::bindings::wasi::{
96 cli0_2_0_rc_2023_10_18 as cli, clocks0_2_0_rc_2023_10_18 as clocks,
97 filesystem0_2_0_rc_2023_10_18 as filesystem, io0_2_0_rc_2023_10_18 as io,
98 random0_2_0_rc_2023_10_18 as random, sockets0_2_0_rc_2023_10_18 as sockets,
99 };
100}
101
102use wasi::cli::terminal_input::TerminalInput;
103use wasi::cli::terminal_output::TerminalOutput;
104use wasi::clocks::monotonic_clock::Instant;
105use wasi::clocks::wall_clock::Datetime;
106use wasi::filesystem::types::{
107 AccessType, Advice, Descriptor, DescriptorFlags, DescriptorStat, DescriptorType,
108 DirectoryEntry, DirectoryEntryStream, Error, ErrorCode as FsErrorCode, Filesize,
109 MetadataHashValue, Modes, NewTimestamp, OpenFlags, PathFlags,
110};
111use wasi::io::streams::{InputStream, OutputStream, StreamError};
112use wasi::sockets::ip_name_lookup::{IpAddress, ResolveAddressStream};
113use wasi::sockets::network::{Ipv4SocketAddress, Ipv6SocketAddress};
114use wasi::sockets::tcp::{
115 ErrorCode as SocketErrorCode, IpAddressFamily, IpSocketAddress, Network, ShutdownType,
116 TcpSocket,
117};
118use wasi::sockets::udp::Datagram;
119
120use crate::WasiImplInner;
121
122pub fn add_to_linker<T>(
123 linker: &mut Linker<T>,
124 closure: fn(&mut T) -> WasiImpl<WasiImplInner<'_>>,
125) -> Result<()>
126where
127 T: Send + 'static,
128{
129 wasi::clocks::monotonic_clock::add_to_linker_get_host(linker, closure)?;
130 wasi::clocks::wall_clock::add_to_linker_get_host(linker, closure)?;
131 wasi::filesystem::types::add_to_linker_get_host(linker, closure)?;
132 wasi::filesystem::preopens::add_to_linker_get_host(linker, closure)?;
133 wasi::io::poll::add_to_linker_get_host(linker, closure)?;
134 wasi::io::streams::add_to_linker_get_host(linker, closure)?;
135 wasi::random::random::add_to_linker_get_host(linker, closure)?;
136 wasi::random::insecure::add_to_linker_get_host(linker, closure)?;
137 wasi::random::insecure_seed::add_to_linker_get_host(linker, closure)?;
138 wasi::cli::exit::add_to_linker_get_host(linker, closure)?;
139 wasi::cli::environment::add_to_linker_get_host(linker, closure)?;
140 wasi::cli::stdin::add_to_linker_get_host(linker, closure)?;
141 wasi::cli::stdout::add_to_linker_get_host(linker, closure)?;
142 wasi::cli::stderr::add_to_linker_get_host(linker, closure)?;
143 wasi::cli::terminal_input::add_to_linker_get_host(linker, closure)?;
144 wasi::cli::terminal_output::add_to_linker_get_host(linker, closure)?;
145 wasi::cli::terminal_stdin::add_to_linker_get_host(linker, closure)?;
146 wasi::cli::terminal_stdout::add_to_linker_get_host(linker, closure)?;
147 wasi::cli::terminal_stderr::add_to_linker_get_host(linker, closure)?;
148 wasi::sockets::tcp::add_to_linker_get_host(linker, closure)?;
149 wasi::sockets::tcp_create_socket::add_to_linker_get_host(linker, closure)?;
150 wasi::sockets::udp::add_to_linker_get_host(linker, closure)?;
151 wasi::sockets::udp_create_socket::add_to_linker_get_host(linker, closure)?;
152 wasi::sockets::instance_network::add_to_linker_get_host(linker, closure)?;
153 wasi::sockets::network::add_to_linker_get_host(linker, closure)?;
154 wasi::sockets::ip_name_lookup::add_to_linker_get_host(linker, closure)?;
155 Ok(())
156}
157
158impl<T> wasi::clocks::monotonic_clock::Host for WasiImpl<T>
159where
160 T: WasiView,
161{
162 fn now(&mut self) -> wasmtime::Result<Instant> {
163 latest::clocks::monotonic_clock::Host::now(self)
164 }
165
166 fn resolution(&mut self) -> wasmtime::Result<Instant> {
167 latest::clocks::monotonic_clock::Host::resolution(self)
168 }
169
170 fn subscribe(
171 &mut self,
172 when: Instant,
173 absolute: bool,
174 ) -> wasmtime::Result<Resource<DynPollable>> {
175 if absolute {
176 latest::clocks::monotonic_clock::Host::subscribe_instant(self, when)
177 } else {
178 latest::clocks::monotonic_clock::Host::subscribe_duration(self, when)
179 }
180 }
181}
182
183impl<T> wasi::clocks::wall_clock::Host for WasiImpl<T>
184where
185 T: WasiView,
186{
187 fn now(&mut self) -> wasmtime::Result<Datetime> {
188 Ok(latest::clocks::wall_clock::Host::now(self)?.into())
189 }
190
191 fn resolution(&mut self) -> wasmtime::Result<Datetime> {
192 Ok(latest::clocks::wall_clock::Host::resolution(self)?.into())
193 }
194}
195
196impl<T> wasi::filesystem::types::Host for WasiImpl<T>
197where
198 T: WasiView,
199{
200 fn filesystem_error_code(
201 &mut self,
202 err: Resource<wasi::filesystem::types::Error>,
203 ) -> wasmtime::Result<Option<FsErrorCode>> {
204 Ok(latest::filesystem::types::Host::filesystem_error_code(self, err)?.map(|e| e.into()))
205 }
206}
207
208impl<T> wasi::filesystem::types::HostDescriptor for WasiImpl<T>
209where
210 T: WasiView,
211{
212 fn read_via_stream(
213 &mut self,
214 self_: Resource<Descriptor>,
215 offset: Filesize,
216 ) -> wasmtime::Result<Result<Resource<InputStream>, FsErrorCode>> {
217 convert_result(latest::filesystem::types::HostDescriptor::read_via_stream(
218 self, self_, offset,
219 ))
220 }
221
222 fn write_via_stream(
223 &mut self,
224 self_: Resource<Descriptor>,
225 offset: Filesize,
226 ) -> wasmtime::Result<Result<Resource<OutputStream>, FsErrorCode>> {
227 convert_result(latest::filesystem::types::HostDescriptor::write_via_stream(
228 self, self_, offset,
229 ))
230 }
231
232 fn append_via_stream(
233 &mut self,
234 self_: Resource<Descriptor>,
235 ) -> wasmtime::Result<Result<Resource<OutputStream>, FsErrorCode>> {
236 convert_result(latest::filesystem::types::HostDescriptor::append_via_stream(self, self_))
237 }
238
239 async fn advise(
240 &mut self,
241 self_: Resource<Descriptor>,
242 offset: Filesize,
243 length: Filesize,
244 advice: Advice,
245 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
246 convert_result(
247 latest::filesystem::types::HostDescriptor::advise(
248 self,
249 self_,
250 offset,
251 length,
252 advice.into(),
253 )
254 .await,
255 )
256 }
257
258 async fn sync_data(
259 &mut self,
260 self_: Resource<Descriptor>,
261 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
262 convert_result(latest::filesystem::types::HostDescriptor::sync_data(self, self_).await)
263 }
264
265 async fn get_flags(
266 &mut self,
267 self_: Resource<Descriptor>,
268 ) -> wasmtime::Result<Result<DescriptorFlags, FsErrorCode>> {
269 convert_result(latest::filesystem::types::HostDescriptor::get_flags(self, self_).await)
270 }
271
272 async fn get_type(
273 &mut self,
274 self_: Resource<Descriptor>,
275 ) -> wasmtime::Result<Result<DescriptorType, FsErrorCode>> {
276 convert_result(latest::filesystem::types::HostDescriptor::get_type(self, self_).await)
277 }
278
279 async fn set_size(
280 &mut self,
281 self_: Resource<Descriptor>,
282 size: Filesize,
283 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
284 convert_result(latest::filesystem::types::HostDescriptor::set_size(self, self_, size).await)
285 }
286
287 async fn set_times(
288 &mut self,
289 self_: Resource<Descriptor>,
290 data_access_timestamp: NewTimestamp,
291 data_modification_timestamp: NewTimestamp,
292 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
293 convert_result(
294 latest::filesystem::types::HostDescriptor::set_times(
295 self,
296 self_,
297 data_access_timestamp.into(),
298 data_modification_timestamp.into(),
299 )
300 .await,
301 )
302 }
303
304 async fn read(
305 &mut self,
306 self_: Resource<Descriptor>,
307 length: Filesize,
308 offset: Filesize,
309 ) -> wasmtime::Result<Result<(Vec<u8>, bool), FsErrorCode>> {
310 convert_result(
311 latest::filesystem::types::HostDescriptor::read(self, self_, length, offset).await,
312 )
313 }
314
315 async fn write(
316 &mut self,
317 self_: Resource<Descriptor>,
318 buffer: Vec<u8>,
319 offset: Filesize,
320 ) -> wasmtime::Result<Result<Filesize, FsErrorCode>> {
321 convert_result(
322 latest::filesystem::types::HostDescriptor::write(self, self_, buffer, offset).await,
323 )
324 }
325
326 async fn read_directory(
327 &mut self,
328 self_: Resource<Descriptor>,
329 ) -> wasmtime::Result<Result<Resource<DirectoryEntryStream>, FsErrorCode>> {
330 convert_result(latest::filesystem::types::HostDescriptor::read_directory(self, self_).await)
331 }
332
333 async fn sync(
334 &mut self,
335 self_: Resource<Descriptor>,
336 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
337 convert_result(latest::filesystem::types::HostDescriptor::sync(self, self_).await)
338 }
339
340 async fn create_directory_at(
341 &mut self,
342 self_: Resource<Descriptor>,
343 path: String,
344 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
345 convert_result(
346 latest::filesystem::types::HostDescriptor::create_directory_at(self, self_, path).await,
347 )
348 }
349
350 async fn stat(
351 &mut self,
352 self_: Resource<Descriptor>,
353 ) -> wasmtime::Result<Result<DescriptorStat, FsErrorCode>> {
354 convert_result(latest::filesystem::types::HostDescriptor::stat(self, self_).await)
355 }
356
357 async fn stat_at(
358 &mut self,
359 self_: Resource<Descriptor>,
360 path_flags: PathFlags,
361 path: String,
362 ) -> wasmtime::Result<Result<DescriptorStat, FsErrorCode>> {
363 convert_result(
364 latest::filesystem::types::HostDescriptor::stat_at(
365 self,
366 self_,
367 path_flags.into(),
368 path,
369 )
370 .await,
371 )
372 }
373
374 async fn set_times_at(
375 &mut self,
376 self_: Resource<Descriptor>,
377 path_flags: PathFlags,
378 path: String,
379 data_access_timestamp: NewTimestamp,
380 data_modification_timestamp: NewTimestamp,
381 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
382 convert_result(
383 latest::filesystem::types::HostDescriptor::set_times_at(
384 self,
385 self_,
386 path_flags.into(),
387 path,
388 data_access_timestamp.into(),
389 data_modification_timestamp.into(),
390 )
391 .await,
392 )
393 }
394
395 async fn link_at(
396 &mut self,
397 self_: Resource<Descriptor>,
398 old_path_flags: PathFlags,
399 old_path: String,
400 new_descriptor: Resource<Descriptor>,
401 new_path: String,
402 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
403 convert_result(
404 latest::filesystem::types::HostDescriptor::link_at(
405 self,
406 self_,
407 old_path_flags.into(),
408 old_path,
409 new_descriptor,
410 new_path,
411 )
412 .await,
413 )
414 }
415
416 async fn open_at(
417 &mut self,
418 self_: Resource<Descriptor>,
419 path_flags: PathFlags,
420 path: String,
421 open_flags: OpenFlags,
422 flags: DescriptorFlags,
423 _modes: Modes,
424 ) -> wasmtime::Result<Result<Resource<Descriptor>, FsErrorCode>> {
425 convert_result(
426 latest::filesystem::types::HostDescriptor::open_at(
427 self,
428 self_,
429 path_flags.into(),
430 path,
431 open_flags.into(),
432 flags.into(),
433 )
434 .await,
435 )
436 }
437
438 async fn readlink_at(
439 &mut self,
440 self_: Resource<Descriptor>,
441 path: String,
442 ) -> wasmtime::Result<Result<String, FsErrorCode>> {
443 convert_result(
444 latest::filesystem::types::HostDescriptor::readlink_at(self, self_, path).await,
445 )
446 }
447
448 async fn remove_directory_at(
449 &mut self,
450 self_: Resource<Descriptor>,
451 path: String,
452 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
453 convert_result(
454 latest::filesystem::types::HostDescriptor::remove_directory_at(self, self_, path).await,
455 )
456 }
457
458 async fn rename_at(
459 &mut self,
460 self_: Resource<Descriptor>,
461 old_path: String,
462 new_descriptor: Resource<Descriptor>,
463 new_path: String,
464 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
465 convert_result(
466 latest::filesystem::types::HostDescriptor::rename_at(
467 self,
468 self_,
469 old_path,
470 new_descriptor,
471 new_path,
472 )
473 .await,
474 )
475 }
476
477 async fn symlink_at(
478 &mut self,
479 self_: Resource<Descriptor>,
480 old_path: String,
481 new_path: String,
482 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
483 convert_result(
484 latest::filesystem::types::HostDescriptor::symlink_at(self, self_, old_path, new_path)
485 .await,
486 )
487 }
488
489 async fn access_at(
490 &mut self,
491 _self_: Resource<Descriptor>,
492 _path_flags: PathFlags,
493 _path: String,
494 _type_: AccessType,
495 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
496 anyhow::bail!("access-at API is no longer supported in the latest snapshot")
497 }
498
499 async fn unlink_file_at(
500 &mut self,
501 self_: Resource<Descriptor>,
502 path: String,
503 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
504 convert_result(
505 latest::filesystem::types::HostDescriptor::unlink_file_at(self, self_, path).await,
506 )
507 }
508
509 async fn change_file_permissions_at(
510 &mut self,
511 _self_: Resource<Descriptor>,
512 _path_flags: PathFlags,
513 _path: String,
514 _modes: Modes,
515 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
516 anyhow::bail!(
517 "change-file-permissions-at API is no longer supported in the latest snapshot"
518 )
519 }
520
521 async fn change_directory_permissions_at(
522 &mut self,
523 _self_: Resource<Descriptor>,
524 _path_flags: PathFlags,
525 _path: String,
526 _modes: Modes,
527 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
528 anyhow::bail!(
529 "change-directory-permissions-at API is no longer supported in the latest snapshot"
530 )
531 }
532
533 async fn lock_shared(
534 &mut self,
535 _self_: Resource<Descriptor>,
536 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
537 anyhow::bail!("lock-shared API is no longer supported in the latest snapshot")
538 }
539
540 async fn lock_exclusive(
541 &mut self,
542 _self_: Resource<Descriptor>,
543 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
544 anyhow::bail!("lock-exclusive API is no longer supported in the latest snapshot")
545 }
546
547 async fn try_lock_shared(
548 &mut self,
549 _self_: Resource<Descriptor>,
550 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
551 anyhow::bail!("try-lock-shared API is no longer supported in the latest snapshot")
552 }
553
554 async fn try_lock_exclusive(
555 &mut self,
556 _self_: Resource<Descriptor>,
557 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
558 anyhow::bail!("try-lock-exclusive API is no longer supported in the latest snapshot")
559 }
560
561 async fn unlock(
562 &mut self,
563 _self_: Resource<Descriptor>,
564 ) -> wasmtime::Result<Result<(), FsErrorCode>> {
565 anyhow::bail!("unlock API is no longer supported in the latest snapshot")
566 }
567
568 async fn is_same_object(
569 &mut self,
570 self_: Resource<Descriptor>,
571 other: Resource<Descriptor>,
572 ) -> wasmtime::Result<bool> {
573 latest::filesystem::types::HostDescriptor::is_same_object(self, self_, other).await
574 }
575
576 async fn metadata_hash(
577 &mut self,
578 self_: Resource<Descriptor>,
579 ) -> wasmtime::Result<Result<MetadataHashValue, FsErrorCode>> {
580 convert_result(latest::filesystem::types::HostDescriptor::metadata_hash(self, self_).await)
581 }
582
583 async fn metadata_hash_at(
584 &mut self,
585 self_: Resource<Descriptor>,
586 path_flags: PathFlags,
587 path: String,
588 ) -> wasmtime::Result<Result<MetadataHashValue, FsErrorCode>> {
589 convert_result(
590 latest::filesystem::types::HostDescriptor::metadata_hash_at(
591 self,
592 self_,
593 path_flags.into(),
594 path,
595 )
596 .await,
597 )
598 }
599
600 fn drop(&mut self, rep: Resource<Descriptor>) -> wasmtime::Result<()> {
601 latest::filesystem::types::HostDescriptor::drop(self, rep)
602 }
603}
604
605impl<T> wasi::filesystem::types::HostDirectoryEntryStream for WasiImpl<T>
606where
607 T: WasiView,
608{
609 async fn read_directory_entry(
610 &mut self,
611 self_: Resource<DirectoryEntryStream>,
612 ) -> wasmtime::Result<Result<Option<DirectoryEntry>, FsErrorCode>> {
613 convert_result(
614 latest::filesystem::types::HostDirectoryEntryStream::read_directory_entry(self, self_)
615 .await
616 .map(|e| e.map(DirectoryEntry::from)),
617 )
618 }
619
620 fn drop(&mut self, rep: Resource<DirectoryEntryStream>) -> wasmtime::Result<()> {
621 latest::filesystem::types::HostDirectoryEntryStream::drop(self, rep)
622 }
623}
624
625impl<T> wasi::filesystem::preopens::Host for WasiImpl<T>
626where
627 T: WasiView,
628{
629 fn get_directories(&mut self) -> wasmtime::Result<Vec<(Resource<Descriptor>, String)>> {
630 latest::filesystem::preopens::Host::get_directories(self)
631 }
632}
633
634impl<T> wasi::io::poll::Host for WasiImpl<T>
635where
636 T: WasiView,
637{
638 async fn poll_list(&mut self, list: Vec<Resource<DynPollable>>) -> wasmtime::Result<Vec<u32>> {
639 latest::io::poll::Host::poll(&mut self.0, list).await
640 }
641
642 async fn poll_one(&mut self, rep: Resource<DynPollable>) -> wasmtime::Result<()> {
643 latest::io::poll::HostPollable::block(&mut self.0, rep).await
644 }
645}
646
647impl<T> wasi::io::poll::HostPollable for WasiImpl<T>
648where
649 T: WasiView,
650{
651 fn drop(&mut self, rep: Resource<DynPollable>) -> wasmtime::Result<()> {
652 latest::io::poll::HostPollable::drop(&mut self.0, rep)
653 }
654}
655
656impl<T> wasi::io::streams::Host for WasiImpl<T> where T: WasiView {}
657
658impl<T> wasi::io::streams::HostError for WasiImpl<T>
659where
660 T: WasiView,
661{
662 fn to_debug_string(&mut self, self_: Resource<Error>) -> wasmtime::Result<String> {
663 latest::io::error::HostError::to_debug_string(&mut self.0, self_)
664 }
665
666 fn drop(&mut self, rep: Resource<Error>) -> wasmtime::Result<()> {
667 latest::io::error::HostError::drop(&mut self.0, rep)
668 }
669}
670
671impl<T> wasi::io::streams::HostInputStream for WasiImpl<T>
672where
673 T: WasiView,
674{
675 fn read(
676 &mut self,
677 self_: Resource<InputStream>,
678 len: u64,
679 ) -> wasmtime::Result<Result<Vec<u8>, StreamError>> {
680 let result = latest::io::streams::HostInputStream::read(&mut self.0, self_, len);
681 convert_stream_result(self, result)
682 }
683
684 async fn blocking_read(
685 &mut self,
686 self_: Resource<InputStream>,
687 len: u64,
688 ) -> wasmtime::Result<Result<Vec<u8>, StreamError>> {
689 let result =
690 latest::io::streams::HostInputStream::blocking_read(&mut self.0, self_, len).await;
691 convert_stream_result(self, result)
692 }
693
694 fn skip(
695 &mut self,
696 self_: Resource<InputStream>,
697 len: u64,
698 ) -> wasmtime::Result<Result<u64, StreamError>> {
699 let result = latest::io::streams::HostInputStream::skip(&mut self.0, self_, len);
700 convert_stream_result(self, result)
701 }
702
703 async fn blocking_skip(
704 &mut self,
705 self_: Resource<InputStream>,
706 len: u64,
707 ) -> wasmtime::Result<Result<u64, StreamError>> {
708 let result =
709 latest::io::streams::HostInputStream::blocking_skip(&mut self.0, self_, len).await;
710 convert_stream_result(self, result)
711 }
712
713 fn subscribe(
714 &mut self,
715 self_: Resource<InputStream>,
716 ) -> wasmtime::Result<Resource<DynPollable>> {
717 latest::io::streams::HostInputStream::subscribe(&mut self.0, self_)
718 }
719
720 async fn drop(&mut self, rep: Resource<InputStream>) -> wasmtime::Result<()> {
721 latest::io::streams::HostInputStream::drop(&mut self.0, rep).await
722 }
723}
724
725impl<T> wasi::io::streams::HostOutputStream for WasiImpl<T>
726where
727 T: WasiView,
728{
729 fn check_write(
730 &mut self,
731 self_: Resource<OutputStream>,
732 ) -> wasmtime::Result<Result<u64, StreamError>> {
733 let result = latest::io::streams::HostOutputStream::check_write(&mut self.0, self_);
734 convert_stream_result(self, result)
735 }
736
737 fn write(
738 &mut self,
739 self_: Resource<OutputStream>,
740 contents: Vec<u8>,
741 ) -> wasmtime::Result<Result<(), StreamError>> {
742 let result = latest::io::streams::HostOutputStream::write(&mut self.0, self_, contents);
743 convert_stream_result(self, result)
744 }
745
746 async fn blocking_write_and_flush(
747 &mut self,
748 self_: Resource<OutputStream>,
749 contents: Vec<u8>,
750 ) -> wasmtime::Result<Result<(), StreamError>> {
751 let result = latest::io::streams::HostOutputStream::blocking_write_and_flush(
752 &mut self.0,
753 self_,
754 contents,
755 )
756 .await;
757 convert_stream_result(self, result)
758 }
759
760 fn flush(
761 &mut self,
762 self_: Resource<OutputStream>,
763 ) -> wasmtime::Result<Result<(), StreamError>> {
764 let result = latest::io::streams::HostOutputStream::flush(&mut self.0, self_);
765 convert_stream_result(self, result)
766 }
767
768 async fn blocking_flush(
769 &mut self,
770 self_: Resource<OutputStream>,
771 ) -> wasmtime::Result<Result<(), StreamError>> {
772 let result =
773 latest::io::streams::HostOutputStream::blocking_flush(&mut self.0, self_).await;
774 convert_stream_result(self, result)
775 }
776
777 fn subscribe(
778 &mut self,
779 self_: Resource<OutputStream>,
780 ) -> wasmtime::Result<Resource<DynPollable>> {
781 latest::io::streams::HostOutputStream::subscribe(&mut self.0, self_)
782 }
783
784 fn write_zeroes(
785 &mut self,
786 self_: Resource<OutputStream>,
787 len: u64,
788 ) -> wasmtime::Result<Result<(), StreamError>> {
789 let result = latest::io::streams::HostOutputStream::write_zeroes(&mut self.0, self_, len);
790 convert_stream_result(self, result)
791 }
792
793 async fn blocking_write_zeroes_and_flush(
794 &mut self,
795 self_: Resource<OutputStream>,
796 len: u64,
797 ) -> wasmtime::Result<Result<(), StreamError>> {
798 let result = latest::io::streams::HostOutputStream::blocking_write_zeroes_and_flush(
799 &mut self.0,
800 self_,
801 len,
802 )
803 .await;
804 convert_stream_result(self, result)
805 }
806
807 fn splice(
808 &mut self,
809 self_: Resource<OutputStream>,
810 src: Resource<InputStream>,
811 len: u64,
812 ) -> wasmtime::Result<Result<u64, StreamError>> {
813 let result = latest::io::streams::HostOutputStream::splice(&mut self.0, self_, src, len);
814 convert_stream_result(self, result)
815 }
816
817 async fn blocking_splice(
818 &mut self,
819 self_: Resource<OutputStream>,
820 src: Resource<InputStream>,
821 len: u64,
822 ) -> wasmtime::Result<Result<u64, StreamError>> {
823 let result =
824 latest::io::streams::HostOutputStream::blocking_splice(&mut self.0, self_, src, len)
825 .await;
826 convert_stream_result(self, result)
827 }
828
829 async fn forward(
830 &mut self,
831 _self_: Resource<OutputStream>,
832 _src: Resource<InputStream>,
833 ) -> wasmtime::Result<Result<u64, StreamError>> {
834 anyhow::bail!("forward API no longer supported")
835 }
836
837 async fn drop(&mut self, rep: Resource<OutputStream>) -> wasmtime::Result<()> {
838 latest::io::streams::HostOutputStream::drop(&mut self.0, rep).await
839 }
840}
841
842impl<T> wasi::random::random::Host for WasiImpl<T>
843where
844 T: WasiView,
845{
846 fn get_random_bytes(&mut self, len: u64) -> wasmtime::Result<Vec<u8>> {
847 latest::random::random::Host::get_random_bytes(self, len)
848 }
849
850 fn get_random_u64(&mut self) -> wasmtime::Result<u64> {
851 latest::random::random::Host::get_random_u64(self)
852 }
853}
854
855impl<T> wasi::random::insecure::Host for WasiImpl<T>
856where
857 T: WasiView,
858{
859 fn get_insecure_random_bytes(&mut self, len: u64) -> wasmtime::Result<Vec<u8>> {
860 latest::random::insecure::Host::get_insecure_random_bytes(self, len)
861 }
862
863 fn get_insecure_random_u64(&mut self) -> wasmtime::Result<u64> {
864 latest::random::insecure::Host::get_insecure_random_u64(self)
865 }
866}
867
868impl<T> wasi::random::insecure_seed::Host for WasiImpl<T>
869where
870 T: WasiView,
871{
872 fn insecure_seed(&mut self) -> wasmtime::Result<(u64, u64)> {
873 latest::random::insecure_seed::Host::insecure_seed(self)
874 }
875}
876
877impl<T> wasi::cli::exit::Host for WasiImpl<T>
878where
879 T: WasiView,
880{
881 fn exit(&mut self, status: Result<(), ()>) -> wasmtime::Result<()> {
882 latest::cli::exit::Host::exit(self, status)
883 }
884}
885
886impl<T> wasi::cli::environment::Host for WasiImpl<T>
887where
888 T: WasiView,
889{
890 fn get_environment(&mut self) -> wasmtime::Result<Vec<(String, String)>> {
891 latest::cli::environment::Host::get_environment(self)
892 }
893
894 fn get_arguments(&mut self) -> wasmtime::Result<Vec<String>> {
895 latest::cli::environment::Host::get_arguments(self)
896 }
897
898 fn initial_cwd(&mut self) -> wasmtime::Result<Option<String>> {
899 latest::cli::environment::Host::initial_cwd(self)
900 }
901}
902
903impl<T> wasi::cli::stdin::Host for WasiImpl<T>
904where
905 T: WasiView,
906{
907 fn get_stdin(&mut self) -> wasmtime::Result<Resource<InputStream>> {
908 latest::cli::stdin::Host::get_stdin(self)
909 }
910}
911
912impl<T> wasi::cli::stdout::Host for WasiImpl<T>
913where
914 T: WasiView,
915{
916 fn get_stdout(&mut self) -> wasmtime::Result<Resource<OutputStream>> {
917 latest::cli::stdout::Host::get_stdout(self)
918 }
919}
920
921impl<T> wasi::cli::stderr::Host for WasiImpl<T>
922where
923 T: WasiView,
924{
925 fn get_stderr(&mut self) -> wasmtime::Result<Resource<OutputStream>> {
926 latest::cli::stderr::Host::get_stderr(self)
927 }
928}
929
930impl<T> wasi::cli::terminal_stdin::Host for WasiImpl<T>
931where
932 T: WasiView,
933{
934 fn get_terminal_stdin(&mut self) -> wasmtime::Result<Option<Resource<TerminalInput>>> {
935 latest::cli::terminal_stdin::Host::get_terminal_stdin(self)
936 }
937}
938
939impl<T> wasi::cli::terminal_stdout::Host for WasiImpl<T>
940where
941 T: WasiView,
942{
943 fn get_terminal_stdout(&mut self) -> wasmtime::Result<Option<Resource<TerminalOutput>>> {
944 latest::cli::terminal_stdout::Host::get_terminal_stdout(self)
945 }
946}
947
948impl<T> wasi::cli::terminal_stderr::Host for WasiImpl<T>
949where
950 T: WasiView,
951{
952 fn get_terminal_stderr(&mut self) -> wasmtime::Result<Option<Resource<TerminalOutput>>> {
953 latest::cli::terminal_stderr::Host::get_terminal_stderr(self)
954 }
955}
956
957impl<T> wasi::cli::terminal_input::Host for WasiImpl<T> where T: WasiView {}
958
959impl<T> wasi::cli::terminal_input::HostTerminalInput for WasiImpl<T>
960where
961 T: WasiView,
962{
963 fn drop(&mut self, rep: Resource<TerminalInput>) -> wasmtime::Result<()> {
964 latest::cli::terminal_input::HostTerminalInput::drop(self, rep)
965 }
966}
967
968impl<T> wasi::cli::terminal_output::Host for WasiImpl<T> where T: WasiView {}
969
970impl<T> wasi::cli::terminal_output::HostTerminalOutput for WasiImpl<T>
971where
972 T: WasiView,
973{
974 fn drop(&mut self, rep: Resource<TerminalOutput>) -> wasmtime::Result<()> {
975 latest::cli::terminal_output::HostTerminalOutput::drop(self, rep)
976 }
977}
978
979impl<T> wasi::sockets::tcp::Host for WasiImpl<T> where T: WasiView {}
980
981impl<T> wasi::sockets::tcp::HostTcpSocket for WasiImpl<T>
982where
983 T: WasiView,
984{
985 async fn start_bind(
986 &mut self,
987 self_: Resource<TcpSocket>,
988 network: Resource<Network>,
989 local_address: IpSocketAddress,
990 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
991 convert_result(
992 latest::sockets::tcp::HostTcpSocket::start_bind(
993 self,
994 self_,
995 network,
996 local_address.into(),
997 )
998 .await,
999 )
1000 }
1001
1002 fn finish_bind(
1003 &mut self,
1004 self_: Resource<TcpSocket>,
1005 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1006 convert_result(latest::sockets::tcp::HostTcpSocket::finish_bind(
1007 self, self_,
1008 ))
1009 }
1010
1011 async fn start_connect(
1012 &mut self,
1013 self_: Resource<TcpSocket>,
1014 network: Resource<Network>,
1015 remote_address: IpSocketAddress,
1016 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1017 convert_result(
1018 latest::sockets::tcp::HostTcpSocket::start_connect(
1019 self,
1020 self_,
1021 network,
1022 remote_address.into(),
1023 )
1024 .await,
1025 )
1026 }
1027
1028 fn finish_connect(
1029 &mut self,
1030 self_: Resource<TcpSocket>,
1031 ) -> wasmtime::Result<Result<(Resource<InputStream>, Resource<OutputStream>), SocketErrorCode>>
1032 {
1033 convert_result(latest::sockets::tcp::HostTcpSocket::finish_connect(
1034 self, self_,
1035 ))
1036 }
1037
1038 fn start_listen(
1039 &mut self,
1040 self_: Resource<TcpSocket>,
1041 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1042 convert_result(latest::sockets::tcp::HostTcpSocket::start_listen(
1043 self, self_,
1044 ))
1045 }
1046
1047 fn finish_listen(
1048 &mut self,
1049 self_: Resource<TcpSocket>,
1050 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1051 convert_result(latest::sockets::tcp::HostTcpSocket::finish_listen(
1052 self, self_,
1053 ))
1054 }
1055
1056 fn accept(
1057 &mut self,
1058 self_: Resource<TcpSocket>,
1059 ) -> wasmtime::Result<
1060 Result<
1061 (
1062 Resource<TcpSocket>,
1063 Resource<InputStream>,
1064 Resource<OutputStream>,
1065 ),
1066 SocketErrorCode,
1067 >,
1068 > {
1069 convert_result(latest::sockets::tcp::HostTcpSocket::accept(self, self_))
1070 }
1071
1072 fn local_address(
1073 &mut self,
1074 self_: Resource<TcpSocket>,
1075 ) -> wasmtime::Result<Result<IpSocketAddress, SocketErrorCode>> {
1076 convert_result(latest::sockets::tcp::HostTcpSocket::local_address(
1077 self, self_,
1078 ))
1079 }
1080
1081 fn remote_address(
1082 &mut self,
1083 self_: Resource<TcpSocket>,
1084 ) -> wasmtime::Result<Result<IpSocketAddress, SocketErrorCode>> {
1085 convert_result(latest::sockets::tcp::HostTcpSocket::remote_address(
1086 self, self_,
1087 ))
1088 }
1089
1090 fn address_family(&mut self, self_: Resource<TcpSocket>) -> wasmtime::Result<IpAddressFamily> {
1091 latest::sockets::tcp::HostTcpSocket::address_family(self, self_).map(|e| e.into())
1092 }
1093
1094 fn ipv6_only(
1095 &mut self,
1096 _self_: Resource<TcpSocket>,
1097 ) -> wasmtime::Result<Result<bool, SocketErrorCode>> {
1098 anyhow::bail!("ipv6-only API no longer supported")
1099 }
1100
1101 fn set_ipv6_only(
1102 &mut self,
1103 _self_: Resource<TcpSocket>,
1104 _value: bool,
1105 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1106 anyhow::bail!("ipv6-only API no longer supported")
1107 }
1108
1109 fn set_listen_backlog_size(
1110 &mut self,
1111 self_: Resource<TcpSocket>,
1112 value: u64,
1113 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1114 convert_result(
1115 latest::sockets::tcp::HostTcpSocket::set_listen_backlog_size(self, self_, value),
1116 )
1117 }
1118
1119 fn keep_alive(
1120 &mut self,
1121 self_: Resource<TcpSocket>,
1122 ) -> wasmtime::Result<Result<bool, SocketErrorCode>> {
1123 convert_result(latest::sockets::tcp::HostTcpSocket::keep_alive_enabled(
1124 self, self_,
1125 ))
1126 }
1127
1128 fn set_keep_alive(
1129 &mut self,
1130 self_: Resource<TcpSocket>,
1131 value: bool,
1132 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1133 convert_result(latest::sockets::tcp::HostTcpSocket::set_keep_alive_enabled(
1134 self, self_, value,
1135 ))
1136 }
1137
1138 fn no_delay(
1139 &mut self,
1140 _self_: Resource<TcpSocket>,
1141 ) -> wasmtime::Result<Result<bool, SocketErrorCode>> {
1142 anyhow::bail!("no-delay API no longer supported")
1143 }
1144
1145 fn set_no_delay(
1146 &mut self,
1147 _self_: Resource<TcpSocket>,
1148 _value: bool,
1149 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1150 anyhow::bail!("set-no-delay API no longer supported")
1151 }
1152
1153 fn unicast_hop_limit(
1154 &mut self,
1155 self_: Resource<TcpSocket>,
1156 ) -> wasmtime::Result<Result<u8, SocketErrorCode>> {
1157 convert_result(latest::sockets::tcp::HostTcpSocket::hop_limit(self, self_))
1158 }
1159
1160 fn set_unicast_hop_limit(
1161 &mut self,
1162 self_: Resource<TcpSocket>,
1163 value: u8,
1164 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1165 convert_result(latest::sockets::tcp::HostTcpSocket::set_hop_limit(
1166 self, self_, value,
1167 ))
1168 }
1169
1170 fn receive_buffer_size(
1171 &mut self,
1172 self_: Resource<TcpSocket>,
1173 ) -> wasmtime::Result<Result<u64, SocketErrorCode>> {
1174 convert_result(latest::sockets::tcp::HostTcpSocket::receive_buffer_size(
1175 self, self_,
1176 ))
1177 }
1178
1179 fn set_receive_buffer_size(
1180 &mut self,
1181 self_: Resource<TcpSocket>,
1182 value: u64,
1183 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1184 convert_result(
1185 latest::sockets::tcp::HostTcpSocket::set_receive_buffer_size(self, self_, value),
1186 )
1187 }
1188
1189 fn send_buffer_size(
1190 &mut self,
1191 self_: Resource<TcpSocket>,
1192 ) -> wasmtime::Result<Result<u64, SocketErrorCode>> {
1193 convert_result(latest::sockets::tcp::HostTcpSocket::send_buffer_size(
1194 self, self_,
1195 ))
1196 }
1197
1198 fn set_send_buffer_size(
1199 &mut self,
1200 self_: Resource<TcpSocket>,
1201 value: u64,
1202 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1203 convert_result(latest::sockets::tcp::HostTcpSocket::set_send_buffer_size(
1204 self, self_, value,
1205 ))
1206 }
1207
1208 fn subscribe(&mut self, self_: Resource<TcpSocket>) -> wasmtime::Result<Resource<DynPollable>> {
1209 latest::sockets::tcp::HostTcpSocket::subscribe(self, self_)
1210 }
1211
1212 fn shutdown(
1213 &mut self,
1214 self_: Resource<TcpSocket>,
1215 shutdown_type: ShutdownType,
1216 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1217 convert_result(latest::sockets::tcp::HostTcpSocket::shutdown(
1218 self,
1219 self_,
1220 shutdown_type.into(),
1221 ))
1222 }
1223
1224 fn drop(&mut self, rep: Resource<TcpSocket>) -> wasmtime::Result<()> {
1225 latest::sockets::tcp::HostTcpSocket::drop(self, rep)
1226 }
1227}
1228
1229impl<T> wasi::sockets::tcp_create_socket::Host for WasiImpl<T>
1230where
1231 T: WasiView,
1232{
1233 fn create_tcp_socket(
1234 &mut self,
1235 address_family: IpAddressFamily,
1236 ) -> wasmtime::Result<Result<Resource<TcpSocket>, SocketErrorCode>> {
1237 convert_result(latest::sockets::tcp_create_socket::Host::create_tcp_socket(
1238 self,
1239 address_family.into(),
1240 ))
1241 }
1242}
1243
1244impl<T> wasi::sockets::udp::Host for WasiImpl<T> where T: WasiView {}
1245
1246pub enum UdpSocket {
1253 Initial(Resource<latest::sockets::udp::UdpSocket>),
1254 Connecting(Resource<latest::sockets::udp::UdpSocket>, IpSocketAddress),
1255 Connected {
1256 socket: Resource<latest::sockets::udp::UdpSocket>,
1257 incoming: Resource<latest::sockets::udp::IncomingDatagramStream>,
1258 outgoing: Resource<latest::sockets::udp::OutgoingDatagramStream>,
1259 },
1260 Dummy,
1261}
1262
1263impl UdpSocket {
1264 async fn finish_connect<T: WasiView>(
1265 table: &mut WasiImpl<T>,
1266 socket: &Resource<UdpSocket>,
1267 explicit: bool,
1268 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1269 let state = table.table().get_mut(socket)?;
1270 let (new_socket, addr) = match mem::replace(state, UdpSocket::Dummy) {
1271 UdpSocket::Initial(socket) if !explicit => (socket, None),
1274 UdpSocket::Connected { .. } if !explicit => return Ok(Ok(())),
1276 UdpSocket::Connecting(socket, addr) if explicit => (socket, Some(addr)),
1278 _ => return Ok(Err(SocketErrorCode::ConcurrencyConflict)),
1279 };
1280 let borrow = Resource::new_borrow(new_socket.rep());
1281 let result = convert_result(
1282 latest::sockets::udp::HostUdpSocket::stream(table, borrow, addr.map(|a| a.into()))
1283 .await,
1284 )?;
1285 let (incoming, outgoing) = match result {
1286 Ok(pair) => pair,
1287 Err(e) => return Ok(Err(e)),
1288 };
1289 *table.table().get_mut(socket)? = UdpSocket::Connected {
1290 socket: new_socket,
1291 incoming,
1292 outgoing,
1293 };
1294 Ok(Ok(()))
1295 }
1296
1297 fn inner(&self) -> wasmtime::Result<Resource<latest::sockets::udp::UdpSocket>> {
1298 let r = match self {
1299 UdpSocket::Initial(r) => r,
1300 UdpSocket::Connecting(r, _) => r,
1301 UdpSocket::Connected { socket, .. } => socket,
1302 UdpSocket::Dummy => anyhow::bail!("invalid udp socket state"),
1303 };
1304 Ok(Resource::new_borrow(r.rep()))
1305 }
1306}
1307
1308impl<T> wasi::sockets::udp::HostUdpSocket for WasiImpl<T>
1309where
1310 T: WasiView,
1311{
1312 async fn start_bind(
1313 &mut self,
1314 self_: Resource<UdpSocket>,
1315 network: Resource<Network>,
1316 local_address: IpSocketAddress,
1317 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1318 let socket = self.table().get(&self_)?.inner()?;
1319 convert_result(
1320 latest::sockets::udp::HostUdpSocket::start_bind(
1321 self,
1322 socket,
1323 network,
1324 local_address.into(),
1325 )
1326 .await,
1327 )
1328 }
1329
1330 fn finish_bind(
1331 &mut self,
1332 self_: Resource<UdpSocket>,
1333 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1334 let socket = self.table().get(&self_)?.inner()?;
1335 convert_result(latest::sockets::udp::HostUdpSocket::finish_bind(
1336 self, socket,
1337 ))
1338 }
1339
1340 fn start_connect(
1341 &mut self,
1342 self_: Resource<UdpSocket>,
1343 _network: Resource<Network>,
1344 remote_address: IpSocketAddress,
1345 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1346 let socket = self.table().get_mut(&self_)?;
1347 let (new_state, result) = match mem::replace(socket, UdpSocket::Dummy) {
1348 UdpSocket::Initial(socket) => (UdpSocket::Connecting(socket, remote_address), Ok(())),
1349 other => (other, Err(SocketErrorCode::ConcurrencyConflict)),
1350 };
1351 *socket = new_state;
1352 Ok(result)
1353 }
1354
1355 async fn finish_connect(
1356 &mut self,
1357 self_: Resource<UdpSocket>,
1358 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1359 UdpSocket::finish_connect(self, &self_, true).await
1360 }
1361
1362 async fn receive(
1363 &mut self,
1364 self_: Resource<UdpSocket>,
1365 max_results: u64,
1366 ) -> wasmtime::Result<Result<Vec<Datagram>, SocketErrorCode>> {
1367 if let Err(e) = UdpSocket::finish_connect(self, &self_, true).await? {
1370 return Ok(Err(e));
1371 }
1372
1373 let incoming = match self.table().get(&self_)? {
1376 UdpSocket::Connected { incoming, .. } => Resource::new_borrow(incoming.rep()),
1377 _ => return Ok(Err(SocketErrorCode::ConcurrencyConflict)),
1378 };
1379 let result: Result<Vec<_>, _> = convert_result(
1380 latest::sockets::udp::HostIncomingDatagramStream::receive(self, incoming, max_results),
1381 )?;
1382 match result {
1383 Ok(datagrams) => Ok(Ok(datagrams
1384 .into_iter()
1385 .map(|datagram| datagram.into())
1386 .collect())),
1387 Err(e) => Ok(Err(e)),
1388 }
1389 }
1390
1391 async fn send(
1392 &mut self,
1393 self_: Resource<UdpSocket>,
1394 mut datagrams: Vec<Datagram>,
1395 ) -> wasmtime::Result<Result<u64, SocketErrorCode>> {
1396 if let Err(e) = UdpSocket::finish_connect(self, &self_, true).await? {
1399 return Ok(Err(e));
1400 }
1401
1402 let outgoing = match self.table().get(&self_)? {
1405 UdpSocket::Connected { outgoing, .. } => Resource::new_borrow(outgoing.rep()),
1406 _ => return Ok(Err(SocketErrorCode::ConcurrencyConflict)),
1407 };
1408
1409 let outgoing2 = Resource::new_borrow(outgoing.rep());
1412 match convert_result(
1413 latest::sockets::udp::HostOutgoingDatagramStream::check_send(self, outgoing2),
1414 )? {
1415 Ok(n) => {
1416 if datagrams.len() as u64 > n {
1417 datagrams.truncate(n as usize);
1418 }
1419 }
1420 Err(e) => return Ok(Err(e)),
1421 }
1422
1423 convert_result(
1425 latest::sockets::udp::HostOutgoingDatagramStream::send(
1426 self,
1427 outgoing,
1428 datagrams
1429 .into_iter()
1430 .map(|d| latest::sockets::udp::OutgoingDatagram {
1431 data: d.data,
1432 remote_address: Some(d.remote_address.into()),
1433 })
1434 .collect(),
1435 )
1436 .await,
1437 )
1438 }
1439
1440 fn local_address(
1441 &mut self,
1442 self_: Resource<UdpSocket>,
1443 ) -> wasmtime::Result<Result<IpSocketAddress, SocketErrorCode>> {
1444 let socket = self.table().get(&self_)?.inner()?;
1445 convert_result(latest::sockets::udp::HostUdpSocket::local_address(
1446 self, socket,
1447 ))
1448 }
1449
1450 fn remote_address(
1451 &mut self,
1452 self_: Resource<UdpSocket>,
1453 ) -> wasmtime::Result<Result<IpSocketAddress, SocketErrorCode>> {
1454 let socket = self.table().get(&self_)?.inner()?;
1455 convert_result(latest::sockets::udp::HostUdpSocket::remote_address(
1456 self, socket,
1457 ))
1458 }
1459
1460 fn address_family(&mut self, self_: Resource<UdpSocket>) -> wasmtime::Result<IpAddressFamily> {
1461 let socket = self.table().get(&self_)?.inner()?;
1462 latest::sockets::udp::HostUdpSocket::address_family(self, socket).map(|e| e.into())
1463 }
1464
1465 fn ipv6_only(
1466 &mut self,
1467 _self_: Resource<UdpSocket>,
1468 ) -> wasmtime::Result<Result<bool, SocketErrorCode>> {
1469 anyhow::bail!("ipv6-only API no longer supported")
1470 }
1471
1472 fn set_ipv6_only(
1473 &mut self,
1474 _self_: Resource<UdpSocket>,
1475 _value: bool,
1476 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1477 anyhow::bail!("ipv6-only API no longer supported")
1478 }
1479
1480 fn unicast_hop_limit(
1481 &mut self,
1482 self_: Resource<UdpSocket>,
1483 ) -> wasmtime::Result<Result<u8, SocketErrorCode>> {
1484 let socket = self.table().get(&self_)?.inner()?;
1485 convert_result(latest::sockets::udp::HostUdpSocket::unicast_hop_limit(
1486 self, socket,
1487 ))
1488 }
1489
1490 fn set_unicast_hop_limit(
1491 &mut self,
1492 self_: Resource<UdpSocket>,
1493 value: u8,
1494 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1495 let socket = self.table().get(&self_)?.inner()?;
1496 convert_result(latest::sockets::udp::HostUdpSocket::set_unicast_hop_limit(
1497 self, socket, value,
1498 ))
1499 }
1500
1501 fn receive_buffer_size(
1502 &mut self,
1503 self_: Resource<UdpSocket>,
1504 ) -> wasmtime::Result<Result<u64, SocketErrorCode>> {
1505 let socket = self.table().get(&self_)?.inner()?;
1506 convert_result(latest::sockets::udp::HostUdpSocket::receive_buffer_size(
1507 self, socket,
1508 ))
1509 }
1510
1511 fn set_receive_buffer_size(
1512 &mut self,
1513 self_: Resource<UdpSocket>,
1514 value: u64,
1515 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1516 let socket = self.table().get(&self_)?.inner()?;
1517 convert_result(
1518 latest::sockets::udp::HostUdpSocket::set_receive_buffer_size(self, socket, value),
1519 )
1520 }
1521
1522 fn send_buffer_size(
1523 &mut self,
1524 self_: Resource<UdpSocket>,
1525 ) -> wasmtime::Result<Result<u64, SocketErrorCode>> {
1526 let socket = self.table().get(&self_)?.inner()?;
1527 convert_result(latest::sockets::udp::HostUdpSocket::send_buffer_size(
1528 self, socket,
1529 ))
1530 }
1531
1532 fn set_send_buffer_size(
1533 &mut self,
1534 self_: Resource<UdpSocket>,
1535 value: u64,
1536 ) -> wasmtime::Result<Result<(), SocketErrorCode>> {
1537 let socket = self.table().get(&self_)?.inner()?;
1538 convert_result(latest::sockets::udp::HostUdpSocket::set_send_buffer_size(
1539 self, socket, value,
1540 ))
1541 }
1542
1543 fn subscribe(&mut self, self_: Resource<UdpSocket>) -> wasmtime::Result<Resource<DynPollable>> {
1544 let socket = self.table().get(&self_)?.inner()?;
1545 latest::sockets::udp::HostUdpSocket::subscribe(self, socket)
1546 }
1547
1548 fn drop(&mut self, rep: Resource<UdpSocket>) -> wasmtime::Result<()> {
1549 let me = self.table().delete(rep)?;
1550 let socket = match me {
1551 UdpSocket::Initial(s) => s,
1552 UdpSocket::Connecting(s, _) => s,
1553 UdpSocket::Connected {
1554 socket,
1555 incoming,
1556 outgoing,
1557 } => {
1558 latest::sockets::udp::HostIncomingDatagramStream::drop(self, incoming)?;
1559 latest::sockets::udp::HostOutgoingDatagramStream::drop(self, outgoing)?;
1560 socket
1561 }
1562 UdpSocket::Dummy => return Ok(()),
1563 };
1564 latest::sockets::udp::HostUdpSocket::drop(self, socket)
1565 }
1566}
1567
1568impl<T> wasi::sockets::udp_create_socket::Host for WasiImpl<T>
1569where
1570 T: WasiView,
1571{
1572 fn create_udp_socket(
1573 &mut self,
1574 address_family: IpAddressFamily,
1575 ) -> wasmtime::Result<Result<Resource<UdpSocket>, SocketErrorCode>> {
1576 let result = convert_result(latest::sockets::udp_create_socket::Host::create_udp_socket(
1577 self,
1578 address_family.into(),
1579 ))?;
1580 let socket = match result {
1581 Ok(socket) => socket,
1582 Err(e) => return Ok(Err(e)),
1583 };
1584 let socket = self.table().push(UdpSocket::Initial(socket))?;
1585 Ok(Ok(socket))
1586 }
1587}
1588
1589impl<T> wasi::sockets::instance_network::Host for WasiImpl<T>
1590where
1591 T: WasiView,
1592{
1593 fn instance_network(&mut self) -> wasmtime::Result<Resource<Network>> {
1594 latest::sockets::instance_network::Host::instance_network(self)
1595 }
1596}
1597
1598impl<T> wasi::sockets::network::Host for WasiImpl<T> where T: WasiView {}
1599
1600impl<T> wasi::sockets::network::HostNetwork for WasiImpl<T>
1601where
1602 T: WasiView,
1603{
1604 fn drop(&mut self, rep: Resource<Network>) -> wasmtime::Result<()> {
1605 latest::sockets::network::HostNetwork::drop(self, rep)
1606 }
1607}
1608
1609impl<T> wasi::sockets::ip_name_lookup::Host for WasiImpl<T>
1610where
1611 T: WasiView,
1612{
1613 fn resolve_addresses(
1614 &mut self,
1615 network: Resource<Network>,
1616 name: String,
1617 _address_family: Option<IpAddressFamily>,
1618 _include_unavailable: bool,
1619 ) -> wasmtime::Result<Result<Resource<ResolveAddressStream>, SocketErrorCode>> {
1620 convert_result(latest::sockets::ip_name_lookup::Host::resolve_addresses(
1621 self, network, name,
1622 ))
1623 }
1624}
1625
1626impl<T> wasi::sockets::ip_name_lookup::HostResolveAddressStream for WasiImpl<T>
1627where
1628 T: WasiView,
1629{
1630 fn resolve_next_address(
1631 &mut self,
1632 self_: Resource<ResolveAddressStream>,
1633 ) -> wasmtime::Result<Result<Option<IpAddress>, SocketErrorCode>> {
1634 convert_result(
1635 latest::sockets::ip_name_lookup::HostResolveAddressStream::resolve_next_address(
1636 self, self_,
1637 )
1638 .map(|e| e.map(|e| e.into())),
1639 )
1640 }
1641
1642 fn subscribe(
1643 &mut self,
1644 self_: Resource<ResolveAddressStream>,
1645 ) -> wasmtime::Result<Resource<DynPollable>> {
1646 latest::sockets::ip_name_lookup::HostResolveAddressStream::subscribe(self, self_)
1647 }
1648
1649 fn drop(&mut self, rep: Resource<ResolveAddressStream>) -> wasmtime::Result<()> {
1650 latest::sockets::ip_name_lookup::HostResolveAddressStream::drop(self, rep)
1651 }
1652}
1653
1654pub fn convert_result<T, T2, E, E2>(
1655 result: Result<T, TrappableError<E>>,
1656) -> wasmtime::Result<Result<T2, E2>>
1657where
1658 T2: From<T>,
1659 E: std::error::Error + Send + Sync + 'static,
1660 E2: From<E>,
1661{
1662 match result {
1663 Ok(e) => Ok(Ok(e.into())),
1664 Err(e) => Ok(Err(e.downcast()?.into())),
1665 }
1666}
1667
1668fn convert_stream_result<T, T2>(
1669 mut view: impl WasiView,
1670 result: Result<T, wasmtime_wasi::p2::StreamError>,
1671) -> wasmtime::Result<Result<T2, StreamError>>
1672where
1673 T2: From<T>,
1674{
1675 match result {
1676 Ok(e) => Ok(Ok(e.into())),
1677 Err(wasmtime_wasi::p2::StreamError::Closed) => Ok(Err(StreamError::Closed)),
1678 Err(wasmtime_wasi::p2::StreamError::LastOperationFailed(e)) => {
1679 let e = view.table().push(e)?;
1680 Ok(Err(StreamError::LastOperationFailed(e)))
1681 }
1682 Err(wasmtime_wasi::p2::StreamError::Trap(e)) => Err(e),
1683 }
1684}
1685
1686macro_rules! convert {
1687 () => {};
1688 ($kind:ident $from:path [<=>] $to:path { $($body:tt)* } $($rest:tt)*) => {
1689 convert!($kind $from => $to { $($body)* });
1690 convert!($kind $to => $from { $($body)* });
1691
1692 convert!($($rest)*);
1693 };
1694 (struct $from:ty => $to:path { $($field:ident,)* } $($rest:tt)*) => {
1695 impl From<$from> for $to {
1696 fn from(e: $from) -> $to {
1697 $to {
1698 $( $field: e.$field.into(), )*
1699 }
1700 }
1701 }
1702
1703 convert!($($rest)*);
1704 };
1705 (enum $from:path => $to:path { $($variant:ident $(($e:ident))?,)* } $($rest:tt)*) => {
1706 impl From<$from> for $to {
1707 fn from(e: $from) -> $to {
1708 use $from as A;
1709 use $to as B;
1710 match e {
1711 $(
1712 A::$variant $(($e))? => B::$variant $(($e.into()))?,
1713 )*
1714 }
1715 }
1716 }
1717
1718 convert!($($rest)*);
1719 };
1720 (flags $from:path => $to:path { $($flag:ident,)* } $($rest:tt)*) => {
1721 impl From<$from> for $to {
1722 fn from(e: $from) -> $to {
1723 use $from as A;
1724 use $to as B;
1725 let mut out = B::empty();
1726 $(
1727 if e.contains(A::$flag) {
1728 out |= B::$flag;
1729 }
1730 )*
1731 out
1732 }
1733 }
1734
1735 convert!($($rest)*);
1736 };
1737}
1738
1739pub(crate) use convert;
1740
1741convert! {
1742 struct latest::clocks::wall_clock::Datetime [<=>] Datetime {
1743 seconds,
1744 nanoseconds,
1745 }
1746
1747 enum latest::filesystem::types::ErrorCode => FsErrorCode {
1748 Access,
1749 WouldBlock,
1750 Already,
1751 BadDescriptor,
1752 Busy,
1753 Deadlock,
1754 Quota,
1755 Exist,
1756 FileTooLarge,
1757 IllegalByteSequence,
1758 InProgress,
1759 Interrupted,
1760 Invalid,
1761 Io,
1762 IsDirectory,
1763 Loop,
1764 TooManyLinks,
1765 MessageSize,
1766 NameTooLong,
1767 NoDevice,
1768 NoEntry,
1769 NoLock,
1770 InsufficientMemory,
1771 InsufficientSpace,
1772 NotDirectory,
1773 NotEmpty,
1774 NotRecoverable,
1775 Unsupported,
1776 NoTty,
1777 NoSuchDevice,
1778 Overflow,
1779 NotPermitted,
1780 Pipe,
1781 ReadOnly,
1782 InvalidSeek,
1783 TextFileBusy,
1784 CrossDevice,
1785 }
1786
1787 enum Advice => latest::filesystem::types::Advice {
1788 Normal,
1789 Sequential,
1790 Random,
1791 WillNeed,
1792 DontNeed,
1793 NoReuse,
1794 }
1795
1796 flags DescriptorFlags [<=>] latest::filesystem::types::DescriptorFlags {
1797 READ,
1798 WRITE,
1799 FILE_INTEGRITY_SYNC,
1800 DATA_INTEGRITY_SYNC,
1801 REQUESTED_WRITE_SYNC,
1802 MUTATE_DIRECTORY,
1803 }
1804
1805 enum DescriptorType [<=>] latest::filesystem::types::DescriptorType {
1806 Unknown,
1807 BlockDevice,
1808 CharacterDevice,
1809 Directory,
1810 Fifo,
1811 SymbolicLink,
1812 RegularFile,
1813 Socket,
1814 }
1815
1816 enum NewTimestamp => latest::filesystem::types::NewTimestamp {
1817 NoChange,
1818 Now,
1819 Timestamp(e),
1820 }
1821
1822 flags PathFlags => latest::filesystem::types::PathFlags {
1823 SYMLINK_FOLLOW,
1824 }
1825
1826 flags OpenFlags => latest::filesystem::types::OpenFlags {
1827 CREATE,
1828 DIRECTORY,
1829 EXCLUSIVE,
1830 TRUNCATE,
1831 }
1832
1833 struct latest::filesystem::types::MetadataHashValue => MetadataHashValue {
1834 lower,
1835 upper,
1836 }
1837
1838 struct latest::filesystem::types::DirectoryEntry => DirectoryEntry {
1839 type_,
1840 name,
1841 }
1842
1843 enum latest::sockets::network::ErrorCode => SocketErrorCode {
1844 Unknown,
1845 AccessDenied,
1846 NotSupported,
1847 InvalidArgument,
1848 OutOfMemory,
1849 Timeout,
1850 ConcurrencyConflict,
1851 NotInProgress,
1852 WouldBlock,
1853 InvalidState,
1854 NewSocketLimit,
1855 AddressNotBindable,
1856 AddressInUse,
1857 RemoteUnreachable,
1858 ConnectionRefused,
1859 ConnectionReset,
1860 ConnectionAborted,
1861 DatagramTooLarge,
1862 NameUnresolvable,
1863 TemporaryResolverFailure,
1864 PermanentResolverFailure,
1865 }
1866
1867 enum latest::sockets::network::IpAddress [<=>] IpAddress {
1868 Ipv4(e),
1869 Ipv6(e),
1870 }
1871
1872 enum latest::sockets::network::IpSocketAddress [<=>] IpSocketAddress {
1873 Ipv4(e),
1874 Ipv6(e),
1875 }
1876
1877 struct latest::sockets::network::Ipv4SocketAddress [<=>] Ipv4SocketAddress {
1878 port,
1879 address,
1880 }
1881
1882 struct latest::sockets::network::Ipv6SocketAddress [<=>] Ipv6SocketAddress {
1883 port,
1884 flow_info,
1885 scope_id,
1886 address,
1887 }
1888
1889 enum latest::sockets::network::IpAddressFamily [<=>] IpAddressFamily {
1890 Ipv4,
1891 Ipv6,
1892 }
1893
1894 enum ShutdownType => latest::sockets::tcp::ShutdownType {
1895 Receive,
1896 Send,
1897 Both,
1898 }
1899
1900 struct latest::sockets::udp::IncomingDatagram => Datagram {
1901 data,
1902 remote_address,
1903 }
1904}
1905
1906impl From<latest::filesystem::types::DescriptorStat> for DescriptorStat {
1907 fn from(e: latest::filesystem::types::DescriptorStat) -> DescriptorStat {
1908 DescriptorStat {
1909 type_: e.type_.into(),
1910 link_count: e.link_count,
1911 size: e.size,
1912 data_access_timestamp: e.data_access_timestamp.map(|e| e.into()),
1913 data_modification_timestamp: e.data_modification_timestamp.map(|e| e.into()),
1914 status_change_timestamp: e.status_change_timestamp.map(|e| e.into()),
1915 }
1916 }
1917}