Skip to main content

sark_core/request/frame/
raw.rs

1//! Trusted request projection bindings.
2
3use std::{mem, ops};
4
5use o3::{buffer, buffer::resident, mem::rc};
6use request::{Projection, field, frame::proof, path};
7use sark_http::request::{Bytes, span};
8
9use crate::{request, route};
10
11pub struct Path<'a, R> {
12    req: &'a R,
13    cap: route::raw::PathCapture,
14}
15
16impl<'a, R> Path<'a, R> {
17    /// Binds a generated capture to its exact request.
18    ///
19    /// # Safety
20    /// `cap` must have been matched from `req`.
21    pub const unsafe fn new(req: &'a R, cap: route::raw::PathCapture) -> Self {
22        Self { req, cap }
23    }
24}
25
26impl<'req, R: route::Schema>
27    Path<'_, request::raw::Parsed<request::Head<&'req [u8], R::Frame>, R>>
28{
29    pub fn get(self) -> &'req [u8] {
30        let path = self.req.owner().path();
31        let range = self.cap.start()..self.cap.end();
32        unsafe { path.get_unchecked(range) }
33    }
34
35    pub fn try_parse<T: field::Path>(self) -> Result<T, field::Error> {
36        let start = self.cap.start();
37        T::parse(path::Capture::new(self.get(), start))
38    }
39}
40
41impl<'d, R: route::Schema> Path<'_, request::raw::Parsed<request::Parts<'d, R::Frame>, R>> {
42    /// Retains a capture within this route, whose end fits the immutable owner.
43    pub fn try_get(self) -> Result<Bytes<'d>, rc::Error> {
44        let range = self.cap.start()..self.cap.end();
45        Ok(match self.req.owner().head.route() {
46            Projection::Frame(path) => {
47                let start = path.start + range.start;
48                let end = path.start + range.end;
49                let owner = self.req.owner().head.owner();
50                let frame = unsafe { buffer::raw::Segment::try_project(owner, start..end) }?;
51                Bytes::from_shared(self.req.owner().id, frame)
52            }
53            Projection::Root => self.static_path(b"/", range),
54            Projection::Star => self.static_path(b"*", range),
55        })
56    }
57
58    pub fn try_parse<T: field::Path>(self) -> Result<T, field::Error> {
59        let path = self.req.owner().head.borrow().path();
60        let range = self.cap.start()..self.cap.end();
61        // SAFETY: this capture was matched from this exact retained request.
62        let value = unsafe { path.get_unchecked(range) };
63        T::parse(path::Capture::new(value, self.cap.start()))
64    }
65
66    fn static_path(self, path: &'d [u8], range: ops::Range<usize>) -> Bytes<'d> {
67        let frame = unsafe { path.get_unchecked(range) };
68        Bytes::new(self.req.owner().id, resident::Shared::from(frame))
69    }
70}
71
72pub struct Bound<'a, R> {
73    req: &'a R,
74    span: span::Span,
75}
76
77impl<'a, R> Bound<'a, R> {
78    /// Binds a parsed frame to its exact request head.
79    ///
80    /// # Safety
81    /// `span` must have been parsed from `req`.
82    pub const unsafe fn new(req: &'a R, span: span::Span) -> Self {
83        Self { req, span }
84    }
85}
86
87impl<'req, R: route::Schema>
88    Bound<'_, request::raw::Parsed<request::Head<&'req [u8], R::Frame>, R>>
89{
90    pub fn get(self) -> &'req [u8] {
91        let range = self.span.start()..self.span.end();
92        let owner = *self.req.owner().owner();
93        unsafe { owner.get_unchecked(range) }
94    }
95}
96
97impl<'a, 'req, R: route::Schema<Frame = proof::Peer>>
98    Bound<'a, request::raw::Parsed<request::Head<&'req [u8], proof::Peer>, R>>
99{
100    pub fn required(
101        req: &'a request::raw::Parsed<request::Head<&'req [u8], proof::Peer>, R>,
102    ) -> Self {
103        Self {
104            req,
105            span: req.owner().peer(),
106        }
107    }
108}
109
110impl<'d, R: route::Schema> Bound<'_, request::raw::Parsed<request::Parts<'d, R::Frame>, R>> {
111    pub fn try_get(self) -> Result<Bytes<'d>, rc::Error> {
112        let range = self.span.start()..self.span.end();
113        let owner = self.req.owner().head.owner();
114        let frame = unsafe { buffer::raw::Segment::try_project(owner, range) }?;
115        Ok(Bytes::from_shared(self.req.owner().id, frame))
116    }
117}
118
119impl<'a, 'd, R: route::Schema<Frame = proof::Peer>>
120    Bound<'a, request::raw::Parsed<request::Parts<'d, proof::Peer>, R>>
121{
122    pub fn required(req: &'a request::raw::Parsed<request::Parts<'d, proof::Peer>, R>) -> Self {
123        Self {
124            req,
125            span: req.owner().head.peer(),
126        }
127    }
128}
129
130const _: () = {
131    assert!(mem::size_of::<Path<'_, ()>>() == 3 * mem::size_of::<usize>());
132    assert!(mem::size_of::<Bound<'_, ()>>() == 2 * mem::size_of::<usize>());
133};