str_utils/
starts_with_ignore_ascii_case.rs

1/// To extend types which implement `AsRef<[u8]>` to have `starts_with_ignore_ascii_case`, `starts_with_ignore_ascii_case_with_lowercase` and `starts_with_ignore_ascii_case_with_uppercase` methods.
2pub trait StartsWithIgnoreAsciiCase {
3    /// Returns `true` if the given string slice case-insensitively (only ignoring ASCII case) matches a prefix of this string slice.
4    fn starts_with_ignore_ascii_case<S: AsRef<[u8]>>(&self, b: S) -> bool;
5
6    /// Returns `true` if the given lowercase string slice case-insensitively (only ignoring ASCII case) matches a prefix of this string slice.
7    fn starts_with_ignore_ascii_case_with_lowercase<S: AsRef<[u8]>>(&self, b: S) -> bool;
8
9    /// Returns `true` if the given uppercase string slice case-insensitively (only ignoring ASCII case) matches a prefix of this string slice.
10    fn starts_with_ignore_ascii_case_with_uppercase<S: AsRef<[u8]>>(&self, b: S) -> bool;
11}
12
13impl<T: AsRef<[u8]>> StartsWithIgnoreAsciiCase for T {
14    #[inline]
15    fn starts_with_ignore_ascii_case<S: AsRef<[u8]>>(&self, b: S) -> bool {
16        let b = b.as_ref();
17
18        let b_length = b.len();
19
20        if b_length == 0 {
21            return true;
22        }
23
24        let a = self.as_ref();
25
26        let a_length = a.len();
27
28        if a_length >= b_length {
29            unsafe { a.get_unchecked(..b_length) }.eq_ignore_ascii_case(b)
30        } else {
31            false
32        }
33    }
34
35    #[inline]
36    fn starts_with_ignore_ascii_case_with_lowercase<S: AsRef<[u8]>>(&self, b: S) -> bool {
37        let b = b.as_ref();
38
39        debug_assert!(!b.iter().any(|e| e.is_ascii_uppercase()));
40
41        let b_length = b.len();
42
43        if b_length == 0 {
44            return true;
45        }
46
47        let a = self.as_ref();
48
49        let a_length = a.len();
50
51        if a_length >= b_length {
52            !unsafe { a.get_unchecked(..b_length) }
53                .iter()
54                .map(|e| e.to_ascii_lowercase())
55                .zip(b.iter().copied())
56                .any(|(ac, bc)| ac != bc)
57        } else {
58            false
59        }
60    }
61
62    #[inline]
63    fn starts_with_ignore_ascii_case_with_uppercase<S: AsRef<[u8]>>(&self, b: S) -> bool {
64        let b = b.as_ref();
65
66        debug_assert!(!b.iter().any(|e| e.is_ascii_lowercase()));
67
68        let b_length = b.len();
69
70        if b_length == 0 {
71            return true;
72        }
73
74        let a = self.as_ref();
75
76        let a_length = a.len();
77
78        if a_length >= b_length {
79            !unsafe { a.get_unchecked(..b_length) }
80                .iter()
81                .map(|e| e.to_ascii_uppercase())
82                .zip(b.iter().copied())
83                .any(|(ac, bc)| ac != bc)
84        } else {
85            false
86        }
87    }
88}