Skip to main content

ipfix_parser/parsers/
mod.rs

1//! IPFIX parser
2//!
3//! This module provides parsing functionality for IPFIX Messages.
4//! All data is in network byte order (big-endian) as per RFC 7011 Section 6.1.
5//!
6//! IPFIX Messages are length-delimited, so parsing works on byte slices and
7//! every read is bounds-checked: malformed input returns a [`ParseError`],
8//! never panics.
9
10mod decoder;
11mod elements;
12mod error;
13mod value;
14
15pub use decoder::{parse_message, parse_messages, Decoder, DecoderConfig, Transport};
16pub use error::{ParseError, Result};
17
18/// Bounds-checked big-endian reader over a byte slice
19#[derive(Debug, Clone)]
20pub(crate) struct Cursor<'a> {
21    data: &'a [u8],
22    pos: usize,
23}
24
25impl<'a> Cursor<'a> {
26    pub(crate) fn new(data: &'a [u8]) -> Self {
27        Self { data, pos: 0 }
28    }
29
30    /// Number of unread octets
31    pub(crate) fn remaining(&self) -> usize {
32        self.data.len() - self.pos
33    }
34
35    pub(crate) fn is_empty(&self) -> bool {
36        self.remaining() == 0
37    }
38
39    /// Read `n` octets
40    pub(crate) fn read_bytes(&mut self, n: usize, context: &'static str) -> Result<&'a [u8]> {
41        if n > self.remaining() {
42            return Err(ParseError::Truncated {
43                context,
44                needed: n,
45                available: self.remaining(),
46            });
47        }
48        let bytes = &self.data[self.pos..self.pos + n];
49        self.pos += n;
50        Ok(bytes)
51    }
52
53    /// Read all remaining octets
54    pub(crate) fn read_rest(&mut self) -> &'a [u8] {
55        let bytes = &self.data[self.pos..];
56        self.pos = self.data.len();
57        bytes
58    }
59
60    pub(crate) fn read_u8(&mut self, context: &'static str) -> Result<u8> {
61        Ok(self.read_bytes(1, context)?[0])
62    }
63
64    pub(crate) fn read_u16(&mut self, context: &'static str) -> Result<u16> {
65        let b = self.read_bytes(2, context)?;
66        Ok(u16::from_be_bytes([b[0], b[1]]))
67    }
68
69    pub(crate) fn read_u32(&mut self, context: &'static str) -> Result<u32> {
70        let b = self.read_bytes(4, context)?;
71        Ok(u32::from_be_bytes([b[0], b[1], b[2], b[3]]))
72    }
73
74    /// Read a variable-length Information Element length prefix
75    /// (RFC 7011 Section 7): one octet if < 255, otherwise 255 followed by a
76    /// two-octet length.
77    pub(crate) fn read_variable_length(&mut self, context: &'static str) -> Result<usize> {
78        let first = self.read_u8(context)?;
79        if first < 255 {
80            Ok(first as usize)
81        } else {
82            Ok(self.read_u16(context)? as usize)
83        }
84    }
85
86    /// Read a Field Specifier (RFC 7011 Section 3.2), also used by the
87    /// basicList header (RFC 6313 Section 4.5.1)
88    pub(crate) fn read_field_id(&mut self, context: &'static str) -> Result<(u16, bool)> {
89        let raw = self.read_u16(context)?;
90        Ok((raw & 0x7FFF, raw & 0x8000 != 0))
91    }
92}