1use crate::FieldMap;
2use crate::p3::bindings::clocks::monotonic_clock::Duration;
3use crate::p3::bindings::http::types::{
4 ErrorCode, FieldName, FieldValue, Fields, HeaderError, Headers, Host, HostFields, HostRequest,
5 HostRequestOptions, HostRequestWithStore, HostResponse, HostResponseWithStore, Method, Request,
6 RequestOptions, RequestOptionsError, Response, Scheme, StatusCode, Trailers,
7};
8use crate::p3::body::Body;
9use crate::p3::{HeaderResult, HttpError, RequestOptionsResult};
10use crate::{WasiHttp, WasiHttpCtxView};
11use std::sync::Arc;
12use wasmtime::AsContextMut;
13use wasmtime::component::{Access, FutureReader, Resource, ResourceTable, StreamReader};
14use wasmtime::error::Context as _;
15
16fn get_fields<'a>(
17 table: &'a ResourceTable,
18 fields: &Resource<Fields>,
19) -> wasmtime::Result<&'a Fields> {
20 table
21 .get(&fields)
22 .context("failed to get fields from table")
23}
24
25fn get_fields_mut<'a>(
26 table: &'a mut ResourceTable,
27 fields: &Resource<Fields>,
28) -> HeaderResult<&'a mut Fields> {
29 table
30 .get_mut(&fields)
31 .context("failed to get fields from table")
32 .map_err(crate::p3::HeaderError::trap)
33}
34
35fn push_fields(table: &mut ResourceTable, fields: Fields) -> wasmtime::Result<Resource<Fields>> {
36 table.push(fields).context("failed to push fields to table")
37}
38
39fn delete_fields(table: &mut ResourceTable, fields: Resource<Fields>) -> wasmtime::Result<Fields> {
40 let mut fields = table
41 .delete(fields)
42 .context("failed to delete fields from table")?;
43 fields.set_immutable();
48 Ok(fields)
49}
50
51fn get_request<'a>(
52 table: &'a ResourceTable,
53 req: &Resource<Request>,
54) -> wasmtime::Result<&'a Request> {
55 table.get(req).context("failed to get request from table")
56}
57
58fn get_request_mut<'a>(
59 table: &'a mut ResourceTable,
60 req: &Resource<Request>,
61) -> wasmtime::Result<&'a mut Request> {
62 table
63 .get_mut(req)
64 .context("failed to get request from table")
65}
66
67fn get_response<'a>(
68 table: &'a ResourceTable,
69 res: &Resource<Response>,
70) -> wasmtime::Result<&'a Response> {
71 table.get(res).context("failed to get response from table")
72}
73
74fn get_response_mut<'a>(
75 table: &'a mut ResourceTable,
76 res: &Resource<Response>,
77) -> wasmtime::Result<&'a mut Response> {
78 table
79 .get_mut(res)
80 .context("failed to get response from table")
81}
82
83fn get_request_options<'a>(
84 table: &'a ResourceTable,
85 opts: &Resource<RequestOptions>,
86) -> wasmtime::Result<&'a RequestOptions> {
87 table
88 .get(opts)
89 .context("failed to get request options from table")
90}
91
92fn get_request_options_mut<'a>(
93 table: &'a mut ResourceTable,
94 opts: &Resource<RequestOptions>,
95) -> RequestOptionsResult<&'a mut RequestOptions> {
96 table
97 .get_mut(opts)
98 .context("failed to get request options from table")
99 .map_err(crate::p3::RequestOptionsError::trap)
100}
101
102fn push_request_options(
103 table: &mut ResourceTable,
104 opts: RequestOptions,
105) -> wasmtime::Result<Resource<RequestOptions>> {
106 table
107 .push(opts)
108 .context("failed to push request options to table")
109}
110
111fn delete_request_options(
112 table: &mut ResourceTable,
113 opts: Resource<RequestOptions>,
114) -> wasmtime::Result<RequestOptions> {
115 table
116 .delete(opts)
117 .context("failed to delete request options from table")
118}
119
120impl HostFields for WasiHttpCtxView<'_> {
121 fn new(&mut self) -> wasmtime::Result<Resource<Fields>> {
122 push_fields(self.table, FieldMap::new_mutable(self.ctx.field_size_limit))
123 }
124
125 fn from_list(
126 &mut self,
127 entries: Vec<(FieldName, FieldValue)>,
128 ) -> HeaderResult<Resource<Fields>> {
129 let mut fields = FieldMap::new_mutable(self.ctx.field_size_limit);
130 for (name, value) in entries {
131 fields.append(self.hooks, name, value)?;
132 }
133 let fields = push_fields(self.table, fields).map_err(crate::p3::HeaderError::trap)?;
134 Ok(fields)
135 }
136
137 fn get(
138 &mut self,
139 fields: Resource<Fields>,
140 name: FieldName,
141 ) -> wasmtime::Result<Vec<FieldValue>> {
142 let fields = get_fields(self.table, &fields)?;
143 Ok(fields
144 .get_all(name)
145 .into_iter()
146 .map(|val| val.as_bytes().into())
147 .collect())
148 }
149
150 fn has(&mut self, fields: Resource<Fields>, name: FieldName) -> wasmtime::Result<bool> {
151 let fields = get_fields(self.table, &fields)?;
152 Ok(fields.contains_key(name))
153 }
154
155 fn set(
156 &mut self,
157 fields: Resource<Fields>,
158 name: FieldName,
159 values: Vec<FieldValue>,
160 ) -> HeaderResult<()> {
161 get_fields_mut(self.table, &fields)?.set(self.hooks, name, values)?;
162 Ok(())
163 }
164
165 fn delete(&mut self, fields: Resource<Fields>, name: FieldName) -> HeaderResult<()> {
166 get_fields_mut(self.table, &fields)?.remove_all(self.hooks, name)?;
167 Ok(())
168 }
169
170 fn get_and_delete(
171 &mut self,
172 fields: Resource<Fields>,
173 name: FieldName,
174 ) -> HeaderResult<Vec<FieldValue>> {
175 let name = name.parse().or(Err(HeaderError::InvalidSyntax))?;
176 let values = get_fields_mut(self.table, &fields)?
177 .remove_all(self.hooks, name)?
178 .into_iter();
179 Ok(values.map(|value| value.as_bytes().into()).collect())
180 }
181
182 fn append(
183 &mut self,
184 fields: Resource<Fields>,
185 name: FieldName,
186 value: FieldValue,
187 ) -> HeaderResult<()> {
188 get_fields_mut(self.table, &fields)?.append(self.hooks, name, value)?;
189 Ok(())
190 }
191
192 fn copy_all(
193 &mut self,
194 fields: Resource<Fields>,
195 ) -> wasmtime::Result<Vec<(FieldName, FieldValue)>> {
196 let fields = get_fields(self.table, &fields)?;
197 let fields = fields
198 .iter()
199 .map(|(name, value)| (name.as_str().into(), value.as_bytes().into()))
200 .collect();
201 Ok(fields)
202 }
203
204 fn clone(&mut self, fields: Resource<Fields>) -> wasmtime::Result<Resource<Fields>> {
205 let mut fields = get_fields(self.table, &fields)?.clone();
206 fields.set_mutable(self.ctx.field_size_limit);
207 push_fields(self.table, fields)
208 }
209
210 fn drop(&mut self, fields: Resource<Fields>) -> wasmtime::Result<()> {
211 delete_fields(self.table, fields)?;
212 Ok(())
213 }
214}
215
216fn new_request<S>(
217 mut store: S,
218 mut getter: impl FnMut(&mut S::Data) -> WasiHttpCtxView<'_> + Copy + Send + 'static,
219 headers: Resource<Headers>,
220 contents: Option<StreamReader<u8>>,
221 trailers: FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
222 options: Option<Resource<RequestOptions>>,
223) -> wasmtime::Result<(Resource<Request>, FutureReader<Result<(), ErrorCode>>)>
224where
225 S: AsContextMut,
226{
227 let mut store = store.as_context_mut();
228 let (body, body_result) = Body::new_guest(&mut store, getter, contents, trailers)?;
229 let cx = getter(store.data_mut());
230 let headers = delete_fields(cx.table, headers)?;
231 let options = options
232 .map(|options| delete_request_options(cx.table, options))
233 .transpose()?;
234 let req = Request {
235 method: http::Method::GET,
236 scheme: None,
237 authority: None,
238 path_with_query: None,
239 headers,
240 options: options.map(Into::into),
241 body,
242 };
243 let req = cx
244 .table
245 .push(req)
246 .context("failed to push request to table")?;
247 Ok((req, body_result))
248}
249
250impl<T> HostRequestWithStore<T> for WasiHttp {
251 fn new(
252 store: Access<T, Self>,
253 headers: Resource<Headers>,
254 contents: Option<StreamReader<u8>>,
255 trailers: FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
256 options: Option<Resource<RequestOptions>>,
257 ) -> wasmtime::Result<(Resource<Request>, FutureReader<Result<(), ErrorCode>>)> {
258 let getter = store.getter();
259 new_request(store, getter, headers, contents, trailers, options)
260 }
261
262 fn consume_body(
263 mut store: Access<T, Self>,
264 req: Resource<Request>,
265 fut: FutureReader<Result<(), ErrorCode>>,
266 ) -> wasmtime::Result<(
267 StreamReader<u8>,
268 FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
269 )> {
270 let getter = store.getter();
271 let Request { body, .. } = store.get().table.delete(req)?;
272 body.consume(store, fut, getter)
273 }
274
275 fn drop(mut store: Access<'_, T, Self>, req: Resource<Request>) -> wasmtime::Result<()> {
276 let Request { body, .. } = store.get().table.delete(req)?;
277 body.drop(store)?;
278 Ok(())
279 }
280}
281
282impl HostRequest for WasiHttpCtxView<'_> {
283 fn get_method(&mut self, req: Resource<Request>) -> wasmtime::Result<Method> {
284 let Request { method, .. } = get_request(self.table, &req)?;
285 Ok(method.into())
286 }
287
288 fn set_method(
289 &mut self,
290 req: Resource<Request>,
291 method: Method,
292 ) -> wasmtime::Result<Result<(), ()>> {
293 let req = get_request_mut(self.table, &req)?;
294 let Ok(method) = method.try_into() else {
295 return Ok(Err(()));
296 };
297 req.method = method;
298 Ok(Ok(()))
299 }
300
301 fn get_path_with_query(&mut self, req: Resource<Request>) -> wasmtime::Result<Option<String>> {
302 let Request {
303 path_with_query, ..
304 } = get_request(self.table, &req)?;
305 Ok(path_with_query.as_ref().map(|pq| pq.as_str().into()))
306 }
307
308 fn set_path_with_query(
309 &mut self,
310 req: Resource<Request>,
311 path_with_query: Option<String>,
312 ) -> wasmtime::Result<Result<(), ()>> {
313 let req = get_request_mut(self.table, &req)?;
314
315 let Some(path_with_query) = path_with_query else {
316 req.path_with_query = None;
317 return Ok(Ok(()));
318 };
319 let Some(path_with_query) = crate::parse_path_with_query(&path_with_query) else {
320 return Ok(Err(()));
321 };
322 req.path_with_query = Some(path_with_query);
323 Ok(Ok(()))
324 }
325
326 fn get_scheme(&mut self, req: Resource<Request>) -> wasmtime::Result<Option<Scheme>> {
327 let Request { scheme, .. } = get_request(self.table, &req)?;
328 Ok(scheme.as_ref().map(Into::into))
329 }
330
331 fn set_scheme(
332 &mut self,
333 req: Resource<Request>,
334 scheme: Option<Scheme>,
335 ) -> wasmtime::Result<Result<(), ()>> {
336 let req = get_request_mut(self.table, &req)?;
337 let Some(scheme) = scheme else {
338 req.scheme = None;
339 return Ok(Ok(()));
340 };
341 let Ok(scheme) = scheme.try_into() else {
342 return Ok(Err(()));
343 };
344 req.scheme = Some(scheme);
345 Ok(Ok(()))
346 }
347
348 fn get_authority(&mut self, req: Resource<Request>) -> wasmtime::Result<Option<String>> {
349 let Request { authority, .. } = get_request(self.table, &req)?;
350 Ok(authority.as_ref().map(|auth| auth.as_str().into()))
351 }
352
353 fn set_authority(
354 &mut self,
355 req: Resource<Request>,
356 authority: Option<String>,
357 ) -> wasmtime::Result<Result<(), ()>> {
358 let req = get_request_mut(self.table, &req)?;
359 let Some(authority) = authority else {
360 req.authority = None;
361 return Ok(Ok(()));
362 };
363 let Ok(authority) = crate::parse_authority(authority) else {
364 return Ok(Err(()));
365 };
366 req.authority = Some(authority);
367 Ok(Ok(()))
368 }
369
370 fn get_options(
371 &mut self,
372 req: Resource<Request>,
373 ) -> wasmtime::Result<Option<Resource<RequestOptions>>> {
374 let Request { options, .. } = get_request(self.table, &req)?;
375 if let Some(options) = options {
376 let options = push_request_options(
377 self.table,
378 RequestOptions::new_immutable(Arc::clone(options)),
379 )?;
380 Ok(Some(options))
381 } else {
382 Ok(None)
383 }
384 }
385
386 fn get_headers(&mut self, req: Resource<Request>) -> wasmtime::Result<Resource<Headers>> {
387 let Request { headers, .. } = get_request(self.table, &req)?;
388 let mut headers = headers.clone();
390 headers.set_immutable();
391 push_fields(self.table, headers)
392 }
393}
394
395impl HostRequestOptions for WasiHttpCtxView<'_> {
396 fn new(&mut self) -> wasmtime::Result<Resource<RequestOptions>> {
397 push_request_options(self.table, RequestOptions::new_mutable_default())
398 }
399
400 fn get_connect_timeout(
401 &mut self,
402 opts: Resource<RequestOptions>,
403 ) -> wasmtime::Result<Option<Duration>> {
404 let opts = get_request_options(self.table, &opts)?;
405 let Some(connect_timeout) = opts.connect_timeout else {
406 return Ok(None);
407 };
408 let ns = connect_timeout.as_nanos();
409 let ns = Duration::try_from(ns)
410 .context("connect timeout duration nanoseconds do not fit in u64")?;
411 Ok(Some(ns))
412 }
413
414 fn set_connect_timeout(
415 &mut self,
416 opts: Resource<RequestOptions>,
417 duration: Option<Duration>,
418 ) -> RequestOptionsResult<()> {
419 let opts = get_request_options_mut(self.table, &opts)?;
420 let opts = opts.get_mut().ok_or(RequestOptionsError::Immutable)?;
421 opts.connect_timeout = duration.map(core::time::Duration::from_nanos);
422 Ok(())
423 }
424
425 fn get_first_byte_timeout(
426 &mut self,
427 opts: Resource<RequestOptions>,
428 ) -> wasmtime::Result<Option<Duration>> {
429 let opts = get_request_options(self.table, &opts)?;
430 let Some(first_byte_timeout) = opts.first_byte_timeout else {
431 return Ok(None);
432 };
433 let ns = first_byte_timeout.as_nanos();
434 let ns = Duration::try_from(ns)
435 .context("first byte timeout duration nanoseconds do not fit in u64")?;
436 Ok(Some(ns))
437 }
438
439 fn set_first_byte_timeout(
440 &mut self,
441 opts: Resource<RequestOptions>,
442 duration: Option<Duration>,
443 ) -> RequestOptionsResult<()> {
444 let opts = get_request_options_mut(self.table, &opts)?;
445 let opts = opts.get_mut().ok_or(RequestOptionsError::Immutable)?;
446 opts.first_byte_timeout = duration.map(core::time::Duration::from_nanos);
447 Ok(())
448 }
449
450 fn get_between_bytes_timeout(
451 &mut self,
452 opts: Resource<RequestOptions>,
453 ) -> wasmtime::Result<Option<Duration>> {
454 let opts = get_request_options(self.table, &opts)?;
455 let Some(between_bytes_timeout) = opts.between_bytes_timeout else {
456 return Ok(None);
457 };
458 let ns = between_bytes_timeout.as_nanos();
459 let ns = Duration::try_from(ns)
460 .context("between bytes timeout duration nanoseconds do not fit in u64")?;
461 Ok(Some(ns))
462 }
463
464 fn set_between_bytes_timeout(
465 &mut self,
466 opts: Resource<RequestOptions>,
467 duration: Option<Duration>,
468 ) -> RequestOptionsResult<()> {
469 let opts = get_request_options_mut(self.table, &opts)?;
470 let opts = opts.get_mut().ok_or(RequestOptionsError::Immutable)?;
471 opts.between_bytes_timeout = duration.map(core::time::Duration::from_nanos);
472 Ok(())
473 }
474
475 fn clone(
476 &mut self,
477 opts: Resource<RequestOptions>,
478 ) -> wasmtime::Result<Resource<RequestOptions>> {
479 let opts = get_request_options(self.table, &opts)?;
480 push_request_options(self.table, RequestOptions::new_mutable(Arc::clone(opts)))
481 }
482
483 fn drop(&mut self, opts: Resource<RequestOptions>) -> wasmtime::Result<()> {
484 delete_request_options(self.table, opts)?;
485 Ok(())
486 }
487}
488
489fn new_response<S>(
490 mut store: S,
491 mut getter: impl FnMut(&mut S::Data) -> WasiHttpCtxView<'_> + Copy + Send + 'static,
492 headers: Resource<Headers>,
493 contents: Option<StreamReader<u8>>,
494 trailers: FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
495) -> wasmtime::Result<(Resource<Response>, FutureReader<Result<(), ErrorCode>>)>
496where
497 S: AsContextMut,
498{
499 let mut store = store.as_context_mut();
500 let (body, body_result) = Body::new_guest(&mut store, getter, contents, trailers)?;
501 let cx = getter(store.data_mut());
502 let headers = delete_fields(cx.table, headers)?;
503 let res = Response {
504 status: http::StatusCode::OK,
505 headers,
506 body,
507 };
508 let res = cx.table.push(res)?;
509 Ok((res, body_result))
510}
511
512impl<T> HostResponseWithStore<T> for WasiHttp {
513 fn new(
514 store: Access<T, Self>,
515 headers: Resource<Headers>,
516 contents: Option<StreamReader<u8>>,
517 trailers: FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
518 ) -> wasmtime::Result<(Resource<Response>, FutureReader<Result<(), ErrorCode>>)> {
519 let getter = store.getter();
520 new_response(store, getter, headers, contents, trailers)
521 }
522
523 fn consume_body(
524 mut store: Access<T, Self>,
525 res: Resource<Response>,
526 fut: FutureReader<Result<(), ErrorCode>>,
527 ) -> wasmtime::Result<(
528 StreamReader<u8>,
529 FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
530 )> {
531 let getter = store.getter();
532 let Response { body, .. } = store.get().table.delete(res)?;
533 body.consume(store, fut, getter)
534 }
535
536 fn drop(mut store: Access<'_, T, Self>, res: Resource<Response>) -> wasmtime::Result<()> {
537 let Response { body, .. } = store.get().table.delete(res)?;
538 body.drop(store)?;
539 Ok(())
540 }
541}
542
543impl HostResponse for WasiHttpCtxView<'_> {
544 fn get_status_code(&mut self, res: Resource<Response>) -> wasmtime::Result<StatusCode> {
545 let res = get_response(self.table, &res)?;
546 Ok(res.status.into())
547 }
548
549 fn set_status_code(
550 &mut self,
551 res: Resource<Response>,
552 status_code: StatusCode,
553 ) -> wasmtime::Result<Result<(), ()>> {
554 let res = get_response_mut(self.table, &res)?;
555 match http::StatusCode::from_u16(status_code) {
556 Ok(status) if matches!(status_code, 100..=599) => {
557 res.status = status;
558 Ok(Ok(()))
559 }
560 _ => Ok(Err(())),
561 }
562 }
563
564 fn get_headers(&mut self, res: Resource<Response>) -> wasmtime::Result<Resource<Headers>> {
565 let Response { headers, .. } = get_response(self.table, &res)?;
566 let mut headers = headers.clone();
568 headers.set_immutable();
569 push_fields(self.table, headers)
570 }
571}
572
573impl Host for WasiHttpCtxView<'_> {
574 fn convert_error_code(&mut self, error: HttpError) -> wasmtime::Result<ErrorCode> {
575 error.downcast()
576 }
577
578 fn convert_header_error(
579 &mut self,
580 error: crate::p3::HeaderError,
581 ) -> wasmtime::Result<HeaderError> {
582 error.downcast()
583 }
584
585 fn convert_request_options_error(
586 &mut self,
587 error: crate::p3::RequestOptionsError,
588 ) -> wasmtime::Result<RequestOptionsError> {
589 error.downcast()
590 }
591}
592
593mod named {
594 use crate::p3::bindings::clocks::monotonic_clock::Duration;
595 use crate::p3::bindings::http::types::{
596 ErrorCode, FieldName, FieldValue, Fields, HeaderError, Headers, Method, Request,
597 RequestOptions, RequestOptionsError, Response, Scheme, StatusCode, Trailers,
598 };
599 use crate::p3::bindings::named_imports::wasi::http::types;
600 use crate::p3::{HeaderResult, HttpError, RequestOptionsResult};
601 use crate::{WasiHttpNamed, WasiHttpNamedView};
602 use wasmtime::component::{Access, FutureReader, Resource, StreamReader};
603 use wasmtime_wasi::{NamedId, WasiCtxNamedView};
604
605 impl<T> types::Host for WasiCtxNamedView<'_, T>
606 where
607 T: WasiHttpNamedView,
608 {
609 fn convert_error_code(&mut self, error: HttpError) -> wasmtime::Result<ErrorCode> {
610 error.downcast()
611 }
612
613 fn convert_header_error(
614 &mut self,
615 error: crate::p3::HeaderError,
616 ) -> wasmtime::Result<HeaderError> {
617 error.downcast()
618 }
619
620 fn convert_request_options_error(
621 &mut self,
622 error: crate::p3::RequestOptionsError,
623 ) -> wasmtime::Result<RequestOptionsError> {
624 error.downcast()
625 }
626 }
627
628 impl<T> types::HostFields for WasiCtxNamedView<'_, T>
629 where
630 T: WasiHttpNamedView,
631 {
632 fn new(&mut self, id: NamedId) -> wasmtime::Result<Resource<Fields>> {
633 super::HostFields::new(&mut self.0.http(id))
634 }
635
636 fn from_list(
637 &mut self,
638 id: NamedId,
639 entries: Vec<(FieldName, FieldValue)>,
640 ) -> HeaderResult<Resource<Fields>> {
641 super::HostFields::from_list(&mut self.0.http(id), entries)
642 }
643
644 fn get(
645 &mut self,
646 id: NamedId,
647 fields: Resource<Fields>,
648 name: FieldName,
649 ) -> wasmtime::Result<Vec<FieldValue>> {
650 super::HostFields::get(&mut self.0.http(id), fields, name)
651 }
652
653 fn has(
654 &mut self,
655 id: NamedId,
656 fields: Resource<Fields>,
657 name: FieldName,
658 ) -> wasmtime::Result<bool> {
659 super::HostFields::has(&mut self.0.http(id), fields, name)
660 }
661
662 fn set(
663 &mut self,
664 id: NamedId,
665 fields: Resource<Fields>,
666 name: FieldName,
667 values: Vec<FieldValue>,
668 ) -> HeaderResult<()> {
669 super::HostFields::set(&mut self.0.http(id), fields, name, values)
670 }
671
672 fn delete(
673 &mut self,
674 id: NamedId,
675 fields: Resource<Fields>,
676 name: FieldName,
677 ) -> HeaderResult<()> {
678 super::HostFields::delete(&mut self.0.http(id), fields, name)
679 }
680
681 fn get_and_delete(
682 &mut self,
683 id: NamedId,
684 fields: Resource<Fields>,
685 name: FieldName,
686 ) -> HeaderResult<Vec<FieldValue>> {
687 super::HostFields::get_and_delete(&mut self.0.http(id), fields, name)
688 }
689
690 fn append(
691 &mut self,
692 id: NamedId,
693 fields: Resource<Fields>,
694 name: FieldName,
695 value: FieldValue,
696 ) -> HeaderResult<()> {
697 super::HostFields::append(&mut self.0.http(id), fields, name, value)
698 }
699
700 fn copy_all(
701 &mut self,
702 id: NamedId,
703 fields: Resource<Fields>,
704 ) -> wasmtime::Result<Vec<(FieldName, FieldValue)>> {
705 super::HostFields::copy_all(&mut self.0.http(id), fields)
706 }
707
708 fn clone(
709 &mut self,
710 id: NamedId,
711 fields: Resource<Fields>,
712 ) -> wasmtime::Result<Resource<Fields>> {
713 super::HostFields::clone(&mut self.0.http(id), fields)
714 }
715
716 fn drop(&mut self, id: NamedId, fields: Resource<Fields>) -> wasmtime::Result<()> {
717 super::HostFields::drop(&mut self.0.http(id), fields)
718 }
719 }
720
721 impl<T> types::HostRequest for WasiCtxNamedView<'_, T>
722 where
723 T: WasiHttpNamedView,
724 {
725 fn get_method(&mut self, id: NamedId, req: Resource<Request>) -> wasmtime::Result<Method> {
726 super::HostRequest::get_method(&mut self.0.http(id), req)
727 }
728
729 fn set_method(
730 &mut self,
731 id: NamedId,
732 req: Resource<Request>,
733 method: Method,
734 ) -> wasmtime::Result<Result<(), ()>> {
735 super::HostRequest::set_method(&mut self.0.http(id), req, method)
736 }
737
738 fn get_path_with_query(
739 &mut self,
740 id: NamedId,
741 req: Resource<Request>,
742 ) -> wasmtime::Result<Option<String>> {
743 super::HostRequest::get_path_with_query(&mut self.0.http(id), req)
744 }
745
746 fn set_path_with_query(
747 &mut self,
748 id: NamedId,
749 req: Resource<Request>,
750 path_with_query: Option<String>,
751 ) -> wasmtime::Result<Result<(), ()>> {
752 super::HostRequest::set_path_with_query(&mut self.0.http(id), req, path_with_query)
753 }
754
755 fn get_scheme(
756 &mut self,
757 id: NamedId,
758 req: Resource<Request>,
759 ) -> wasmtime::Result<Option<Scheme>> {
760 super::HostRequest::get_scheme(&mut self.0.http(id), req)
761 }
762
763 fn set_scheme(
764 &mut self,
765 id: NamedId,
766 req: Resource<Request>,
767 scheme: Option<Scheme>,
768 ) -> wasmtime::Result<Result<(), ()>> {
769 super::HostRequest::set_scheme(&mut self.0.http(id), req, scheme)
770 }
771
772 fn get_authority(
773 &mut self,
774 id: NamedId,
775 req: Resource<Request>,
776 ) -> wasmtime::Result<Option<String>> {
777 super::HostRequest::get_authority(&mut self.0.http(id), req)
778 }
779
780 fn set_authority(
781 &mut self,
782 id: NamedId,
783 req: Resource<Request>,
784 authority: Option<String>,
785 ) -> wasmtime::Result<Result<(), ()>> {
786 super::HostRequest::set_authority(&mut self.0.http(id), req, authority)
787 }
788
789 fn get_options(
790 &mut self,
791 id: NamedId,
792 req: Resource<Request>,
793 ) -> wasmtime::Result<Option<Resource<RequestOptions>>> {
794 super::HostRequest::get_options(&mut self.0.http(id), req)
795 }
796
797 fn get_headers(
798 &mut self,
799 id: NamedId,
800 req: Resource<Request>,
801 ) -> wasmtime::Result<Resource<Headers>> {
802 super::HostRequest::get_headers(&mut self.0.http(id), req)
803 }
804 }
805
806 impl<T> types::HostRequestOptions for WasiCtxNamedView<'_, T>
807 where
808 T: WasiHttpNamedView,
809 {
810 fn new(&mut self, id: NamedId) -> wasmtime::Result<Resource<RequestOptions>> {
811 super::HostRequestOptions::new(&mut self.0.http(id))
812 }
813
814 fn get_connect_timeout(
815 &mut self,
816 id: NamedId,
817 opts: Resource<RequestOptions>,
818 ) -> wasmtime::Result<Option<Duration>> {
819 super::HostRequestOptions::get_connect_timeout(&mut self.0.http(id), opts)
820 }
821
822 fn set_connect_timeout(
823 &mut self,
824 id: NamedId,
825 opts: Resource<RequestOptions>,
826 duration: Option<Duration>,
827 ) -> RequestOptionsResult<()> {
828 super::HostRequestOptions::set_connect_timeout(&mut self.0.http(id), opts, duration)
829 }
830
831 fn get_first_byte_timeout(
832 &mut self,
833 id: NamedId,
834 opts: Resource<RequestOptions>,
835 ) -> wasmtime::Result<Option<Duration>> {
836 super::HostRequestOptions::get_first_byte_timeout(&mut self.0.http(id), opts)
837 }
838
839 fn set_first_byte_timeout(
840 &mut self,
841 id: NamedId,
842 opts: Resource<RequestOptions>,
843 duration: Option<Duration>,
844 ) -> RequestOptionsResult<()> {
845 super::HostRequestOptions::set_first_byte_timeout(&mut self.0.http(id), opts, duration)
846 }
847
848 fn get_between_bytes_timeout(
849 &mut self,
850 id: NamedId,
851 opts: Resource<RequestOptions>,
852 ) -> wasmtime::Result<Option<Duration>> {
853 super::HostRequestOptions::get_between_bytes_timeout(&mut self.0.http(id), opts)
854 }
855
856 fn set_between_bytes_timeout(
857 &mut self,
858 id: NamedId,
859 opts: Resource<RequestOptions>,
860 duration: Option<Duration>,
861 ) -> RequestOptionsResult<()> {
862 super::HostRequestOptions::set_between_bytes_timeout(
863 &mut self.0.http(id),
864 opts,
865 duration,
866 )
867 }
868
869 fn clone(
870 &mut self,
871 id: NamedId,
872 opts: Resource<RequestOptions>,
873 ) -> wasmtime::Result<Resource<RequestOptions>> {
874 super::HostRequestOptions::clone(&mut self.0.http(id), opts)
875 }
876
877 fn drop(&mut self, id: NamedId, opts: Resource<RequestOptions>) -> wasmtime::Result<()> {
878 super::HostRequestOptions::drop(&mut self.0.http(id), opts)
879 }
880 }
881
882 impl<T> types::HostResponse for WasiCtxNamedView<'_, T>
883 where
884 T: WasiHttpNamedView,
885 {
886 fn get_status_code(
887 &mut self,
888 id: NamedId,
889 res: Resource<Response>,
890 ) -> wasmtime::Result<StatusCode> {
891 super::HostResponse::get_status_code(&mut self.0.http(id), res)
892 }
893
894 fn set_status_code(
895 &mut self,
896 id: NamedId,
897 res: Resource<Response>,
898 status_code: StatusCode,
899 ) -> wasmtime::Result<Result<(), ()>> {
900 super::HostResponse::set_status_code(&mut self.0.http(id), res, status_code)
901 }
902
903 fn get_headers(
904 &mut self,
905 id: NamedId,
906 res: Resource<Response>,
907 ) -> wasmtime::Result<Resource<Headers>> {
908 super::HostResponse::get_headers(&mut self.0.http(id), res)
909 }
910 }
911
912 impl<T, U> types::HostRequestWithStore<U> for WasiHttpNamed<T>
913 where
914 T: WasiHttpNamedView,
915 U: 'static,
916 {
917 fn new(
918 store: Access<U, Self>,
919 id: NamedId,
920 headers: Resource<Headers>,
921 contents: Option<StreamReader<u8>>,
922 trailers: FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
923 options: Option<Resource<RequestOptions>>,
924 ) -> wasmtime::Result<(Resource<Request>, FutureReader<Result<(), ErrorCode>>)> {
925 let getter = store.getter();
926 super::new_request(
927 store,
928 move |data| getter(data).0.http(id),
929 headers,
930 contents,
931 trailers,
932 options,
933 )
934 }
935
936 fn consume_body(
937 mut store: Access<U, Self>,
938 id: NamedId,
939 req: Resource<Request>,
940 fut: FutureReader<Result<(), ErrorCode>>,
941 ) -> wasmtime::Result<(
942 StreamReader<u8>,
943 FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
944 )> {
945 let getter = store.getter();
946 let Request { body, .. } = store.get().0.http(id).table.delete(req)?;
947 body.consume(store, fut, move |data: &mut U| getter(data).0.http(id))
948 }
949
950 fn drop(
951 mut store: Access<'_, U, Self>,
952 id: NamedId,
953 req: Resource<Request>,
954 ) -> wasmtime::Result<()> {
955 let Request { body, .. } = store.get().0.http(id).table.delete(req)?;
956 body.drop(store)?;
957 Ok(())
958 }
959 }
960
961 impl<T, U> types::HostResponseWithStore<U> for WasiHttpNamed<T>
962 where
963 T: WasiHttpNamedView,
964 U: 'static,
965 {
966 fn new(
967 store: Access<U, Self>,
968 id: NamedId,
969 headers: Resource<Headers>,
970 contents: Option<StreamReader<u8>>,
971 trailers: FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
972 ) -> wasmtime::Result<(Resource<Response>, FutureReader<Result<(), ErrorCode>>)> {
973 let getter = store.getter();
974 super::new_response(
975 store,
976 move |data| getter(data).0.http(id),
977 headers,
978 contents,
979 trailers,
980 )
981 }
982
983 fn consume_body(
984 mut store: Access<U, Self>,
985 id: NamedId,
986 res: Resource<Response>,
987 fut: FutureReader<Result<(), ErrorCode>>,
988 ) -> wasmtime::Result<(
989 StreamReader<u8>,
990 FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
991 )> {
992 let getter = store.getter();
993 let Response { body, .. } = store.get().0.http(id).table.delete(res)?;
994 body.consume(store, fut, move |data: &mut U| getter(data).0.http(id))
995 }
996
997 fn drop(
998 mut store: Access<'_, U, Self>,
999 id: NamedId,
1000 res: Resource<Response>,
1001 ) -> wasmtime::Result<()> {
1002 let Response { body, .. } = store.get().0.http(id).table.delete(res)?;
1003 body.drop(store)?;
1004 Ok(())
1005 }
1006 }
1007}