1use std::fmt;
2use std::io::{self, Cursor};
3use std::ops::{Deref, DerefMut};
4
5pub(crate) fn find_crlf(b: &[u8]) -> Option<usize> {
6 let cr = b.iter().position(|c| *c == b'\r')?;
7 let maybe_lf = b.get(cr + 1)?;
8 if *maybe_lf == b'\n' { Some(cr) } else { None }
9}
10
11pub(crate) fn compare_lowercase_ascii(a: &str, lowercased: &str) -> bool {
12 if a.len() != lowercased.len() {
13 return false;
14 }
15
16 for (a, b) in a.chars().zip(lowercased.chars()) {
17 if !a.is_ascii() {
18 return false;
19 }
20 let norm = a.to_ascii_lowercase();
21 if norm != b {
22 return false;
23 }
24 }
25
26 true
27}
28
29pub(crate) struct Writer<'a>(pub Cursor<&'a mut [u8]>);
30
31impl<'a> Writer<'a> {
32 pub(crate) fn new(output: &'a mut [u8]) -> Writer<'a> {
33 Self(Cursor::new(output))
34 }
35
36 pub fn len(&self) -> usize {
37 self.0.position() as usize
38 }
39
40 pub fn available(&self) -> usize {
41 self.0.get_ref().len() - self.len()
42 }
43
44 pub(crate) fn try_write(&mut self, block: impl Fn(&mut Self) -> io::Result<()>) -> bool {
45 let pos = self.0.position();
46 let success = (block)(self).is_ok();
47 if !success {
48 self.0.set_position(pos);
49 }
50 success
51 }
52}
53
54impl<'a> io::Write for Writer<'a> {
55 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
56 self.0.write(buf)
57 }
58
59 fn flush(&mut self) -> io::Result<()> {
60 self.0.flush()
61 }
62}
63
64const CHARS_PER_ROW: usize = 16;
65
66impl<'a> Drop for Writer<'a> {
67 fn drop(&mut self) {
68 let len = self.len();
69 log_data(&self.0.get_ref()[..len]);
70 }
71}
72
73pub(crate) fn log_data(data: &[u8]) {
74 for row in data.chunks(CHARS_PER_ROW) {
75 trace!("{:?}", Row(row))
76 }
77}
78
79struct Row<'a>(&'a [u8]);
80
81impl<'a> fmt::Debug for Row<'a> {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 for i in 0..CHARS_PER_ROW {
84 if let Some(v) = self.0.get(i) {
85 write!(f, "{}", HEX[*v as usize])?
86 } else {
87 write!(f, "--")?;
88 }
89 if i % 2 == 1 {
90 write!(f, " ")?;
91 }
92 }
93 write!(f, " ")?;
94 for i in 0..CHARS_PER_ROW {
95 if let Some(v) = self.0.get(i) {
96 if v.is_ascii_alphanumeric() || v.is_ascii_punctuation() {
97 write!(f, "{}", *v as char)?;
98 } else {
99 write!(f, ".")?;
100 }
101 } else {
102 write!(f, ".")?;
103 }
104 }
105 Ok(())
106 }
107}
108
109const HEX: [&str; 256] = [
110 "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
111 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
112 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
113 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
114 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
115 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
116 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
117 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
118 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
119 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
120 "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
121 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
122 "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
123 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
124 "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
125 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff",
126];
127
128pub struct ArrayVec<T, const N: usize> {
130 len: usize,
131 arr: [T; N],
132}
133
134impl<T, const N: usize> Deref for ArrayVec<T, N> {
135 type Target = [T];
136
137 fn deref(&self) -> &Self::Target {
138 &self.arr[..self.len]
139 }
140}
141
142impl<T, const N: usize> DerefMut for ArrayVec<T, N> {
143 fn deref_mut(&mut self) -> &mut Self::Target {
144 &mut self.arr[..self.len]
145 }
146}
147
148impl<T, const N: usize> ArrayVec<T, N> {
149 pub fn from_fn(cb: impl FnMut(usize) -> T) -> Self {
153 Self {
154 len: 0,
155 arr: std::array::from_fn(cb),
156 }
157 }
158
159 pub fn push(&mut self, value: T) {
161 self.arr[self.len] = value;
162 self.len += 1;
163 }
164
165 pub fn truncate(&mut self, len: usize) {
169 assert!(len <= self.len);
170 self.len = len;
171 }
172}
173
174impl<T, const N: usize> fmt::Debug for ArrayVec<T, N>
175where
176 T: fmt::Debug,
177{
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 f.debug_struct("ArrayVec")
180 .field("len", &self.len)
181 .field("arr", &&self.arr[..self.len])
182 .finish()
183 }
184}
185
186impl<'a, T, const N: usize> IntoIterator for &'a ArrayVec<T, N> {
187 type Item = &'a T;
188 type IntoIter = core::slice::Iter<'a, T>;
189
190 fn into_iter(self) -> Self::IntoIter {
191 self[..self.len].iter()
192 }
193}