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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use crate::poll::Pollable;
use crate::streams::{InputStream, OutputStream, StreamError};
use crate::WasiHttp;
use anyhow::{anyhow, bail};
use std::vec::Vec;

impl crate::streams::Host for WasiHttp {
    fn read(
        &mut self,
        stream: InputStream,
        len: u64,
    ) -> wasmtime::Result<Result<(Vec<u8>, bool), StreamError>> {
        let st = self
            .streams
            .get_mut(&stream)
            .ok_or_else(|| anyhow!("stream not found: {stream}"))?;
        if st.closed {
            bail!("stream is dropped!");
        }
        let s = &mut st.data;
        if len == 0 {
            Ok(Ok((bytes::Bytes::new().to_vec(), s.len() > 0)))
        } else if s.len() > len.try_into()? {
            let result = s.split_to(len.try_into()?);
            Ok(Ok((result.to_vec(), false)))
        } else {
            s.truncate(s.len());
            Ok(Ok((s.clone().to_vec(), true)))
        }
    }

    fn skip(
        &mut self,
        stream: InputStream,
        len: u64,
    ) -> wasmtime::Result<Result<(u64, bool), StreamError>> {
        let st = self
            .streams
            .get_mut(&stream)
            .ok_or_else(|| anyhow!("stream not found: {stream}"))?;
        if st.closed {
            bail!("stream is dropped!");
        }
        let s = &mut st.data;
        if len == 0 {
            Ok(Ok((0, s.len() > 0)))
        } else if s.len() > len.try_into()? {
            s.truncate(len.try_into()?);
            Ok(Ok((len, false)))
        } else {
            let bytes = s.len();
            s.truncate(s.len());
            Ok(Ok((bytes.try_into()?, true)))
        }
    }

    fn subscribe_to_input_stream(&mut self, _this: InputStream) -> wasmtime::Result<Pollable> {
        bail!("unimplemented: subscribe_to_input_stream");
    }

    fn drop_input_stream(&mut self, stream: InputStream) -> wasmtime::Result<()> {
        let st = self
            .streams
            .get_mut(&stream)
            .ok_or_else(|| anyhow!("stream not found: {stream}"))?;
        st.closed = true;
        Ok(())
    }

    fn write(
        &mut self,
        this: OutputStream,
        buf: Vec<u8>,
    ) -> wasmtime::Result<Result<u64, StreamError>> {
        let len = buf.len();
        let st = self.streams.entry(this).or_default();
        if st.closed {
            bail!("cannot write to closed stream");
        }
        st.data.extend_from_slice(buf.as_slice());
        Ok(Ok(len.try_into()?))
    }

    fn write_zeroes(
        &mut self,
        this: OutputStream,
        len: u64,
    ) -> wasmtime::Result<Result<u64, StreamError>> {
        let mut data = Vec::with_capacity(len.try_into()?);
        let mut i = 0;
        while i < len {
            data.push(0);
            i = i + 1;
        }
        self.write(this, data)
    }

    fn splice(
        &mut self,
        _this: OutputStream,
        _src: InputStream,
        _len: u64,
    ) -> wasmtime::Result<Result<(u64, bool), StreamError>> {
        bail!("unimplemented: splice");
    }

    fn forward(
        &mut self,
        _this: OutputStream,
        _src: InputStream,
    ) -> wasmtime::Result<Result<u64, StreamError>> {
        bail!("unimplemented: forward");
    }

    fn subscribe_to_output_stream(&mut self, _this: OutputStream) -> wasmtime::Result<Pollable> {
        bail!("unimplemented: subscribe_to_output_stream");
    }

    fn drop_output_stream(&mut self, stream: OutputStream) -> wasmtime::Result<()> {
        let st = self
            .streams
            .get_mut(&stream)
            .ok_or_else(|| anyhow!("stream not found: {stream}"))?;
        st.closed = true;
        Ok(())
    }
}