TLA Line data Source code
1 : //! Small parsing helpers.
2 :
3 : use std::ffi::CStr;
4 :
5 CBC 36 : pub fn split_cstr(bytes: &[u8]) -> Option<(&CStr, &[u8])> {
6 456 : let pos = bytes.iter().position(|&x| x == 0)?;
7 34 : let (cstr, other) = bytes.split_at(pos + 1);
8 34 : // SAFETY: we've already checked that there's a terminator
9 34 : Some((unsafe { CStr::from_bytes_with_nul_unchecked(cstr) }, other))
10 36 : }
11 :
12 : /// See <https://doc.rust-lang.org/std/primitive.slice.html#method.split_array_ref>.
13 35 : pub fn split_at_const<const N: usize>(bytes: &[u8]) -> Option<(&[u8; N], &[u8])> {
14 35 : (bytes.len() >= N).then(|| {
15 34 : let (head, tail) = bytes.split_at(N);
16 34 : (head.try_into().unwrap(), tail)
17 35 : })
18 35 : }
19 :
20 : #[cfg(test)]
21 : mod tests {
22 : use super::*;
23 :
24 1 : #[test]
25 1 : fn test_split_cstr() {
26 1 : assert!(split_cstr(b"").is_none());
27 1 : assert!(split_cstr(b"foo").is_none());
28 :
29 1 : let (cstr, rest) = split_cstr(b"\0").expect("uh-oh");
30 1 : assert_eq!(cstr.to_bytes(), b"");
31 1 : assert_eq!(rest, b"");
32 :
33 1 : let (cstr, rest) = split_cstr(b"foo\0bar").expect("uh-oh");
34 1 : assert_eq!(cstr.to_bytes(), b"foo");
35 1 : assert_eq!(rest, b"bar");
36 1 : }
37 :
38 1 : #[test]
39 1 : fn test_split_at_const() {
40 1 : assert!(split_at_const::<0>(b"").is_some());
41 1 : assert!(split_at_const::<1>(b"").is_none());
42 1 : assert!(matches!(split_at_const::<1>(b"ok"), Some((b"o", b"k"))));
43 1 : }
44 : }
|