1use core::str::Utf8Error;
4use thiserror::Error;
5
6#[derive(Debug, PartialEq, Eq, Clone, Error)]
8pub enum StringError {
9 #[error("string is not null terminated")]
12 MissingNul(#[source] core::ffi::FromBytesUntilNulError),
13 #[error("string is not valid UTF-8")]
15 Utf8(#[source] Utf8Error),
16}
17
18pub fn parse_slice_as_string(bytes: &[u8]) -> Result<&str, StringError> {
21 let cstr = core::ffi::CStr::from_bytes_until_nul(bytes).map_err(StringError::MissingNul)?;
22 cstr.to_str().map_err(StringError::Utf8)
23}
24
25#[cfg(test)]
26mod tests {
27 use super::*;
28
29 #[test]
30 fn test_parse_slice_as_string() {
31 assert!(matches!(
33 parse_slice_as_string(&[]),
34 Err(StringError::MissingNul(_))
35 ));
36 assert_eq!(parse_slice_as_string(&[0x00]), Ok(""));
38 assert!(matches!(
40 parse_slice_as_string(&[0xff, 0x00]),
41 Err(StringError::Utf8(_))
42 ));
43 assert!(matches!(
45 parse_slice_as_string(b"hello"),
46 Err(StringError::MissingNul(_))
47 ));
48 assert_eq!(parse_slice_as_string(b"hello\0"), Ok("hello"));
50 assert_eq!(parse_slice_as_string(b"hello\0\0"), Ok("hello"));
51 assert_eq!(parse_slice_as_string(b"hello\0foo"), Ok("hello"));
53 }
54}