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}