falco_event/types/primitive/
newtypes.rs1use crate::fields::{FromBytes, FromBytesError, ToBytes};
2use std::fmt::{Debug, Formatter, LowerHex};
3
4macro_rules! default_debug {
5 ($name:ident) => {
6 impl Debug for $name {
7 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
8 Debug::fmt(&self.0, fmt)
9 }
10 }
11 };
12}
13
14macro_rules! newtype {
15 ($(#[$attr:meta])* $name:ident($repr:ty)) => {
16 $(#[$attr])*
17 #[derive(Default, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
18 pub struct $name(pub $repr);
19
20 impl FromBytes<'_> for $name {
21 #[inline]
22 fn from_bytes(buf: &mut &[u8]) -> Result<Self, FromBytesError>
23 where
24 Self: Sized,
25 {
26 Ok(Self(FromBytes::from_bytes(buf)?))
27 }
28 }
29
30 impl ToBytes for $name {
31 #[inline]
32 fn binary_size(&self) -> usize {
33 self.0.binary_size()
34 }
35
36 #[inline]
37 fn write<W: std::io::Write>(&self, writer: W) -> std::io::Result<()> {
38 self.0.write(writer)
39 }
40
41 #[inline]
42 fn default_repr() -> impl ToBytes {
43 <$repr>::default_repr()
44 }
45 }
46 };
47}
48
49newtype!(
50 SyscallResult(i64)
52);
53
54impl Debug for SyscallResult {
55 #[cfg(target_os = "linux")]
56 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
57 if self.0 < 0 {
58 let errno = nix::errno::Errno::from_raw(-self.0 as i32);
59 if errno == nix::errno::Errno::UnknownErrno {
60 write!(f, "{}", self.0)
62 } else {
63 write!(f, "{}({:?})", self.0, errno)
64 }
65 } else {
66 Debug::fmt(&self.0, f)
67 }
68 }
69
70 #[cfg(not(target_os = "linux"))]
72 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
73 if self.0 < 0 {
74 write!(f, "{}", self.0)
76 } else {
77 Debug::fmt(&self.0, f)
78 }
79 }
80}
81
82impl LowerHex for SyscallResult {
83 #[cfg(target_os = "linux")]
84 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
85 if self.0 < 0 {
86 let errno = nix::errno::Errno::from_raw(-self.0 as i32);
87 if errno == nix::errno::Errno::UnknownErrno {
88 write!(f, "{}", self.0)
90 } else {
91 write!(f, "{}({:?})", self.0, errno)
92 }
93 } else {
94 LowerHex::fmt(&self.0, f)
95 }
96 }
97
98 #[cfg(not(target_os = "linux"))]
100 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
101 if self.0 < 0 {
102 write!(f, "{}", self.0)
104 } else {
105 LowerHex::fmt(&self.0, f)
106 }
107 }
108}
109
110#[cfg(test)]
111mod syscall_result_tests {
112 use crate::types::SyscallResult;
113
114 #[test]
115 #[cfg(target_os = "linux")]
116 fn test_fmt_syscall_result() {
117 assert_eq!(format!("{:?}", SyscallResult(0)), "0");
118 assert_eq!(format!("{:?}", SyscallResult(1024)), "1024");
119 assert_eq!(format!("{:?}", SyscallResult(-2)), "-2(ENOENT)");
120 assert_eq!(format!("{:?}", SyscallResult(-28)), "-28(ENOSPC)");
121 assert_eq!(format!("{:?}", SyscallResult(-1024)), "-1024");
122
123 assert_eq!(format!("{:#x}", SyscallResult(0)), "0x0");
124 assert_eq!(format!("{:#x}", SyscallResult(1024)), "0x400");
125 assert_eq!(format!("{:#x}", SyscallResult(-2)), "-2(ENOENT)");
126 assert_eq!(format!("{:#x}", SyscallResult(-28)), "-28(ENOSPC)");
127 assert_eq!(format!("{:#x}", SyscallResult(-1024)), "-1024");
128 }
129
130 #[test]
131 #[cfg(not(target_os = "linux"))]
132 fn test_fmt_syscall_result() {
133 assert_eq!(format!("{:?}", SyscallResult(0)), "0");
134 assert_eq!(format!("{:?}", SyscallResult(1024)), "1024");
135 assert_eq!(format!("{:?}", SyscallResult(-2)), "-2");
136 assert_eq!(format!("{:?}", SyscallResult(-28)), "-28");
137 assert_eq!(format!("{:?}", SyscallResult(-1024)), "-1024");
138
139 assert_eq!(format!("{:#x}", SyscallResult(0)), "0x0");
140 assert_eq!(format!("{:#x}", SyscallResult(1024)), "0x400");
141 assert_eq!(format!("{:#x}", SyscallResult(-2)), "-2");
142 assert_eq!(format!("{:#x}", SyscallResult(-28)), "-28");
143 assert_eq!(format!("{:#x}", SyscallResult(-1024)), "-1024");
144 }
145}
146
147newtype!(
148 SyscallId(u16)
150);
151default_debug!(SyscallId);
152
153newtype!(
154 SigType(u8)
156);
157
158impl Debug for SigType {
159 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
160 Debug::fmt(&self.0, f)?;
161
162 #[cfg(target_os = "linux")]
163 {
164 let sig = nix::sys::signal::Signal::try_from(self.0 as i32);
165 if let Ok(sig) = sig {
166 write!(f, "({sig:?})")?;
167 }
168 }
169
170 Ok(())
171 }
172}
173
174#[cfg(test)]
175mod sig_tests {
176 use crate::types::SigType;
177
178 #[test]
179 #[cfg(target_os = "linux")]
180 fn test_sig_fmt() {
181 let formatted = format!("{:?}", SigType(1));
182 assert_eq!(formatted, "1(SIGHUP)");
183 }
184
185 #[test]
186 #[cfg(not(target_os = "linux"))]
187 fn test_sig_fmt() {
188 let formatted = format!("{:?}", SigType(1));
189 assert_eq!(formatted, "1");
190 }
191}
192
193newtype!(
194 Fd(i64)
196);
197
198impl Debug for Fd {
199 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
200 if self.0 == -100 {
201 f.write_str("AT_FDCWD")
202 } else {
203 Debug::fmt(&self.0, f)
204 }
205 }
206}
207
208newtype!(
209 Fd32(i32)
211);
212
213impl Debug for Fd32 {
214 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
215 if self.0 == -100 {
216 f.write_str("AT_FDCWD")
217 } else {
218 Debug::fmt(&self.0, f)
219 }
220 }
221}
222
223#[cfg(test)]
224mod fd_tests {
225 use crate::types::Fd;
226
227 #[test]
228 fn test_fd_fmt() {
229 assert_eq!(format!("{:?}", Fd(10)), "10");
230 assert_eq!(format!("{:?}", Fd(-100)), "AT_FDCWD");
231 }
232}
233
234newtype!(
235 Pid(i64)
237);
238default_debug!(Pid);
239
240newtype!(
241 Pid32(i32)
243);
244default_debug!(Pid32);
245
246newtype!(
247 Uid(u32)
249);
250default_debug!(Uid);
251
252newtype!(
253 Gid(u32)
255);
256default_debug!(Gid);
257
258newtype!(
259 SigSet(u32)
261);
262
263impl SigSet {
264 #[inline]
266 pub fn iter(&self) -> impl Iterator<Item = SigType> + use<> {
267 let mask = self.0;
268 (0..32u8)
269 .filter(move |sig| mask & (1u32 << sig) != 0)
270 .map(SigType)
271 }
272}
273
274impl Debug for SigSet {
275 fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result {
276 write!(fmt, "{:#2x}", self.0)?;
277 if self.0 != 0 {
278 let mut first = true;
279 for sig in self.iter() {
280 if first {
281 write!(fmt, "(")?;
282 first = false;
283 } else {
284 write!(fmt, ",")?;
285 }
286 write!(fmt, "{sig:?}")?;
287 }
288 write!(fmt, ")")?;
289 }
290
291 Ok(())
292 }
293}
294
295#[cfg(test)]
296mod sigset_tests {
297 use crate::types::SigSet;
298
299 #[test]
300 #[cfg(target_os = "linux")]
301 fn test_sigset() {
302 let signals = (1 << 2) | (1 << 9); let formatted = format!("{:?}", SigSet(signals));
306 assert_eq!(formatted, "0x204(2(SIGINT),9(SIGKILL))");
307 }
308
309 #[test]
310 #[cfg(not(target_os = "linux"))]
311 fn test_sigset() {
312 let signals = (1 << 2) | (1 << 9); let formatted = format!("{:?}", SigSet(signals));
316 assert_eq!(formatted, "0x204(2,9)");
317 }
318}
319
320newtype!(
321 Port(u16)
325);
326default_debug!(Port);
327
328impl LowerHex for Port {
329 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
330 Debug::fmt(&self, f)
331 }
332}
333
334#[cfg(test)]
335mod port_tests {
336 use crate::types::Port;
337
338 #[test]
339 fn test_port() {
340 assert_eq!(format!("{:?}", Port(12345)), "12345");
341 assert_eq!(format!("{:x}", Port(12345)), "12345");
342 }
343}
344
345newtype!(
346 #[allow(unused)]
350 L4Proto(u8)
351);
352default_debug!(L4Proto);
353
354newtype!(
355 #[derive(Debug)]
359 SockFamily(u8)
360);
361
362newtype!(
363 Bool(u32)
367);
368
369impl Debug for Bool {
370 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
371 match self.0 {
372 0 => f.write_str("false"),
373 1 => f.write_str("true"),
374 n => write!(f, "true({n})"),
375 }
376 }
377}
378
379#[cfg(test)]
380mod bool_tests {
381 use crate::types::Bool;
382
383 #[test]
384 fn test_bool() {
385 assert_eq!(format!("{:?}", Bool(0)), "false");
386 assert_eq!(format!("{:?}", Bool(1)), "true");
387 assert_eq!(format!("{:?}", Bool(10)), "true(10)");
388 }
389}