Skip to main content

sark_http/request/
bytes.rs

1use std::{mem, ops};
2
3use o3::{
4    buffer::{
5        bytes::scope,
6        resident,
7        storage::{self, range},
8    },
9    mem::Rejected,
10};
11
12use crate::{
13    owner::{handoff, handoff::stage},
14    payload::{owned, response},
15    request::{Id, Segments},
16};
17
18/// Contiguous bytes derived from one exact request.
19///
20/// Projection cannot extend the request owner's lifetime.
21#[repr(C)]
22pub struct Bytes<'d> {
23    owner: resident::Shared<'d>,
24    id: Id<'d>,
25}
26
27impl<'d> Bytes<'d> {
28    #[doc(hidden)]
29    pub fn from_shared(id: Id<'d>, owner: storage::Shared) -> Self {
30        Self {
31            owner: resident::Shared::from(owner),
32            id,
33        }
34    }
35
36    #[doc(hidden)]
37    pub const fn new(id: Id<'d>, owner: resident::Shared<'d>) -> Self {
38        Self { owner, id }
39    }
40
41    pub fn as_slice(&self) -> &[u8] {
42        self.owner.as_slice()
43    }
44
45    pub fn len(&self) -> usize {
46        self.owner.len()
47    }
48
49    pub fn is_empty(&self) -> bool {
50        self.owner.is_empty()
51    }
52
53    /// Narrows this request owner, retaining its identity on success and rejection.
54    pub fn project(self, visible: ops::Range<usize>) -> Result<Self, Rejected<Self, range::Error>> {
55        let Self { owner, id } = self;
56        match owner.project(visible) {
57            Ok(owner) => Ok(Self { owner, id }),
58            Err(rejected) => Err(rejected.map(|owner| Self { owner, id })),
59        }
60    }
61
62    #[doc(hidden)]
63    pub const fn id(&self) -> Id<'d> {
64        self.id
65    }
66
67    #[doc(hidden)]
68    pub fn into_body(self) -> Segments<'d> {
69        Segments::new(self.id, owned::Segments::from(self.owner))
70    }
71}
72
73impl<'d> response::Body<'d> for Bytes<'d> {
74    fn len(&self) -> usize {
75        self.owner.len()
76    }
77
78    fn as_slice(&self) -> Option<&[u8]> {
79        Some(self.owner.as_slice())
80    }
81
82    fn try_resolve<'req, H: scope::Source, O: stage::Body<'req, 'd>>(
83        self,
84        slot: &handoff::Slot<'req, 'd, H, O>,
85    ) -> Result<handoff::Plan<'req, 'd, H::Selection, O>, owned::Error> {
86        Ok(handoff::Plan::new(slot.origin().request(self.into_body())))
87    }
88}
89
90const _: () = assert!(mem::size_of::<Bytes<'static>>() == 5 * mem::size_of::<usize>());
91
92impl AsRef<[u8]> for Bytes<'_> {
93    fn as_ref(&self) -> &[u8] {
94        self.as_slice()
95    }
96}