sark_http/request/
span.rs1use core::{num::NonZero, ops};
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq)]
4pub enum Error {
5 Order {
6 start: usize,
7 end: usize,
8 },
9 Overflow {
10 start: usize,
11 len: usize,
12 },
13 Bounds {
14 start: usize,
15 len: usize,
16 },
17 Shift {
18 start: usize,
19 len: usize,
20 base: usize,
21 },
22}
23
24#[derive(Clone, Copy, Debug, PartialEq, Eq)]
26pub struct Span {
27 start_plus_one: NonZero<u32>,
28 len: u32,
29}
30
31impl Span {
32 pub(crate) const fn from_target(target: super::Target) -> Self {
33 Self::pack(target.start(), target.len())
34 }
35
36 pub fn checked(start: usize, len: usize) -> Result<Self, Error> {
37 let Some(end) = start.checked_add(len) else {
38 return Err(Error::Overflow { start, len });
39 };
40 if start >= u32::MAX as usize || end > u32::MAX as usize {
41 return Err(Error::Bounds { start, len });
42 }
43 Ok(Self::pack(start, len))
44 }
45
46 pub(crate) const fn from_start(len: u32) -> Self {
51 Self::pack(0, len as usize)
52 }
53
54 pub fn from_range(range: ops::Range<usize>) -> Result<Self, Error> {
55 let Some(len) = range.end.checked_sub(range.start) else {
56 return Err(Error::Order {
57 start: range.start,
58 end: range.end,
59 });
60 };
61 if range.start >= u32::MAX as usize || range.end > u32::MAX as usize {
62 return Err(Error::Bounds {
63 start: range.start,
64 len,
65 });
66 }
67 Ok(Self::pack(range.start, len))
68 }
69
70 pub const fn start(self) -> usize {
71 (self.start_plus_one.get() - 1) as usize
72 }
73
74 pub const fn len(self) -> usize {
75 self.len as usize
76 }
77
78 pub const fn is_empty(self) -> bool {
79 self.len == 0
80 }
81
82 pub const fn end(self) -> usize {
83 self.start() + self.len()
84 }
85
86 pub(crate) const fn shifted_to(self, start: NonZero<u32>) -> Self {
91 Self {
92 start_plus_one: start,
93 len: self.len,
94 }
95 }
96
97 pub fn get(self, input: &[u8]) -> Option<&[u8]> {
98 input.get(self.start()..self.end())
99 }
100
101 pub fn shifted(self, base: usize) -> Result<Self, Error> {
102 let start = self.start();
103 let len = self.len();
104 let Some(shifted) = base.checked_add(start) else {
105 return Err(Error::Shift { start, len, base });
106 };
107 let Some(end) = shifted.checked_add(len) else {
108 return Err(Error::Shift { start, len, base });
109 };
110 if shifted >= u32::MAX as usize || end > u32::MAX as usize {
111 return Err(Error::Shift { start, len, base });
112 }
113 Ok(Self::pack(shifted, len))
114 }
115
116 const fn pack(start: usize, len: usize) -> Self {
118 Self {
119 start_plus_one: NonZero::<u32>::MIN.saturating_add(start as u32),
120 len: len as u32,
121 }
122 }
123}
124
125impl Default for Span {
126 fn default() -> Self {
127 Self::from_start(0)
128 }
129}
130
131#[derive(Clone, Copy)]
135pub(crate) struct Retained<'owner> {
136 bytes: &'owner [u8],
137 span: Span,
138}
139
140impl<'owner> Retained<'owner> {
141 pub(crate) fn try_new(owner: &'owner [u8], range: ops::Range<u32>) -> Result<Self, Error> {
142 let span = Span::from_range(range.start as usize..range.end as usize)?;
143 let start = span.start();
144 let bytes = owner.get(start..span.end()).ok_or(Error::Bounds {
145 start,
146 len: span.len(),
147 })?;
148 Ok(Self { bytes, span })
149 }
150
151 pub(crate) const fn bytes(self) -> &'owner [u8] {
152 self.bytes
153 }
154
155 pub(crate) const fn span(self) -> Span {
156 self.span
157 }
158}
159
160const _: () = {
161 assert!(core::mem::size_of::<Span>() == 8);
162 assert!(core::mem::size_of::<Option<Span>>() == 8);
163};