Skip to main content

sark_core/request/
path.rs

1//! Request target capture access.
2
3use std::{mem, ops};
4
5#[repr(u8)]
6#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7pub enum Error {
8    Order {
9        start: usize,
10        end: usize,
11        capacity: usize,
12    },
13    Bounds {
14        start: usize,
15        end: usize,
16        capacity: usize,
17    },
18}
19
20pub struct Target<'a> {
21    raw: &'a [u8],
22}
23
24/// An admitted path slice retaining its offset within the route path.
25pub struct Capture<'a> {
26    value: &'a [u8],
27    start: usize,
28}
29
30impl<'a> Capture<'a> {
31    pub(in crate::request) const fn new(value: &'a [u8], start: usize) -> Self {
32        Self { value, start }
33    }
34
35    pub const fn as_bytes(&self) -> &'a [u8] {
36        self.value
37    }
38
39    pub const fn range(&self) -> ops::Range<usize> {
40        self.start..self.start + self.value.len()
41    }
42}
43
44impl<'a> Target<'a> {
45    pub const fn new(raw: &'a [u8]) -> Self {
46        Self { raw }
47    }
48
49    pub fn get(&self, range: ops::Range<usize>) -> Result<&'a [u8], Error> {
50        let start = range.start;
51        let end = range.end;
52        let capacity = self.raw.len();
53        if start > end {
54            return Err(Error::Order {
55                start,
56                end,
57                capacity,
58            });
59        }
60        self.raw.get(start..end).ok_or(Error::Bounds {
61            start,
62            end,
63            capacity,
64        })
65    }
66
67    pub fn try_capture(&self, range: ops::Range<usize>) -> Result<Capture<'a>, Error> {
68        let start = range.start;
69        Ok(Capture::new(self.get(range)?, start))
70    }
71}
72
73const _: () = {
74    assert!(mem::size_of::<Target<'_>>() == mem::size_of::<&[u8]>());
75    assert!(mem::size_of::<Capture<'_>>() == 3 * mem::size_of::<usize>());
76    assert!(mem::size_of::<Error>() == mem::size_of::<usize>() * 4);
77    assert!(!mem::needs_drop::<Error>());
78};