sark_http/h1/codec/
numbers.rs1use std::num::NonZero;
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq)]
4pub enum Error {
5 Overflow {
6 current: usize,
7 added: NonZero<usize>,
8 },
9 Capacity {
10 required: NonZero<usize>,
11 actual: usize,
12 },
13}
14
15pub trait Wire {
16 fn decimal_len(self) -> NonZero<usize>;
17
18 fn decimal(self, buf: &mut [u8; 20]) -> &[u8];
20
21 fn try_write(self, buf: &mut [u8], offset: usize) -> Result<NonZero<usize>, Error>;
24}
25
26impl Wire for usize {
27 fn decimal_len(mut self) -> NonZero<usize> {
28 let mut len = NonZero::<usize>::MIN;
29 while self >= 10 {
30 self /= 10;
31 len = len.saturating_add(1);
32 }
33 len
34 }
35
36 fn decimal(mut self, buf: &mut [u8; 20]) -> &[u8] {
37 let mut start = buf.len();
38 loop {
39 start -= 1;
40 buf[start] = take(&mut self);
41 if self == 0 {
42 return &buf[start..];
43 }
44 }
45 }
46
47 fn try_write(self, buf: &mut [u8], offset: usize) -> Result<NonZero<usize>, Error> {
48 let width = self.decimal_len();
49 let end = width.checked_add(offset).ok_or(Error::Overflow {
50 current: offset,
51 added: width,
52 })?;
53 let actual = buf.len();
54 let digits = buf.get_mut(offset..end.get()).ok_or(Error::Capacity {
55 required: end,
56 actual,
57 })?;
58 let mut value = self;
59 for digit in digits.iter_mut().rev() {
60 *digit = take(&mut value);
61 }
62 Ok(end)
63 }
64}
65
66fn take(value: &mut usize) -> u8 {
67 let digit = b'0' + (*value % 10) as u8;
68 *value /= 10;
69 digit
70}
71
72const _: () = assert!(usize::BITS <= u64::BITS);