1use 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 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 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 let buf = memory.as_slice(buf)?.ok_or(Error::SharedMemory)?;
83
84 match end {
86 BodyWriteEnd::Front => {
87 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 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 if self.is_streaming_body(body_handle) {
114 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 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 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 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 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 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}