1#[must_use]
3pub const fn find(slice: &[u8], elem: u8) -> Option<usize> {
4 let mut idx = 0;
5 loop {
6 if idx == slice.len() {
7 return None;
8 }
9 if slice[idx] == elem {
10 return Some(idx);
11 }
12 idx += 1;
13 }
14}
15
16#[must_use]
19pub const fn is_cstr(slice: &[u8]) -> bool {
20 matches!(find(slice, 0), Some(nul_pos) if nul_pos + 1 == slice.len())
21}
22
23#[must_use]
25pub const fn contains_nul(slice: &[u8]) -> bool {
26 matches!(find(slice, 0), Some(_))
27}
28
29#[cfg(test)]
30mod tests {
31 use super::{contains_nul, find, is_cstr};
32
33 #[test]
34 fn find_nul_byte() {
35 assert_eq!(find(b"", 0), None);
36 assert_eq!(find(b"abc", 0), None);
37 assert_eq!(find(b"abc\xFFxyz", 0), None);
38
39 assert_eq!(find(b"abc\0xyz", 0), Some(3));
40 assert_eq!(find(b"abc\0xyz\0", 0), Some(3));
41 assert_eq!(find(b"abc\xFF\0xyz", 0), Some(4));
42 assert_eq!(find(b"abc\xFF\0xyz\0", 0), Some(4));
43
44 assert_eq!(find(b"\0", 0), Some(0));
45 assert_eq!(find(b"abc\0", 0), Some(3));
46 assert_eq!(find(b"abc\xFFxyz\0", 0), Some(7));
47 }
48
49 #[test]
50 fn check_is_cstr() {
51 assert!(!is_cstr(b""));
52 assert!(!is_cstr(b"abc"));
53 assert!(!is_cstr(b"abc\xFFxyz"));
54
55 assert!(!is_cstr(b"abc\0xyz"));
56 assert!(!is_cstr(b"abc\0xyz\0"));
57 assert!(!is_cstr(b"abc\xFF\0xyz"));
58 assert!(!is_cstr(b"abc\xFF\0xyz\0"));
59
60 assert!(is_cstr(b"\0"));
61 assert!(is_cstr(b"abc\0"));
62 assert!(is_cstr(b"abc\xFFxyz\0"));
63 }
64
65 #[test]
66 fn check_contains_nul_byte() {
67 assert!(!contains_nul(b""));
68 assert!(!contains_nul(b"abc"));
69 assert!(!contains_nul(b"abc\xFFxyz"));
70
71 assert!(contains_nul(b"abc\0xyz"));
72 assert!(contains_nul(b"abc\0xyz\0"));
73 assert!(contains_nul(b"abc\xFF\0xyz"));
74 assert!(contains_nul(b"abc\xFF\0xyz\0"));
75
76 assert!(contains_nul(b"\0"));
77 assert!(contains_nul(b"abc\0"));
78 assert!(contains_nul(b"abc\xFFxyz\0"));
79 }
80}