ttpkit_utils/
ascii.rs

1//! ASCII helpers.
2
3use bytes::Bytes;
4
5/// ASCII extensions.
6pub trait AsciiExt {
7    /// Split the current slice once by a given separator predicate.
8    fn split_once<F>(&self, separator: F) -> Option<(Self, Self)>
9    where
10        F: FnMut(u8) -> bool,
11        Self: Sized;
12
13    /// Trim ASCII whitespace from the start of the current slice.
14    fn trim_ascii_start(&self) -> Self;
15
16    /// Trim ASCII whitespace from the end of the current slice.
17    fn trim_ascii_end(&self) -> Self;
18
19    /// Trim ASCII whitespace from both ends of the current slice.
20    fn trim_ascii(&self) -> Self
21    where
22        Self: Sized,
23    {
24        self.trim_ascii_start().trim_ascii_end()
25    }
26}
27
28impl AsciiExt for Bytes {
29    fn split_once<F>(&self, mut pred: F) -> Option<(Self, Self)>
30    where
31        F: FnMut(u8) -> bool,
32    {
33        self.iter().position(|&b| pred(b)).map(|idx| {
34            let start = self.slice(..idx);
35            let end = self.slice(idx + 1..);
36
37            (start, end)
38        })
39    }
40
41    fn trim_ascii_start(&self) -> Self {
42        let start = self
43            .iter()
44            .position(|&b| !b.is_ascii_whitespace())
45            .unwrap_or(self.len());
46
47        self.slice(start..)
48    }
49
50    fn trim_ascii_end(&self) -> Self {
51        let end = self
52            .iter()
53            .rposition(|&b| !b.is_ascii_whitespace())
54            .unwrap_or(usize::MAX)
55            .wrapping_add(1);
56
57        self.slice(..end)
58    }
59}