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
48/// Deserialize a field from a byte buffer
49pub trait FromBytes<'a>: Sized {
50    /// Read the binary representation of a field and return the parsed representation
51    ///
52    /// **Note**: the argument is a mutable reference to an immutable slice. While the contents
53    /// of the slice cannot be modified, the slice itself can. Every call to `from_bytes` consumes
54    /// a number of bytes from the beginning of the slice.
55    fn from_bytes(buf: &mut &'a [u8]) -> Result<Self, FromBytesError>;
56
57    /// Read the binary representation of a field from a buffer that may or may not exist
58    ///
59    /// The default implementation returns an error when the buffer does not exist, but the blanket
60    /// impl for `Option<T>` effectively returns `Ok(None)`
61    fn from_maybe_bytes(buf: Option<&mut &'a [u8]>) -> Result<Self, FromBytesError> {
62        match buf {
63            Some(buf) => Self::from_bytes(buf),
64            None => Err(FromBytesError::RequiredFieldNotFound),
65        }
66    }
67}
68
69impl<'a, T: FromBytes<'a> + 'a> FromBytes<'a> for Option<T>
70where
71    T: Sized,
72{
73    fn from_bytes(buf: &mut &'a [u8]) -> Result<Self, FromBytesError> {
74        T::from_bytes(buf).map(Some)
75    }
76
77    fn from_maybe_bytes(buf: Option<&mut &'a [u8]>) -> Result<Self, FromBytesError> {
78        match buf {
79            Some([]) => Ok(None),
80            Some(buf) => Self::from_bytes(buf),
81            None => Ok(None),
82        }
83    }
84}