falco_event/types/string/
cstr_array.rs1use crate::fields::{FromBytes, FromBytesError, ToBytes};
2use crate::types::format::CStrFormatter;
3use std::ffi::CStr;
4use std::fmt::{Debug, Formatter, Write as _};
5use std::io::Write;
6
7#[derive(Copy, Clone)]
12pub struct CStrArray<'a>(&'a [u8]);
13
14pub struct CStrArrayIter<'a>(&'a [u8]);
16
17impl<'a> Iterator for CStrArrayIter<'a> {
18 type Item = &'a CStr;
19
20 #[inline]
21 fn next(&mut self) -> Option<Self::Item> {
22 if self.0.is_empty() {
23 None
24 } else {
25 <&'a CStr>::from_bytes(&mut self.0).ok()
26 }
27 }
28}
29
30impl<'a> CStrArray<'a> {
31 #[inline]
33 pub fn iter(&self) -> CStrArrayIter<'a> {
34 CStrArrayIter(self.0)
35 }
36}
37
38impl ToBytes for CStrArray<'_> {
39 #[inline]
40 fn binary_size(&self) -> usize {
41 self.0.binary_size()
42 }
43
44 #[inline]
45 fn write<W: Write>(&self, writer: W) -> std::io::Result<()> {
46 self.0.write(writer)
47 }
48
49 #[inline]
50 fn default_repr() -> impl ToBytes {
51 &[] as &[u8]
52 }
53}
54
55impl<'a> FromBytes<'a> for CStrArray<'a> {
56 #[inline]
57 fn from_bytes(buf: &mut &'a [u8]) -> Result<Self, FromBytesError> {
58 match buf.last() {
59 Some(&0) | None => Ok(CStrArray(std::mem::take(buf))),
60 _ => Err(FromBytesError::MissingNul),
61 }
62 }
63}
64
65impl Debug for CStrArray<'_> {
66 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
67 let mut is_first = true;
68 for s in self.iter() {
69 if is_first {
70 is_first = false;
71 } else {
72 f.write_char(';')?;
73 }
74 Debug::fmt(&CStrFormatter(s), f)?;
75 }
76
77 Ok(())
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use crate::fields::{FromBytes, ToBytes};
84 use crate::types::string::cstr_array::CStrArray;
85
86 #[test]
87 fn test_str_array() {
88 let binary = b"foo\0bar\0".as_slice();
89 let array = CStrArray::from_bytes(&mut &*binary).unwrap();
90
91 let mut iter = array.iter();
92 assert_eq!(iter.next().unwrap(), c"foo");
93 assert_eq!(iter.next().unwrap(), c"bar");
94 assert_eq!(iter.next(), None);
95
96 let mut serialized = Vec::new();
97 array.write(&mut serialized).unwrap();
98 assert_eq!(serialized.as_slice(), binary);
99 }
100
101 #[test]
102 fn test_str_empty_array() {
103 let binary = b"".as_slice();
104 let array = CStrArray::from_bytes(&mut &*binary).unwrap();
105
106 let mut iter = array.iter();
107 assert_eq!(iter.next(), None);
108
109 let mut serialized = Vec::new();
110 array.write(&mut serialized).unwrap();
111 assert_eq!(serialized.as_slice(), binary);
112 }
113
114 #[test]
115 fn test_str_array_with_empty_strings() {
116 let binary = b"\0\0\0".as_slice();
117 let array = CStrArray::from_bytes(&mut &*binary).unwrap();
118
119 let mut iter = array.iter();
120 assert_eq!(iter.next().unwrap(), c"");
121 assert_eq!(iter.next().unwrap(), c"");
122 assert_eq!(iter.next().unwrap(), c"");
123 assert_eq!(iter.next(), None);
124
125 let mut serialized = Vec::new();
126 array.write(&mut serialized).unwrap();
127 assert_eq!(serialized.as_slice(), binary);
128 }
129}