viceroy_lib/wiggle_abi/
body_impl.rs

1//! fastly_body` hostcall implementations.
2
3use http::{HeaderName, HeaderValue};
4
5use crate::wiggle_abi::headers::HttpHeaders;
6
7use {
8    crate::{
9        body::Body,
10        error::Error,
11        session::Session,
12        wiggle_abi::{
13            fastly_http_body::FastlyHttpBody,
14            types::{
15                BodyHandle, BodyLength, BodyWriteEnd, MultiValueCursor, MultiValueCursorResult,
16            },
17        },
18    },
19    std::convert::TryInto,
20    wiggle::{GuestMemory, GuestPtr},
21};
22
23#[wiggle::async_trait]
24impl FastlyHttpBody for Session {
25    async fn append(
26        &mut self,
27        _memory: &mut GuestMemory<'_>,
28        dest: BodyHandle,
29        src: BodyHandle,
30    ) -> Result<(), Error> {
31        // Take the `src` body out of the session, and get a mutable reference
32        // to the `dest` body we will append to.
33        let mut src = self.take_body(src)?;
34        let trailers = std::mem::take(&mut src.trailers);
35
36        if self.is_streaming_body(dest) {
37            let dest = self.streaming_body_mut(dest)?;
38            for chunk in src {
39                dest.send_chunk(chunk).await?;
40            }
41            dest.trailers.extend(trailers);
42        } else {
43            let dest = self.body_mut(dest)?;
44            dest.trailers.extend(trailers);
45            dest.append(src);
46        }
47        Ok(())
48    }
49
50    fn new(&mut self, _memory: &mut GuestMemory<'_>) -> Result<BodyHandle, Error> {
51        Ok(self.insert_body(Body::empty()))
52    }
53
54    async fn read(
55        &mut self,
56        memory: &mut GuestMemory<'_>,
57        body_handle: BodyHandle,
58        buf: GuestPtr<u8>,
59        buf_len: u32,
60    ) -> Result<u32, Error> {
61        // only normal bodies (not streaming bodies) can be read from
62        let body = self.body_mut(body_handle)?;
63
64        let array = buf.as_array(buf_len);
65        let slice = memory.as_slice_mut(array)?.ok_or(Error::SharedMemory)?;
66        let n = body
67            .read(slice)
68            .await?
69            .try_into()
70            .expect("guest buffer size must be less than u32");
71        Ok(n)
72    }
73
74    async fn write(
75        &mut self,
76        memory: &mut GuestMemory<'_>,
77        body_handle: BodyHandle,
78        buf: GuestPtr<[u8]>,
79        end: BodyWriteEnd,
80    ) -> Result<u32, Error> {
81        // Validate the body handle and the buffer.
82        let buf = memory.as_slice(buf)?.ok_or(Error::SharedMemory)?;
83
84        // Push the buffer onto the front or back of the body based on the `BodyWriteEnd` flag.
85        match end {
86            BodyWriteEnd::Front => {
87                // Only normal bodies can be front-written
88                self.body_mut(body_handle)?.push_front(buf);
89            }
90            BodyWriteEnd::Back => {
91                if self.is_streaming_body(body_handle) {
92                    self.streaming_body_mut(body_handle)?
93                        .send_chunk(buf)
94                        .await?;
95                } else {
96                    self.body_mut(body_handle)?.push_back(buf);
97                }
98            }
99        }
100        // Finally, return the number of bytes written, which is _always_ the full buffer
101        Ok(buf
102            .len()
103            .try_into()
104            .expect("the buffer length must fit into a u32"))
105    }
106
107    fn close(
108        &mut self,
109        _memory: &mut GuestMemory<'_>,
110        body_handle: BodyHandle,
111    ) -> Result<(), Error> {
112        // Drop the body and pass up an error if the handle does not exist
113        if self.is_streaming_body(body_handle) {
114            // Make sure a streaming body gets a `finish` message
115            self.take_streaming_body(body_handle)?.finish()
116        } else {
117            Ok(self.drop_body(body_handle)?)
118        }
119    }
120
121    fn abandon(
122        &mut self,
123        _memory: &mut GuestMemory<'_>,
124        body_handle: BodyHandle,
125    ) -> Result<(), Error> {
126        // Drop the body without a `finish` message
127        Ok(self.drop_body(body_handle)?)
128    }
129
130    fn trailer_append(
131        &mut self,
132        memory: &mut GuestMemory<'_>,
133        body_handle: BodyHandle,
134        name: GuestPtr<[u8]>,
135        value: GuestPtr<[u8]>,
136    ) -> Result<(), Error> {
137        // Appending trailers is always allowed for bodies and streaming bodies.
138        if self.is_streaming_body(body_handle) {
139            let body = self.streaming_body_mut(body_handle)?;
140            let name = HeaderName::from_bytes(memory.as_slice(name)?.ok_or(Error::SharedMemory)?)?;
141            let value =
142                HeaderValue::from_bytes(memory.as_slice(value)?.ok_or(Error::SharedMemory)?)?;
143            body.append_trailer(name, value);
144            Ok(())
145        } else {
146            let body = self.body_mut(body_handle)?;
147            let trailers = &mut body.trailers;
148            HttpHeaders::append(trailers, memory, name, value)
149        }
150    }
151
152    fn trailer_names_get<'a>(
153        &mut self,
154        memory: &mut GuestMemory<'_>,
155        body_handle: BodyHandle,
156        buf: GuestPtr<u8>,
157        buf_len: u32,
158        cursor: MultiValueCursor,
159        ending_cursor_out: GuestPtr<MultiValueCursorResult>,
160        nwritten_out: GuestPtr<u32>,
161    ) -> Result<(), Error> {
162        // Read operations are not allowed on streaming bodies.
163        if self.is_streaming_body(body_handle) {
164            return Err(Error::InvalidArgument);
165        }
166
167        let body = self.body_mut(body_handle)?;
168        if body.trailers_ready {
169            let trailers = &body.trailers;
170            return multi_value_result!(
171                memory,
172                trailers.names_get(memory, buf, buf_len, cursor, nwritten_out),
173                ending_cursor_out
174            );
175        }
176        Err(Error::Again)
177    }
178
179    fn trailer_value_get<'a>(
180        &mut self,
181        memory: &mut GuestMemory<'_>,
182        body_handle: BodyHandle,
183        name: GuestPtr<[u8]>,
184        value: GuestPtr<u8>,
185        value_max_len: u32,
186        nwritten_out: GuestPtr<u32>,
187    ) -> Result<(), Error> {
188        // Read operations are not allowed on streaming bodies.
189        if self.is_streaming_body(body_handle) {
190            return Err(Error::InvalidArgument);
191        }
192
193        let body = &mut self.body_mut(body_handle)?;
194        if body.trailers_ready {
195            let trailers = &mut body.trailers;
196            return trailers.value_get(memory, name, value, value_max_len, nwritten_out);
197        }
198        Err(Error::Again)
199    }
200
201    fn trailer_values_get<'a>(
202        &mut self,
203        memory: &mut GuestMemory<'_>,
204        body_handle: BodyHandle,
205        name: GuestPtr<[u8]>,
206        buf: GuestPtr<u8>,
207        buf_len: u32,
208        cursor: MultiValueCursor,
209        ending_cursor_out: GuestPtr<MultiValueCursorResult>,
210        nwritten_out: GuestPtr<u32>,
211    ) -> Result<(), Error> {
212        // Read operations are not allowed on streaming bodies.
213        if self.is_streaming_body(body_handle) {
214            return Err(Error::InvalidArgument);
215        }
216
217        let body = &mut self.body_mut(body_handle)?;
218        if body.trailers_ready {
219            let trailers = &mut body.trailers;
220            return multi_value_result!(
221                memory,
222                trailers.values_get(memory, name, buf, buf_len, cursor, nwritten_out),
223                ending_cursor_out
224            );
225        }
226        Err(Error::Again)
227    }
228
229    fn known_length(
230        &mut self,
231        _memory: &mut GuestMemory<'_>,
232        body_handle: BodyHandle,
233    ) -> Result<BodyLength, Error> {
234        if self.is_streaming_body(body_handle) {
235            Err(Error::ValueAbsent)
236        } else if let Some(len) = self.body_mut(body_handle)?.len() {
237            Ok(len)
238        } else {
239            Err(Error::ValueAbsent)
240        }
241    }
242}