1use core::{num::NonZero, ops};
2
3use crate::field::metadata::block;
4
5pub mod body;
6pub mod raw;
7pub mod span;
8
9mod bytes;
10mod id;
11mod segments;
12mod seq;
13mod source;
14
15pub use bytes::Bytes;
16pub use id::Id;
17pub use segments::Segments;
18pub use seq::Seq;
19pub use source::Source;
20use span::Span;
21
22#[derive(Clone, Copy, PartialEq, Eq)]
23#[repr(u8)]
24pub enum Form {
25 Path = 0,
26 Root = 1,
27 Asterisk = 2,
28 Authority = 3,
29 Extended = 4,
30}
31
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
33pub enum Error {
34 Span(span::Error),
35 InvalidRange,
36 OutOfBounds,
37 MissingAuthority,
38}
39
40impl From<span::Error> for Error {
41 fn from(error: span::Error) -> Self {
42 Self::Span(error)
43 }
44}
45
46#[derive(Clone, Copy, PartialEq, Eq)]
47pub struct Target {
48 packed_start_form_plus_one: NonZero<u32>,
49 len: u32,
50}
51
52const TARGET_LANE: usize = 16;
53
54fn target_lane_invalid<const N: usize>(lane: &[u8; N]) -> bool {
55 let mut invalid = false;
56 for &byte in lane {
57 invalid |= (byte <= 0x20) | (byte == 0x7f);
58 }
59 invalid
60}
61
62impl Target {
63 const FORM_BITS: u32 = 3;
64 const FORM_MASK: u32 = (1 << Self::FORM_BITS) - 1;
65
66 pub fn is_valid(bytes: &[u8]) -> bool {
67 let (blocks, tail) = bytes.as_chunks::<{ TARGET_LANE * 4 }>();
68 for block in blocks {
69 if target_lane_invalid(block) {
70 return false;
71 }
72 }
73 let (lanes, tail) = tail.as_chunks::<TARGET_LANE>();
74 for lane in lanes {
75 if target_lane_invalid(lane) {
76 return false;
77 }
78 }
79 tail.iter().all(|&byte| byte > 0x20 && byte != 0x7f)
80 }
81
82 pub const fn from_span(form: Form, span: Span) -> Result<Self, Error> {
83 let start = span.start();
84 if start >= (1usize << (u32::BITS - Self::FORM_BITS)) {
85 return Err(Error::OutOfBounds);
86 }
87 let packed = ((start as u32) << Self::FORM_BITS) | form as u32;
88 let packed = NonZero::<u32>::MIN.saturating_add(packed);
89 Ok(Self {
90 packed_start_form_plus_one: packed,
91 len: span.len() as u32,
92 })
93 }
94
95 pub const fn form(self) -> Form {
96 match (self.packed_start_form_plus_one.get() - 1) & Self::FORM_MASK {
97 0 => Form::Path,
98 1 => Form::Root,
99 2 => Form::Asterisk,
100 3 => Form::Authority,
101 4..=u32::MAX => Form::Extended,
102 }
103 }
104
105 pub const fn start(self) -> usize {
106 ((self.packed_start_form_plus_one.get() - 1) >> Self::FORM_BITS) as usize
107 }
108
109 pub const fn len(self) -> usize {
110 self.len as usize
111 }
112
113 pub const fn is_empty(self) -> bool {
114 self.len == 0
115 }
116
117 pub const fn end(self) -> usize {
118 self.start() + self.len()
119 }
120
121 pub fn get(self, input: &[u8]) -> Option<&[u8]> {
122 input.get(self.start()..self.end())
123 }
124}
125
126#[repr(C)]
127#[derive(Clone, Copy, PartialEq, Eq)]
128pub struct Layout {
129 target: Target,
130 authority: Option<Span>,
131 route: Option<Span>,
132}
133
134pub struct Bound<O> {
136 owner: O,
137 layout: Layout,
138}
139
140impl<O: Source> Bound<O> {
141 pub fn try_bind(owner: O, layout: Layout) -> Result<Self, Error> {
142 if !layout.is_valid(owner.as_ref()) {
143 return Err(Error::InvalidRange);
144 }
145 Ok(Self { owner, layout })
146 }
147}
148
149impl<O> Bound<O> {
150 pub fn into_parts(self) -> (O, Layout) {
151 (self.owner, self.layout)
152 }
153}
154
155impl Layout {
156 pub fn try_new(
160 form: Form,
161 target: Span,
162 peer: Option<Span>,
163 route: Option<Span>,
164 ) -> Result<Self, Error> {
165 let layout = Self::new(Target::from_span(form, target)?, peer, route);
166 if layout.is_shaped() {
167 Ok(layout)
168 } else {
169 Err(Error::InvalidRange)
170 }
171 }
172
173 pub const fn new(target: Target, peer: Option<Span>, route: Option<Span>) -> Self {
178 Self {
179 target,
180 authority: peer,
181 route,
182 }
183 }
184
185 fn from_kept(
186 owner: &[u8],
187 path: Option<ops::Range<usize>>,
188 path_len: Option<usize>,
189 pseudo: Option<ops::Range<usize>>,
190 host: Option<ops::Range<usize>>,
191 plan: block::Plan,
192 ) -> Result<Self, Error> {
193 let [path, pseudo, host] = checked_spans(owner, path, pseudo, host)?;
194 let layout = Self::from_spans(path, path_len, pseudo, host, plan)?;
195 if layout.checked(owner).is_some() {
196 Ok(layout)
197 } else {
198 Err(Error::InvalidRange)
199 }
200 }
201
202 fn from_spans(
203 path: Option<Span>,
204 path_len: Option<usize>,
205 pseudo: Option<Span>,
206 host: Option<Span>,
207 plan: block::Plan,
208 ) -> Result<Self, Error> {
209 let selected = match plan.authority() {
210 block::Authority::None => None,
211 block::Authority::Pseudo | block::Authority::Target => pseudo,
212 block::Authority::Host => host,
213 };
214 let (target, peer, route) = match plan.form() {
215 block::Form::Path | block::Form::ExtendedConnect => {
216 let target = path.ok_or(Error::InvalidRange)?;
217 let len = path_len.ok_or(Error::InvalidRange)?;
218 let route = Span::checked(target.start(), len).map_err(Error::Span)?;
219 (target, selected, Some(route))
220 }
221 block::Form::Asterisk => (path.ok_or(Error::InvalidRange)?, selected, None),
222 block::Form::Connect => (selected.ok_or(Error::MissingAuthority)?, None, None),
223 };
224 let form = match plan.form() {
225 block::Form::Path => Form::Path,
226 block::Form::Asterisk => Form::Asterisk,
227 block::Form::Connect => Form::Authority,
228 block::Form::ExtendedConnect => Form::Extended,
229 };
230 let target = Target::from_span(form, target)?;
231 Ok(Self::new(target, peer, route))
232 }
233
234 pub const fn target(self) -> Target {
235 self.target
236 }
237
238 pub const fn authority(self) -> Option<Span> {
239 if matches!(self.target.form(), Form::Authority) {
240 Some(Span::from_target(self.target))
241 } else {
242 self.authority
243 }
244 }
245
246 pub const fn route(self) -> Option<Span> {
247 self.route
248 }
249
250 pub fn route_path(self, owner: &[u8]) -> Option<&[u8]> {
251 match self.target.form() {
252 Form::Root => Some(b"/"),
253 Form::Asterisk | Form::Authority => Some(b"*"),
254 Form::Path | Form::Extended => self.route?.get(owner),
255 }
256 }
257
258 pub fn authority_in(self, owner: &[u8]) -> Option<&[u8]> {
259 self.authority()?.get(owner)
260 }
261
262 pub const fn require(self) -> Result<Self, Error> {
263 if matches!(self.target.form(), Form::Authority) || self.authority.is_some() {
264 Ok(self)
265 } else {
266 Err(Error::MissingAuthority)
267 }
268 }
269
270 const fn is_shaped(self) -> bool {
272 match self.target.form() {
273 Form::Path | Form::Extended => match self.route {
274 Some(route) => {
275 route.start() >= self.target.start() && route.end() <= self.target.end()
276 }
277 None => false,
278 },
279 Form::Root => match self.route {
280 Some(route) => {
281 route.is_empty()
282 && route.start() >= self.target.start()
283 && route.start() <= self.target.end()
284 }
285 None => false,
286 },
287 Form::Asterisk | Form::Authority => self.route.is_none(),
288 }
289 }
290
291 pub fn is_valid(self, owner: &[u8]) -> bool {
292 self.checked(owner).is_some_and(Target::is_valid)
293 }
294
295 fn checked(self, owner: &[u8]) -> Option<&[u8]> {
296 if !self.is_shaped() || self.authority.is_some_and(|span| span.end() > owner.len()) {
297 return None;
298 }
299 let target = self.target.get(owner)?;
300 let shaped = match self.target.form() {
301 Form::Path | Form::Extended => self.route.is_some_and(|route| {
302 route.end() == self.target.end() || owner.get(route.end()) == Some(&b'?')
303 }),
304 Form::Root => self.route.is_some_and(|route| {
305 route.start() == self.target.end() || owner.get(route.start()) == Some(&b'?')
306 }),
307 Form::Asterisk => target == b"*",
308 Form::Authority => true,
309 };
310 shaped.then_some(target)
311 }
312}
313
314fn checked_span(range: Option<ops::Range<usize>>) -> Result<Option<Span>, Error> {
315 range.map(Span::from_range).transpose().map_err(Error::Span)
316}
317
318fn checked_spans(
319 owner: &[u8],
320 path: Option<ops::Range<usize>>,
321 pseudo: Option<ops::Range<usize>>,
322 host: Option<ops::Range<usize>>,
323) -> Result<[Option<Span>; 3], Error> {
324 let path = checked_span(path)?;
325 let pseudo = checked_span(pseudo)?;
326 let host = checked_span(host)?;
327 if path.is_some_and(|span| span.end() > owner.len())
328 || pseudo.is_some_and(|span| span.end() > owner.len())
329 || host.is_some_and(|span| span.end() > owner.len())
330 {
331 return Err(Error::InvalidRange);
332 }
333 Ok([path, pseudo, host])
334}
335
336const _: () = assert!(core::mem::size_of::<Target>() == 8);
337const _: () = assert!(core::mem::size_of::<Option<Target>>() == 8);
338const _: () = assert!(core::mem::size_of::<Layout>() == 24);