sark_core/http/codec/encode/
wire.rs1use o3::buffer::Shared;
2
3pub struct Wire;
4
5impl Wire {
6 pub const fn decimal_len(mut n: usize) -> usize {
7 let mut len = 1;
8 while n >= 10 {
9 n /= 10;
10 len += 1;
11 }
12 len
13 }
14
15 pub fn write_dec(n: usize, buf: &mut [u8]) -> usize {
16 let len = Self::decimal_len(n);
17 let mut n = n;
18 let mut i = len;
19 loop {
20 i -= 1;
21 buf[i] = b'0' + (n % 10) as u8;
22 n /= 10;
23 if i == 0 {
24 return len;
25 }
26 }
27 }
28
29 pub fn write_hex(n: usize, buf: &mut [u8; 16]) -> usize {
30 if n == 0 {
31 buf[0] = b'0';
32 return 1;
33 }
34 let mut i = 16;
35 let mut val = n;
36 while val > 0 {
37 i -= 1;
38 buf[i] = b"0123456789abcdef"[val & 0xf];
39 val >>= 4;
40 }
41 buf.copy_within(i..16, 0);
42 16 - i
43 }
44
45 pub fn chunk_prefix(size: usize) -> ([u8; 18], usize) {
46 let mut hex = [0u8; 16];
47 let hex_len = Self::write_hex(size, &mut hex);
48 let mut out = [0u8; 18];
49 out[..hex_len].copy_from_slice(&hex[..hex_len]);
50 out[hex_len] = b'\r';
51 out[hex_len + 1] = b'\n';
52 (out, hex_len + 2)
53 }
54
55 pub fn chunk_frame(body: Shared) -> Shared {
56 let (prefix, prefix_len) = Self::chunk_prefix(body.len());
57 let capacity = prefix_len
58 .checked_add(body.len())
59 .and_then(|len| len.checked_add(2))
60 .expect("chunk frame length overflow");
61 let mut framed = o3::buffer::Owned::with_capacity(capacity);
62 framed.extend_from_slice(&prefix[..prefix_len]);
63 framed.extend_from_slice(&body);
64 framed.extend_from_slice(b"\r\n");
65 framed.freeze()
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::Wire;
72
73 #[test]
74 fn decimal_writer_matches_usize_display() {
75 for value in [0, 1, 9, 10, 99, 100, 999, 1_000, usize::MAX] {
76 let expected = value.to_string();
77 let mut out = [0u8; 20];
78 let written = Wire::write_dec(value, &mut out);
79 assert_eq!(written, Wire::decimal_len(value));
80 assert_eq!(&out[..written], expected.as_bytes());
81 }
82 }
83}