falco_event/fields/
from_bytes.rs

1use thiserror::Error;
2
3/// Error type for deserializing data from a byte buffer
4#[derive(Error, Debug)]
5pub enum FromBytesError {
6    /// I/O error
7    #[error("I/O error")]
8    IoError(#[from] std::io::Error),
9
10    /// Required field not found
11    #[error("required field not found")]
12    RequiredFieldNotFound,
13
14    /// NUL inside a string
15    #[error("internal NUL in string")]
16    InternalNul,
17
18    /// Missing NUL terminator
19    #[error("missing NUL terminator")]
20    MissingNul,
21
22    /// Truncated field
23    #[error("truncated field (wanted {wanted}, got {got})")]
24    TruncatedField {
25        /// the size we wanted
26        wanted: usize,
27        /// the size we got
28        got: usize,
29    },
30
31    /// Invalid length
32    #[error("invalid length")]
33    InvalidLength,
34
35    /// Invalid PT_DYN discriminant
36    #[error("invalid PT_DYN discriminant")]
37    InvalidDynDiscriminant,
38
39    /// Odd item count in a pair array
40    #[error("odd item count in pair array")]
41    OddPairItemCount,
42
43    /// Unconsumed data remaining in field buffer
44    #[error("trailing field data")]
45    LeftoverData,
46
47    /// Other error (from custom conversions)
48    #[error(transparent)]
49    Other(#[from] anyhow::Error),
50}
51
52/// Deserialize a field from a byte buffer
53pub trait FromBytes<'a>: Sized {
54    /// Read the binary representation of a field and return the parsed representation
55    ///
56    /// **Note**: the argument is a mutable reference to an immutable slice. While the contents
57    /// of the slice cannot be modified, the slice itself can. Every call to `from_bytes` consumes
58    /// a number of bytes from the beginning of the slice.
59    fn from_bytes(buf: &mut &'a [u8]) -> Result<Self, FromBytesError>;
60
61    /// Read the binary representation of a field from a buffer that may or may not exist
62    ///
63    /// The default implementation returns an error when the buffer does not exist, but the blanket
64    /// impl for `Option<T>` effectively returns `Ok(None)`
65    #[inline]
66    fn from_maybe_bytes(buf: Option<&mut &'a [u8]>) -> Result<Self, FromBytesError> {
67        match buf {
68            Some(buf) => Self::from_bytes(buf),
69            None => Err(FromBytesError::RequiredFieldNotFound),
70        }
71    }
72}
73
74impl<'a, T: FromBytes<'a> + 'a> FromBytes<'a> for Option<T>
75where
76    T: Sized,
77{
78    #[inline]
79    fn from_bytes(buf: &mut &'a [u8]) -> Result<Self, FromBytesError> {
80        T::from_bytes(buf).map(Some)
81    }
82
83    #[inline]
84    fn from_maybe_bytes(buf: Option<&mut &'a [u8]>) -> Result<Self, FromBytesError> {
85        match buf {
86            Some([]) => Ok(None),
87            Some(buf) => Self::from_bytes(buf),
88            None => Ok(None),
89        }
90    }
91}