falco_event/types/string/
cstr.rs1use crate::fields::{FromBytes, FromBytesError, ToBytes};
2use crate::types::ByteBufFormatter;
3use std::ffi::CStr;
4use std::fmt::{Debug, Formatter};
5use std::io::Write;
6
7impl<'a> FromBytes<'a> for &'a CStr {
8 #[inline]
9 fn from_bytes(buf: &mut &'a [u8]) -> Result<Self, FromBytesError> {
10 let cstr = CStr::from_bytes_until_nul(buf).map_err(|_| FromBytesError::MissingNul)?;
11 let len = cstr.to_bytes().len();
12 *buf = &buf[len + 1..];
13 Ok(cstr)
14 }
15}
16
17impl ToBytes for &CStr {
18 #[inline]
19 fn binary_size(&self) -> usize {
20 self.to_bytes().len() + 1
21 }
22
23 #[inline]
24 fn write<W: Write>(&self, mut writer: W) -> std::io::Result<()> {
25 writer.write_all(self.to_bytes_with_nul())
26 }
27
28 #[inline]
29 fn default_repr() -> impl ToBytes {
30 0u8
31 }
32}
33
34pub struct CStrFormatter<'a>(pub &'a CStr);
39
40impl Debug for CStrFormatter<'_> {
41 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
42 Debug::fmt(&ByteBufFormatter(self.0.to_bytes()), f)
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use crate::fields::{FromBytes, ToBytes};
49 use std::ffi::CStr;
50
51 #[test]
52 fn test_cstr() {
53 let s = CStr::from_bytes_until_nul(b"foo\0").unwrap();
54
55 let mut binary = Vec::new();
56 s.write(&mut binary).unwrap();
57
58 hexdump::hexdump(binary.as_slice());
59
60 assert_eq!(binary.as_slice(), b"foo\0".as_slice());
61
62 let mut buf = binary.as_slice();
63 let s2 = <&CStr>::from_bytes(&mut buf).unwrap();
64
65 assert_eq!(s2.to_bytes_with_nul(), b"foo\0".as_slice());
66 assert_eq!(buf.len(), 0);
67 }
68}