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
128#[derive(Clone)]
130pub struct ArrayVec<T, const N: usize> {
131 len: usize,
132 arr: [T; N],
133}
134
135impl<T: PartialEq, const N: usize> PartialEq for ArrayVec<T, N> {
136 fn eq(&self, other: &Self) -> bool {
137 self[..] == other[..]
138 }
139}
140
141impl<T: Eq, const N: usize> Eq for ArrayVec<T, N> {}
142
143impl<T: Default, const N: usize> Default for ArrayVec<T, N> {
144 fn default() -> Self {
145 Self::from_fn(|_| T::default())
146 }
147}
148
149impl<T, const N: usize> Deref for ArrayVec<T, N> {
150 type Target = [T];
151
152 fn deref(&self) -> &Self::Target {
153 &self.arr[..self.len]
154 }
155}
156
157impl<T, const N: usize> DerefMut for ArrayVec<T, N> {
158 fn deref_mut(&mut self) -> &mut Self::Target {
159 &mut self.arr[..self.len]
160 }
161}
162
163impl<T, const N: usize> ArrayVec<T, N> {
164 pub fn from_fn(cb: impl FnMut(usize) -> T) -> Self {
168 Self {
169 len: 0,
170 arr: std::array::from_fn(cb),
171 }
172 }
173
174 pub fn push(&mut self, value: T) {
178 self.arr[self.len] = value;
179 self.len += 1;
180 }
181
182 pub fn try_push(&mut self, value: T) -> Result<(), CapacityError<T>> {
186 if self.len >= N {
187 return Err(CapacityError { element: value });
188 }
189 self.push(value);
190 Ok(())
191 }
192
193 pub fn truncate(&mut self, len: usize) {
197 assert!(len <= self.len);
198 self.len = len;
199 }
200}
201
202#[derive(PartialEq, Eq, Clone)]
204pub struct CapacityError<T> {
205 element: T,
207}
208
209impl<T> CapacityError<T> {
210 pub fn element(self) -> T {
212 self.element
213 }
214}
215
216impl<T> std::error::Error for CapacityError<T> {}
217
218impl<T> fmt::Debug for CapacityError<T> {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 f.debug_struct("CapacityError").finish()
221 }
222}
223
224impl<T> fmt::Display for CapacityError<T> {
225 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226 write!(f, "ArrayVec capacity exceeded")
227 }
228}
229
230impl<T, const N: usize> fmt::Debug for ArrayVec<T, N>
231where
232 T: fmt::Debug,
233{
234 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
235 f.debug_struct("ArrayVec")
236 .field("len", &self.len)
237 .field("arr", &&self.arr[..self.len])
238 .finish()
239 }
240}
241
242impl<'a, T, const N: usize> IntoIterator for &'a ArrayVec<T, N> {
243 type Item = &'a T;
244 type IntoIter = core::slice::Iter<'a, T>;
245
246 fn into_iter(self) -> Self::IntoIter {
247 self[..self.len].iter()
248 }
249}
250
251#[cfg(test)]
252mod tests {
253 use super::{ArrayVec, CapacityError};
254
255 #[test]
256 fn array_vec_equality_uses_active_elements() {
257 let mut a = ArrayVec::<_, 4>::from_fn(|_| 0);
258 let mut b = ArrayVec::<_, 4>::from_fn(|_| 99);
259 assert_eq!(a, b);
260
261 a.push(1);
262 b.push(1);
263 assert_eq!(a, b);
264
265 b.push(2);
266 assert_ne!(a, b);
267 b.truncate(1);
268 assert_eq!(a, b);
269
270 b[0] = 3;
271 assert_ne!(a, b);
272
273 fn assert_eq_trait<T: Eq>() {}
274 assert_eq_trait::<ArrayVec<i32, 4>>();
275 }
276
277 #[test]
278 fn array_vec_partial_eq_supports_non_eq_elements() {
279 let mut a = ArrayVec::<f32, 1>::default();
280 a.push(f32::NAN);
281 assert_ne!(a, a);
282 }
283
284 #[test]
285 fn array_vec_default_supports_non_copy_elements_and_large_capacities() {
286 let mut values = ArrayVec::<String, 64>::default();
287 assert!(values.is_empty());
288 for i in 0..64 {
289 values.push(i.to_string());
290 }
291 assert_eq!(values.len(), 64);
292 assert_eq!(values[63], "63");
293 }
294
295 #[test]
296 fn array_vec_default_supports_zero_capacity() {
297 let values = ArrayVec::<String, 0>::default();
298 assert!(values.is_empty());
299 assert_eq!(values, ArrayVec::from_fn(|_| String::from("unused")));
300 }
301
302 #[test]
303 fn array_vec_try_push_checks_capacity() {
304 let mut values = ArrayVec::<_, 4>::default();
305 for i in 0..4 {
306 values.try_push(i).unwrap();
307 }
308 let err = values.try_push(1337).unwrap_err();
309 assert_eq!(err, CapacityError { element: 1337 });
310 }
311}