#![doc = include_str!("../README.md")]
#![forbid(unsafe_code)]
pub mod counter_records;
pub mod datagram;
pub mod error;
pub mod flow_records;
pub mod samples;
#[cfg(test)]
mod tests;
pub use counter_records::CounterRecord;
pub use datagram::{AddressType, SflowDatagram};
pub use error::{ParseContext, ParseErrorKind, SflowError};
pub use flow_records::FlowRecord;
pub use samples::SflowSample;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ParseResult {
pub datagrams: Vec<SflowDatagram>,
pub error: Option<SflowError>,
}
#[derive(Debug, Clone, Default)]
pub struct SflowParser {
max_samples: Option<u32>,
}
impl SflowParser {
pub fn builder() -> SflowParserBuilder {
SflowParserBuilder { max_samples: None }
}
pub fn parse_bytes(&self, packet: &[u8]) -> ParseResult {
let mut datagrams = Vec::new();
let mut remaining = packet;
loop {
if remaining.is_empty() {
break;
}
if remaining.len() < 4 {
return ParseResult {
datagrams,
error: Some(SflowError::Incomplete {
available: remaining.len(),
expected: None,
context: ParseContext::DatagramHeader,
}),
};
}
match datagram::parse_datagram(remaining, self.max_samples) {
Ok((rest, dg)) => {
datagrams.push(dg);
remaining = rest;
}
Err(e) => {
return ParseResult {
datagrams,
error: Some(e),
};
}
}
}
ParseResult {
datagrams,
error: None,
}
}
}
#[derive(Debug, Clone)]
pub struct SflowParserBuilder {
max_samples: Option<u32>,
}
impl SflowParserBuilder {
pub fn with_max_samples(mut self, max: u32) -> Self {
self.max_samples = Some(max);
self
}
pub fn build(self) -> SflowParser {
SflowParser {
max_samples: self.max_samples,
}
}
}