1use std::{mem, ops, ops::Deref};
4
5use o3::{
6 buffer::{bytes::scope, pool, pool::owners, storage},
7 mem::rc,
8};
9use sark_http::{
10 field::metadata::{
11 packed,
12 section::storage::{Block, Bytes, Scope},
13 },
14 payload::owned,
15 request,
16 request::{Bound, Error, Form, Id, Layout, span},
17};
18
19use crate::{body, request::frame::proof};
20
21pub mod field;
22pub mod frame;
23#[doc(hidden)]
24pub mod mode;
25pub mod path;
26pub mod raw;
27mod view;
28
29use request::Source;
30pub use view::View;
31
32#[derive(Clone, Copy, PartialEq, Eq, Debug)]
33pub enum BindError {
34 Layout(request::Error),
35 Body(body::Error),
36 Retain(rc::Error),
37}
38
39#[repr(transparent)]
40#[derive(Clone, Copy)]
41pub struct BodyLen {
42 len: usize,
43}
44
45impl BodyLen {
46 pub const fn new(len: usize) -> Self {
47 Self { len }
48 }
49
50 pub const fn len(&self) -> usize {
51 self.len
52 }
53
54 pub const fn is_empty(&self) -> bool {
55 self.len == 0
56 }
57}
58
59#[doc(hidden)]
60pub struct Parts<'d, P = proof::Maybe> {
61 head: Head<storage::Shared, P>,
62 id: Id<'d>,
63}
64
65impl<'d, P: proof::Proof> Parts<'d, P> {
66 pub fn from_head(id: Id<'d>, head: Head<storage::Shared, P>) -> Self {
67 Self { head, id }
68 }
69
70 pub fn try_frame_at(
71 &self,
72 range: ops::Range<usize>,
73 ) -> Result<request::Bytes<'d>, frame::Error<rc::Error>> {
74 let start = range.start;
75 let end = range.end;
76 let capacity = self.head.as_ref().len();
77 if start > end {
78 return Err(frame::Error::Order {
79 start,
80 end,
81 capacity,
82 });
83 }
84 let frame = self
85 .head
86 .owner()
87 .try_get(start..end)
88 .map_err(frame::Error::Retain)?
89 .ok_or(frame::Error::Bounds {
90 start,
91 end,
92 capacity,
93 })?;
94 Ok(request::Bytes::from_shared(self.id, frame))
95 }
96
97 #[doc(hidden)]
98 pub const fn id(&self) -> Id<'d> {
99 self.id
100 }
101}
102
103#[doc(hidden)]
104pub struct Retained<'d, P = proof::Maybe> {
105 parts: Parts<'d, P>,
106 body: body::Body<owned::Segments<'d>>,
107}
108
109impl<'d, P: proof::Proof> Retained<'d, P> {
110 pub fn from_head(
111 id: Id<'d>,
112 head: Head<storage::Shared, P>,
113 body: body::Body<owned::Segments<'d>>,
114 ) -> Self {
115 Self {
116 parts: Parts::from_head(id, head),
117 body,
118 }
119 }
120
121 pub const fn body_len(&self) -> usize {
122 self.body.len()
123 }
124
125 pub fn into_body(self) -> request::Segments<'d> {
126 request::Segments::new(self.parts.id, self.body.into_body())
127 }
128
129 pub fn into_parts(self) -> (Parts<'d, P>, body::Body<owned::Segments<'d>>) {
130 (self.parts, self.body)
131 }
132}
133
134impl<'d, P> Deref for Retained<'d, P> {
135 type Target = Parts<'d, P>;
136
137 fn deref(&self) -> &Self::Target {
138 &self.parts
139 }
140}
141
142const _: () = assert!(mem::size_of::<View<'static, 'static>>() <= 10 * mem::size_of::<usize>());
143const _: () = assert!(mem::size_of::<Parts<'static>>() <= 10 * mem::size_of::<usize>());
144const _: () = assert!(mem::size_of::<Retained<'static>>() <= 14 * mem::size_of::<usize>());
145const _: () =
146 assert!(mem::size_of::<Parts<'static, proof::Peer>>() <= mem::size_of::<Parts<'static>>());
147const _: () = assert!(
148 mem::size_of::<Retained<'static, proof::Peer>>() <= mem::size_of::<Retained<'static>>()
149);
150
151pub struct Head<O, P = proof::Maybe> {
154 owner: O,
155 target: request::Target,
156 authority: P,
157 route: Route,
158}
159
160const _: () = {
161 assert!(mem::size_of::<Head<&'static [u8]>>() == 5 * mem::size_of::<usize>());
162 assert!(mem::size_of::<Option<Head<&'static [u8]>>>() == mem::size_of::<Head<&[u8]>>());
163 assert!(
164 mem::size_of::<Head<&'static [u8], proof::Peer>>() <= mem::size_of::<Head<&'static [u8]>>()
165 );
166 assert!(!mem::needs_drop::<Head<&'static [u8]>>());
167};
168
169impl<O: Source, P: proof::Proof> Head<O, P> {
170 pub fn bind(owner: O, layout: request::Layout) -> Result<Self, BindError> {
171 Self::try_bound(request::Bound::try_bind(owner, layout).map_err(BindError::Layout)?)
172 }
173
174 pub fn borrow(&self) -> Head<&[u8], P> {
175 Head {
176 owner: self.owner.as_ref(),
177 target: self.target,
178 authority: self.authority,
179 route: self.route,
180 }
181 }
182}
183
184impl<O: Source, P> AsRef<[u8]> for Head<O, P> {
185 fn as_ref(&self) -> &[u8] {
186 self.owner.as_ref()
187 }
188}
189
190impl<O, P> Head<O, P> {
191 pub const fn form(&self) -> request::Form {
192 self.target.form()
193 }
194
195 pub(in crate::request) const fn route(&self) -> Projection {
196 self.route.path()
197 }
198 pub fn into_owner(self) -> O {
199 self.owner
200 }
201
202 pub const fn owner(&self) -> &O {
203 &self.owner
204 }
205}
206
207impl<O> Head<O, proof::Peer> {
208 pub(in crate::request) const fn peer(&self) -> span::Span {
209 self.authority.get()
210 }
211}
212
213impl<P, const PREFIX: usize> From<Head<packed::Decoded<o3::buffer::pool::Span, PREFIX>, P>>
214 for Head<Bytes, P>
215{
216 fn from(head: Head<packed::Decoded<o3::buffer::pool::Span, PREFIX>, P>) -> Self {
217 Self {
218 owner: head.owner.into_bytes(),
219 target: head.target,
220 authority: head.authority,
221 route: head.route,
222 }
223 }
224}
225
226impl<P: proof::Proof> Head<Bytes, P> {
227 pub fn from_path(
228 owner: Bytes,
229 target: ops::Range<usize>,
230 path_len: usize,
231 peer: Option<ops::Range<usize>>,
232 ) -> Result<Self, BindError> {
233 let error = |cause| BindError::Layout(request::Error::Span(cause));
234 let target = span::Span::from_range(target).map_err(error)?;
235 let route = span::Span::checked(target.start(), path_len).map_err(error)?;
236 let target =
237 request::Target::from_span(request::Form::Path, target).map_err(BindError::Layout)?;
238 let peer = peer
239 .map(span::Span::from_range)
240 .transpose()
241 .map_err(error)?;
242 let layout = request::Layout::new(target, peer, Some(route));
243 Self::bind(owner, layout)
244 }
245
246 pub fn retain(self) -> Head<storage::Shared, P> {
247 Head {
248 owner: self.owner.into(),
249 target: self.target,
250 authority: self.authority,
251 route: self.route,
252 }
253 }
254}
255
256#[derive(Clone, Copy)]
257enum Route {
258 Frame(span::Span),
259 Literal(Literal),
260}
261
262#[derive(Clone, Copy)]
263enum Literal {
264 Root,
265 Star,
266}
267
268pub(in crate::request) enum Projection {
269 Frame(ops::Range<usize>),
270 Root,
271 Star,
272}
273
274impl Route {
275 const fn path(self) -> Projection {
276 match self {
277 Self::Frame(span) => Projection::Frame(span.start()..span.end()),
278 Self::Literal(Literal::Root) => Projection::Root,
279 Self::Literal(Literal::Star) => Projection::Star,
280 }
281 }
282}
283
284const _: () = assert!(mem::size_of::<Route>() == mem::size_of::<span::Span>());
285
286impl<O: Scope, P> Head<O, P> {
287 pub fn scope<T>(self, use_head: impl for<'id> FnOnce(Head<O::Scoped<'id>, P>) -> T) -> T {
288 let Self {
289 owner,
290 target,
291 authority: peer,
292 route,
293 } = self;
294 owner.scope(|owner| {
295 use_head(Head {
296 owner,
297 target,
298 authority: peer,
299 route,
300 })
301 })
302 }
303}
304
305impl<P>
306 Head<
307 Bytes<scope::Owner<'_, pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>>,
308 P,
309 >
310{
311 pub fn into_inner(self) -> Head<Bytes, P> {
312 Head {
313 owner: self.owner.into_inner(),
314 target: self.target,
315 authority: self.authority,
316 route: self.route,
317 }
318 }
319}
320
321impl<O: Source, P: proof::Proof> Head<O, P> {
322 pub fn try_bound(bound: Bound<O>) -> Result<Self, BindError> {
323 let (owner, layout) = bound.into_parts();
324 unsafe { Self::try_parts(owner, layout) }
326 }
327
328 unsafe fn try_parts(owner: O, layout: Layout) -> Result<Self, BindError> {
331 let target = layout.target();
332 let proof = P::try_from(layout).map_err(BindError::Layout)?;
333 let route = match target.form() {
334 Form::Path | Form::Extended => {
335 let route = layout
336 .route()
337 .ok_or(BindError::Layout(Error::InvalidRange))?;
338 Route::Frame(route)
339 }
340 Form::Root => Route::Literal(Literal::Root),
341 Form::Asterisk | Form::Authority => Route::Literal(Literal::Star),
342 };
343 Ok(Self {
344 owner,
345 target,
346 authority: proof,
347 route,
348 })
349 }
350}
351
352impl<'a, P> Head<&'a [u8], P> {
353 pub fn path(&self) -> &'a [u8] {
354 match self.route() {
355 Projection::Frame(range) => {
356 unsafe { self.owner.get_unchecked(range) }
358 }
359 Projection::Root => b"/",
360 Projection::Star => b"*",
361 }
362 }
363}
364
365impl<'a, P: proof::Proof> Head<&'a [u8], P> {
366 pub fn authority(&self) -> Option<&'a [u8]> {
367 self.authority.span().map(|span| {
368 unsafe { self.owner.get_unchecked(span.start()..span.end()) }
370 })
371 }
372}