sark_http/field/text/
mod.rs1pub mod percent;
4
5pub(crate) const fn hex(byte: u8) -> Option<u8> {
6 match byte {
7 b'0'..=b'9' => Some(byte - b'0'),
8 b'a'..=b'f' => Some(byte - b'a' + 10),
9 b'A'..=b'F' => Some(byte - b'A' + 10),
10 _ => None,
11 }
12}
13
14pub struct Ascii<'a> {
15 bytes: &'a [u8],
16}
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq)]
19pub enum IntError {
20 Empty,
21 InvalidByte,
22 Overflow,
23}
24
25impl<'a> Ascii<'a> {
26 pub const fn new(bytes: &'a [u8]) -> Self {
27 Self { bytes }
28 }
29
30 pub fn parse_usize(&self) -> Result<usize, IntError> {
31 let (value, end) = self.parse_prefix()?;
32 if end != self.bytes.len() {
33 return Err(IntError::InvalidByte);
34 }
35 Ok(value)
36 }
37
38 pub fn parse_prefix(&self) -> Result<(usize, usize), IntError> {
39 parse(self.bytes, 0usize, |value, digit| {
40 value.checked_mul(10)?.checked_add(usize::from(digit))
41 })
42 }
43
44 pub fn parse_u64(&self) -> Result<u64, IntError> {
45 let (value, end) = parse(self.bytes, 0u64, |value, digit| {
46 value.checked_mul(10)?.checked_add(u64::from(digit))
47 })?;
48 if end != self.bytes.len() {
49 return Err(IntError::InvalidByte);
50 }
51 Ok(value)
52 }
53}
54
55fn parse<T>(
56 bytes: &[u8],
57 zero: T,
58 mut push: impl FnMut(T, u8) -> Option<T>,
59) -> Result<(T, usize), IntError> {
60 if bytes.is_empty() {
61 return Err(IntError::Empty);
62 }
63
64 let mut value = zero;
65 let mut end = 0usize;
66 for &byte in bytes {
67 if !byte.is_ascii_digit() {
68 break;
69 }
70 value = push(value, byte - b'0').ok_or(IntError::Overflow)?;
71 end += 1;
72 }
73 if end == 0 {
74 return Err(IntError::InvalidByte);
75 }
76 Ok((value, end))
77}