1use std::{mem, ops};
4
5use o3::{
6 alloc,
7 buffer::{storage, write::consume},
8};
9use sark_http::{
10 field::text::{Ascii, IntError},
11 h1::field::Entry,
12 request::span,
13};
14
15use crate::request::path;
16
17pub trait Prefix<S: Copy>: Sized {
19 type Output;
20
21 fn rest(&self) -> &[u8];
22
23 fn user(self, slot: S, colon: usize) -> Self::Output;
24
25 fn miss(self, start: usize) -> Self::Output;
26
27 fn short(self) -> Self::Output;
28}
29
30#[repr(u8)]
31#[derive(Clone, Copy, Debug, PartialEq, Eq)]
32pub enum Error {
33 Capacity(consume::Error),
34 Exhausted(alloc::Exhausted),
35 Path(path::Error),
36 Span(span::Error),
37 Integer {
38 start: usize,
39 end: usize,
40 cause: IntError,
41 },
42 Boolean {
43 start: usize,
44 end: usize,
45 },
46 Order {
47 start: usize,
48 end: usize,
49 capacity: usize,
50 },
51 Bounds {
52 start: usize,
53 end: usize,
54 capacity: usize,
55 },
56 AcceptEncoding(sark_http::field::head::Error),
57}
58
59impl From<storage::AllocError> for Error {
60 fn from(error: storage::AllocError) -> Self {
61 match error {
62 storage::AllocError::Capacity(error) => Self::Capacity(error),
63 storage::AllocError::Exhausted(error) => Self::Exhausted(error),
64 }
65 }
66}
67
68pub trait HeaderValue: AsRef<[u8]> {
69 fn try_span(&self) -> Result<span::Span, Error>;
70}
71
72impl HeaderValue for storage::Shared {
73 fn try_span(&self) -> Result<span::Span, Error> {
74 span::Span::checked(0, self.len()).map_err(Error::Span)
75 }
76}
77
78pub struct SliceValue<'a> {
79 value: &'a [u8],
80 span: span::Span,
81}
82
83impl<'a> From<Entry<'a>> for SliceValue<'a> {
84 fn from(entry: Entry<'a>) -> Self {
85 Self {
86 value: entry.value(),
87 span: entry.value_span(),
88 }
89 }
90}
91
92impl<'a> SliceValue<'a> {
93 pub fn try_slice(value: &'a [u8], start: usize) -> Result<Self, Error> {
94 let span = span::Span::checked(start, value.len()).map_err(Error::Span)?;
95 Ok(Self { value, span })
96 }
97
98 pub fn try_new(raw: &'a [u8], range: ops::Range<usize>) -> Result<Self, Error> {
99 let start = range.start;
100 let end = range.end;
101 let capacity = raw.len();
102 if start > end {
103 return Err(Error::Order {
104 start,
105 end,
106 capacity,
107 });
108 }
109 let value = raw.get(start..end).ok_or(Error::Bounds {
110 start,
111 end,
112 capacity,
113 })?;
114 let span = span::Span::from_range(start..end).map_err(Error::Span)?;
115 Ok(Self { value, span })
116 }
117
118 pub fn try_at(raw: &'a [u8], span: span::Span) -> Result<Self, Error> {
119 let start = span.start();
120 let end = span.end();
121 let value = raw.get(start..end).ok_or(Error::Bounds {
122 start,
123 end,
124 capacity: raw.len(),
125 })?;
126 Ok(Self { value, span })
127 }
128}
129
130impl HeaderValue for SliceValue<'_> {
131 fn try_span(&self) -> Result<span::Span, Error> {
132 Ok(self.span)
133 }
134}
135
136impl AsRef<[u8]> for SliceValue<'_> {
137 fn as_ref(&self) -> &[u8] {
138 self.value
139 }
140}
141
142pub trait Value: Sized {
143 fn parse_value<V: HeaderValue>(value: &V) -> Result<Self, Error>;
144}
145
146pub trait Path: Sized {
147 fn try_parse(path: &path::Target<'_>, range: ops::Range<usize>) -> Result<Self, Error> {
148 Self::parse(path.try_capture(range).map_err(Error::Path)?)
149 }
150
151 fn parse(capture: path::Capture<'_>) -> Result<Self, Error>;
152}
153
154impl Value for storage::Shared {
155 fn parse_value<V: HeaderValue>(value: &V) -> Result<Self, Error> {
156 storage::Shared::try_copy(value.as_ref()).map_err(Error::from)
157 }
158}
159
160impl Value for usize {
161 fn parse_value<V: HeaderValue>(value: &V) -> Result<Self, Error> {
162 let span = value.try_span()?;
163 integer(
164 Ascii::new(value.as_ref()).parse_usize(),
165 span.start()..span.end(),
166 )
167 }
168}
169
170impl Path for usize {
171 fn parse(capture: path::Capture<'_>) -> Result<Self, Error> {
172 integer(
173 Ascii::new(capture.as_bytes()).parse_usize(),
174 capture.range(),
175 )
176 }
177}
178
179impl Value for u64 {
180 fn parse_value<V: HeaderValue>(value: &V) -> Result<Self, Error> {
181 let span = value.try_span()?;
182 integer(
183 Ascii::new(value.as_ref()).parse_u64(),
184 span.start()..span.end(),
185 )
186 }
187}
188
189impl Path for u64 {
190 fn parse(capture: path::Capture<'_>) -> Result<Self, Error> {
191 integer(Ascii::new(capture.as_bytes()).parse_u64(), capture.range())
192 }
193}
194
195impl Value for bool {
196 fn parse_value<V: HeaderValue>(value: &V) -> Result<Self, Error> {
197 let span = value.try_span()?;
198 boolean(value.as_ref(), span.start()..span.end())
199 }
200}
201
202impl Path for bool {
203 fn parse(capture: path::Capture<'_>) -> Result<Self, Error> {
204 boolean(capture.as_bytes(), capture.range())
205 }
206}
207
208fn integer<T>(value: Result<T, IntError>, range: ops::Range<usize>) -> Result<T, Error> {
209 value.map_err(|cause| Error::Integer {
210 start: range.start,
211 end: range.end,
212 cause,
213 })
214}
215
216fn boolean(value: &[u8], range: ops::Range<usize>) -> Result<bool, Error> {
217 if value.eq_ignore_ascii_case(b"true") || value == b"1" {
218 return Ok(true);
219 }
220 if value.eq_ignore_ascii_case(b"false") || value == b"0" {
221 return Ok(false);
222 }
223 Err(Error::Boolean {
224 start: range.start,
225 end: range.end,
226 })
227}
228
229const _: () = {
230 assert!(mem::size_of::<SliceValue<'_>>() == mem::size_of::<usize>() * 3);
231 assert!(mem::size_of::<Option<SliceValue<'_>>>() == mem::size_of::<SliceValue<'_>>());
232 assert!(mem::size_of::<Error>() == mem::size_of::<usize>() * 5);
233 assert!(mem::size_of::<Option<Error>>() == mem::size_of::<Error>());
234 assert!(mem::size_of::<Result<(), Error>>() == mem::size_of::<Error>());
235 assert!(!mem::needs_drop::<SliceValue<'_>>());
236 assert!(!mem::needs_drop::<Error>());
237};