Skip to content

Commit 24c8182

Browse files
mikemiles-devMichael Mileusnich
and
Michael Mileusnich
authored
fix: * Simplify V9/IPFix Parse function. (#116)
* fix: * Simplify V9/IPFix Parse function. * fix: clippy * fix: re add remaining check v9 --------- Co-authored-by: Michael Mileusnich <[email protected]>
1 parent 84739dd commit 24c8182

File tree

5 files changed

+33
-36
lines changed

5 files changed

+33
-36
lines changed

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "netflow_parser"
33
description = "Parser for Netflow Cisco V5, V7, V9, IPFIX"
4-
version = "0.5.5"
4+
version = "0.5.6"
55
edition = "2024"
66
authors = ["[email protected]"]
77
license = "MIT OR Apache-2.0"
@@ -31,7 +31,6 @@ serde_json = "1.0.100"
3131
[[bench]]
3232
name = "netflow_parser_bench"
3333
harness = false
34-
3534
[[bench]]
3635
name = "netflow_common_bench"
3736
harness = false

RELEASES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# 0.5.6
2+
* Simplify V9/IPFix Parse function.
3+
14
# 0.5.5
25
* More IPFIx/V9 Cleanup.
36
* Reworked FlowSetBody for V9/IPFIX into an enum since a flowset can only contain a single type.

src/variable_versions/data_number.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ impl FieldValue {
195195
FieldValue::DataNumber(d) => d.to_be_bytes(),
196196
FieldValue::Float64(f) => Ok(f.to_be_bytes().to_vec()),
197197
FieldValue::Duration(d) => Ok((u32::try_from(d.as_secs())
198-
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?)
198+
.map_err(std::io::Error::other)?)
199199
.to_be_bytes()
200200
.to_vec()),
201201
FieldValue::Ip4Addr(ip) => Ok(ip.octets().to_vec()),

src/variable_versions/ipfix.rs

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ pub enum FlowSetBody {
9898
///
9999
/// - `i`: A byte slice (`&[u8]`) representing the input data to be parsed.
100100
/// - `parser`: A mutable reference to an `IPFixParser` instance, which maintains the state including
101-
/// registered templates and options templates.
101+
/// registered templates and options templates.
102102
/// - `id`: A 16-bit unsigned integer (`u16`) representing the identifier for the flowset to be parsed.
103103
///
104104
/// # Returns
@@ -287,6 +287,7 @@ pub struct TemplateField {
287287
// Common trait for both templates. Mainly for fetching fields.
288288
trait CommonTemplate {
289289
fn get_fields(&self) -> &Vec<TemplateField>;
290+
290291
fn get_field_count(&self) -> usize {
291292
self.get_fields().len()
292293
}
@@ -319,29 +320,25 @@ impl FieldParser {
319320
i: &[u8],
320321
template: T,
321322
) -> IResult<&[u8], Vec<BTreeMap<usize, IPFixFieldPair>>> {
322-
let mut total_taken = 0;
323-
324323
// If no fields there are no fields to parse, return an error.
325-
let mut fields = vec![];
326-
let mut remaining = i;
327-
for (c, field) in template.get_fields().iter().enumerate() {
328-
// Iter through template fields and push them to a vec. If we encouter any zero length fields we return an error.
329-
let mut data_field = BTreeMap::new();
330-
let (i, field_value) = field.parse_as_field_value(remaining)?;
331-
let taken = remaining.len().saturating_sub(i.len());
332-
total_taken += taken;
333-
remaining = i;
334-
data_field.insert(c, (field.field_type, field_value));
335-
fields.push(data_field);
336-
}
337-
338-
let remaining = if !remaining.is_empty() && remaining.len() >= total_taken {
324+
let (remaining, mut fields, total_taken) =
325+
template.get_fields().iter().enumerate().try_fold(
326+
(i, vec![], 0usize),
327+
|(remaining, mut fields, total_taken), (c, field)| {
328+
let mut data_field = BTreeMap::new();
329+
let (i, field_value) = field.parse_as_field_value(remaining)?;
330+
let taken = remaining.len().saturating_sub(i.len());
331+
data_field.insert(c, (field.field_type, field_value));
332+
fields.push(data_field);
333+
Ok((i, fields, total_taken.saturating_add(taken)))
334+
},
335+
)?;
336+
337+
if remaining.len() >= total_taken {
339338
let (remaining, more) = Self::parse(remaining, template)?;
340339
fields.extend(more);
341-
remaining
342-
} else {
343-
remaining
344-
};
340+
return Ok((remaining, fields));
341+
}
345342

346343
Ok((remaining, fields))
347344
}

src/variable_versions/v9.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ pub enum ScopeDataField {
329329
///
330330
/// * `input` - A byte slice that contains the data to be parsed.
331331
/// * `template_field` - A reference to an `OptionsTemplateScopeField` which holds the metadata describing the expected field,
332-
/// including its length and type.
332+
/// including its length and type.
333333
///
334334
/// # Returns
335335
///
@@ -433,17 +433,15 @@ impl FlowSetParser {
433433
parser: &mut V9Parser,
434434
record_count: u16,
435435
) -> IResult<&'a [u8], Vec<FlowSet>> {
436-
let mut flowsets = vec![];
437-
let mut remaining = i;
438-
let mut record_count_index = 0;
439-
440-
// Header.count represents total number of records in data + records in templates
441-
while !remaining.is_empty() && record_count_index < record_count {
442-
let (i, flowset) = FlowSet::parse(remaining, parser)?;
443-
remaining = i;
444-
flowsets.push(flowset);
445-
record_count_index += 1;
446-
}
436+
let (remaining, flowsets) =
437+
(0..record_count).try_fold((i, Vec::new()), |(remaining, mut flowsets), _| {
438+
if remaining.is_empty() {
439+
return Ok((remaining, flowsets));
440+
}
441+
let (i, flowset) = FlowSet::parse(remaining, parser)?;
442+
flowsets.push(flowset);
443+
Ok((i, flowsets))
444+
})?;
447445

448446
Ok((remaining, flowsets))
449447
}

0 commit comments

Comments
 (0)