1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use std::{
    fmt::Debug,
    io::{stderr, stdin, stdout, IoSlice, IoSliceMut, Read, Write},
};
use wasihost_core::wasi_snapshot_preview1::{Size, WasiResult};

/// Describes a character device.
pub trait CharacterDevice: Debug + Send + Sync + 'static {
    /// Reads data from the character device into `iovs`.
    fn read(&self, iovs: &mut [IoSliceMut<'_>]) -> WasiResult<Size>;
    /// Writes data from `bufs` to the character device.
    fn write(&self, bufs: &[IoSlice<'_>]) -> WasiResult<Size>;
}

/// The host's standard input.
#[derive(Debug)]
pub struct Stdin;

impl CharacterDevice for Stdin {
    fn read(&self, iovs: &mut [IoSliceMut<'_>]) -> WasiResult<Size> {
        Ok(stdin().lock().read_vectored(iovs).map(|s| Size(s as u32))?)
    }

    fn write(&self, _bufs: &[IoSlice<'_>]) -> WasiResult<Size> {
        Ok(Size(0))
    }
}

/// The host's standard output.
#[derive(Debug)]
pub struct Stdout;

impl CharacterDevice for Stdout {
    fn read(&self, _iovs: &mut [IoSliceMut<'_>]) -> WasiResult<Size> {
        Ok(Size(0))
    }

    fn write(&self, bufs: &[IoSlice<'_>]) -> WasiResult<Size> {
        Ok(stdout()
            .lock()
            .write_vectored(bufs)
            .map(|s| Size(s as u32))?)
    }
}

/// The host's standard error.
#[derive(Debug)]
pub struct Stderr;

impl CharacterDevice for Stderr {
    fn read(&self, _iovs: &mut [IoSliceMut<'_>]) -> WasiResult<Size> {
        Ok(Size(0))
    }

    fn write(&self, bufs: &[IoSlice<'_>]) -> WasiResult<Size> {
        Ok(stderr()
            .lock()
            .write_vectored(bufs)
            .map(|s| Size(s as u32))?)
    }
}