const_str/
bytes.rs

1use crate::slice::subslice;
2
3use core::cmp::Ordering;
4
5pub const fn clone<const N: usize>(bytes: &[u8]) -> [u8; N] {
6    assert!(bytes.len() == N);
7    let mut buf = [0; N];
8    let mut i = 0;
9    while i < bytes.len() {
10        buf[i] = bytes[i];
11        i += 1;
12    }
13    buf
14}
15
16pub const fn equal(lhs: &[u8], rhs: &[u8]) -> bool {
17    if lhs.len() != rhs.len() {
18        return false;
19    }
20    let mut i = 0;
21    while i < lhs.len() {
22        if lhs[i] != rhs[i] {
23            return false;
24        }
25        i += 1;
26    }
27    true
28}
29
30pub const fn compare(lhs: &[u8], rhs: &[u8]) -> Ordering {
31    let lhs_len = lhs.len();
32    let rhs_len = rhs.len();
33    let min_len = if lhs_len < rhs_len { lhs_len } else { rhs_len };
34
35    let mut i = 0;
36    while i < min_len {
37        if lhs[i] < rhs[i] {
38            return Ordering::Less;
39        }
40        if lhs[i] > rhs[i] {
41            return Ordering::Greater;
42        }
43        i += 1;
44    }
45
46    if lhs_len < rhs_len {
47        Ordering::Less
48    } else if lhs_len > rhs_len {
49        Ordering::Greater
50    } else {
51        Ordering::Equal
52    }
53}
54
55pub const fn merge<const N: usize>(mut buf: [u8; N], bytes: &[u8]) -> [u8; N] {
56    assert!(N <= bytes.len());
57    let mut i = 0;
58    while i < bytes.len() {
59        buf[i] = bytes[i];
60        i += 1;
61    }
62    buf
63}
64
65pub const fn reversed<const N: usize>(mut arr: [u8; N]) -> [u8; N] {
66    let mut i = 0;
67    while i * 2 < N {
68        let a = arr[i];
69        let b = arr[N - 1 - i];
70        arr[i] = b;
71        arr[N - 1 - i] = a;
72        i += 1;
73    }
74    arr
75}
76
77pub const fn contains(haystack: &[u8], needle: &[u8]) -> bool {
78    let haystack_len = haystack.len();
79    let needle_len = needle.len();
80
81    let mut i = 0;
82    while i < haystack_len {
83        let mut j = 0;
84        while j < needle_len && i + j < haystack_len {
85            if haystack[i + j] != needle[j] {
86                break;
87            }
88            j += 1;
89        }
90        if j == needle_len {
91            return true;
92        }
93        i += 1;
94    }
95
96    false
97}
98
99pub const fn starts_with(haystack: &[u8], needle: &[u8]) -> bool {
100    let haystack_len = haystack.len();
101    let needle_len = needle.len();
102
103    if needle_len > haystack_len {
104        return false;
105    }
106
107    let mut i = 0;
108    while i < needle_len {
109        if haystack[i] != needle[i] {
110            break;
111        }
112        i += 1
113    }
114
115    i == needle_len
116}
117
118pub const fn ends_with(haystack: &[u8], needle: &[u8]) -> bool {
119    let haystack_len = haystack.len();
120    let needle_len = needle.len();
121
122    if needle_len > haystack_len {
123        return false;
124    }
125
126    let mut i = 0;
127    while i < needle_len {
128        if haystack[haystack_len - needle_len + i] != needle[i] {
129            break;
130        }
131        i += 1
132    }
133
134    i == needle_len
135}
136
137pub const fn strip_prefix<'s>(s: &'s [u8], prefix: &[u8]) -> Option<&'s [u8]> {
138    if starts_with(s, prefix) {
139        Some(subslice(s, prefix.len()..s.len()))
140    } else {
141        None
142    }
143}
144
145pub const fn strip_suffix<'s>(s: &'s [u8], suffix: &[u8]) -> Option<&'s [u8]> {
146    if ends_with(s, suffix) {
147        Some(subslice(s, 0..s.len() - suffix.len()))
148    } else {
149        None
150    }
151}
152
153#[cfg(test)]
154mod tests {
155    use super::*;
156
157    #[test]
158    fn test_reversed() {
159        let arr = [0, 1];
160        assert_eq!(reversed(arr), [1, 0]);
161
162        let arr = [0, 1, 2];
163        assert_eq!(reversed(arr), [2, 1, 0]);
164    }
165
166    #[test]
167    fn test_contains() {
168        macro_rules! test_contains {
169            (true, $haystack: expr, $needle: expr) => {
170                assert!(contains($haystack.as_ref(), $needle.as_ref()));
171            };
172            (false, $haystack: expr, $needle: expr) => {
173                assert!(!contains($haystack.as_ref(), $needle.as_ref()));
174            };
175        }
176
177        let buf = b"abcdefgh";
178        test_contains!(true, buf, b"");
179        test_contains!(true, buf, b"a");
180        test_contains!(true, buf, b"ef");
181        test_contains!(false, buf, b"xyz");
182
183        test_contains!(true, "asd", "");
184        test_contains!(true, "asd", "a");
185        test_contains!(true, "asdf", "sd");
186        test_contains!(false, "", "a");
187        test_contains!(false, "asd", "abcd");
188
189        test_contains!(true, "唐可可", "可");
190        test_contains!(true, "Liyuu", "i");
191        test_contains!(false, "Liyuu", "我");
192    }
193
194    #[test]
195    fn test_starts_with() {
196        assert!(starts_with(b"", b""));
197        assert!(starts_with(b"a", b""));
198        assert!(starts_with(b"a", b"a"));
199        assert!(!starts_with(b"", b"a"));
200        assert!(!starts_with(b"ba", b"a"));
201    }
202
203    #[test]
204    fn test_ends_with() {
205        assert!(ends_with(b"", b""));
206        assert!(ends_with(b"a", b""));
207        assert!(ends_with(b"a", b"a"));
208        assert!(!ends_with(b"", b"a"));
209        assert!(!ends_with(b"ab", b"a"));
210    }
211}