Skip to content

Commit 14ecfcf

Browse files
mikemiles-devmikemiles-dev
authored andcommitted
fix: Doc updates
1 parent 6ba86e2 commit 14ecfcf

2 files changed

Lines changed: 121 additions & 5 deletions

File tree

README.md

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ A Netflow Parser library for Cisco V5, V7, V9, and IPFIX written in Rust. Suppor
77
- [Example](#example)
88
- [Serialization (JSON)](#want-serialization-such-as-json)
99
- [Filtering for a Specific Version](#filtering-for-a-specific-version)
10-
- [Stream Processing (Iterator API)](#stream-processing-iterator-api)
10+
- [Iterator API](#iterator-api)
1111
- [Parsing Out Unneeded Versions](#parsing-out-unneeded-versions)
1212
- [Error Handling Configuration](#error-handling-configuration)
1313
- [Netflow Common](#netflow-common)
@@ -112,9 +112,8 @@ let parsed = NetflowParser::default().parse_bytes(&v5_packet);
112112
let v5_parsed: Vec<NetflowPacket> = parsed.into_iter().filter(|p| p.is_v5()).collect();
113113
```
114114

115-
## Stream Processing (Iterator API)
116-
117-
For high-performance scenarios where you want to avoid allocating a `Vec`, you can use the iterator API to process packets one-by-one as they're parsed:
115+
## Iterator API
116+
You can use the iterator API to process packets one-by-one as they're parsed instead of returning `Vec`:
118117

119118
```rust
120119
use netflow_parser::{NetflowParser, NetflowPacket};
@@ -146,13 +145,33 @@ for packet in parser.iter_packets(&buffer) {
146145
}
147146
```
148147

148+
The iterator provides access to unconsumed bytes for advanced use cases:
149+
150+
```rust
151+
use netflow_parser::NetflowParser;
152+
153+
let buffer = /* your netflow data */;
154+
let mut parser = NetflowParser::default();
155+
let mut iter = parser.iter_packets(&buffer);
156+
157+
while let Some(packet) = iter.next() {
158+
// Process packet
159+
}
160+
161+
// Check if all bytes were consumed
162+
if !iter.is_complete() {
163+
println!("Warning: {} bytes remain unconsumed", iter.remaining().len());
164+
}
165+
```
166+
149167
### Benefits of Iterator API
150168

151169
- **Zero allocation**: Packets are yielded one-by-one without allocating a `Vec`
152170
- **Memory efficient**: Ideal for processing large batches or continuous streams
153171
- **Lazy evaluation**: Only parses packets as you consume them
154172
- **Template caching preserved**: V9/IPFIX template state is maintained across iterations
155173
- **Composable**: Works with standard Rust iterator methods (`.filter()`, `.map()`, `.take()`, etc.)
174+
- **Buffer inspection**: Access unconsumed bytes via `.remaining()` and check completion with `.is_complete()`
156175

157176
### Iterator Examples
158177

@@ -169,6 +188,16 @@ for packet in parser.iter_packets(&buffer).take(10) {
169188

170189
// Collect only if needed (equivalent to parse_bytes())
171190
let packets: Vec<_> = parser.iter_packets(&buffer).collect();
191+
192+
// Check unconsumed bytes (useful for mixed protocol streams)
193+
let mut iter = parser.iter_packets(&buffer);
194+
for packet in &mut iter {
195+
// Process packet
196+
}
197+
if !iter.is_complete() {
198+
let remaining = iter.remaining();
199+
// Handle non-netflow data at end of buffer
200+
}
172201
```
173202

174203
## Parsing Out Unneeded Versions

src/lib.rs

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
//! let v5_parsed: Vec<NetflowPacket> = parsed.into_iter().filter(|p| p.is_v5()).collect();
8484
//! ```
8585
//!
86-
//! ## Stream Processing (Iterator API)
86+
//! ## Iterator API
8787
//!
8888
//! For high-performance scenarios where you want to avoid allocating a `Vec`, you can use the iterator API to process packets one-by-one as they're parsed:
8989
//!
@@ -117,13 +117,34 @@
117117
//! }
118118
//! ```
119119
//!
120+
//! The iterator provides access to unconsumed bytes for advanced use cases:
121+
//!
122+
//! ```rust
123+
//! use netflow_parser::NetflowParser;
124+
//!
125+
//! # let buffer = [0u8; 72];
126+
//! let mut parser = NetflowParser::default();
127+
//! let mut iter = parser.iter_packets(&buffer);
128+
//!
129+
//! while let Some(packet) = iter.next() {
130+
//! // Process packet
131+
//! # _ = packet;
132+
//! }
133+
//!
134+
//! // Check if all bytes were consumed
135+
//! if !iter.is_complete() {
136+
//! println!("Warning: {} bytes remain unconsumed", iter.remaining().len());
137+
//! }
138+
//! ```
139+
//!
120140
//! ### Benefits of Iterator API
121141
//!
122142
//! - **Zero allocation**: Packets are yielded one-by-one without allocating a `Vec`
123143
//! - **Memory efficient**: Ideal for processing large batches or continuous streams
124144
//! - **Lazy evaluation**: Only parses packets as you consume them
125145
//! - **Template caching preserved**: V9/IPFIX template state is maintained across iterations
126146
//! - **Composable**: Works with standard Rust iterator methods (`.filter()`, `.map()`, `.take()`, etc.)
147+
//! - **Buffer inspection**: Access unconsumed bytes via `.remaining()` and check completion with `.is_complete()`
127148
//!
128149
//! ### Iterator Examples
129150
//!
@@ -139,10 +160,23 @@
139160
//! // Process only the first 10 packets
140161
//! for packet in parser.iter_packets(&buffer).take(10) {
141162
//! // Handle packet
163+
//! # _ = packet;
142164
//! }
143165
//!
144166
//! // Collect only if needed (equivalent to parse_bytes())
145167
//! let packets: Vec<_> = parser.iter_packets(&buffer).collect();
168+
//!
169+
//! // Check unconsumed bytes (useful for mixed protocol streams)
170+
//! let mut iter = parser.iter_packets(&buffer);
171+
//! for packet in &mut iter {
172+
//! // Process packet
173+
//! # _ = packet;
174+
//! }
175+
//! if !iter.is_complete() {
176+
//! let remaining = iter.remaining();
177+
//! // Handle non-netflow data at end of buffer
178+
//! # _ = remaining;
179+
//! }
146180
//! ```
147181
//!
148182
//! ## Parsing Out Unneeded Versions
@@ -520,6 +554,59 @@ pub struct NetflowPacketIterator<'a> {
520554
errored: bool,
521555
}
522556

557+
impl<'a> NetflowPacketIterator<'a> {
558+
/// Returns the unconsumed bytes remaining in the buffer.
559+
///
560+
/// This is useful for:
561+
/// - Debugging: See how much data was consumed
562+
/// - Mixed protocols: Process non-netflow data after netflow packets
563+
/// - Resumption: Know where parsing stopped
564+
///
565+
/// # Examples
566+
///
567+
/// ```rust
568+
/// use netflow_parser::NetflowParser;
569+
///
570+
/// let v5_packet = [0, 5, 0, 1, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
571+
/// let mut parser = NetflowParser::default();
572+
/// let mut iter = parser.iter_packets(&v5_packet);
573+
///
574+
/// while let Some(_packet) = iter.next() {
575+
/// // Process packet
576+
/// }
577+
///
578+
/// // Check how many bytes remain unconsumed
579+
/// assert_eq!(iter.remaining().len(), 0);
580+
/// ```
581+
pub fn remaining(&self) -> &'a [u8] {
582+
self.remaining
583+
}
584+
585+
/// Returns true if all bytes have been consumed or an error occurred.
586+
///
587+
/// This is useful for validation and ensuring complete buffer processing.
588+
///
589+
/// # Examples
590+
///
591+
/// ```rust
592+
/// use netflow_parser::NetflowParser;
593+
///
594+
/// let v5_packet = [0, 5, 0, 1, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
595+
/// let mut parser = NetflowParser::default();
596+
/// let mut iter = parser.iter_packets(&v5_packet);
597+
///
598+
/// // Consume all packets
599+
/// for _packet in &mut iter {
600+
/// // Process packet
601+
/// }
602+
///
603+
/// assert!(iter.is_complete());
604+
/// ```
605+
pub fn is_complete(&self) -> bool {
606+
self.remaining.is_empty() || self.errored
607+
}
608+
}
609+
523610
impl<'a> Iterator for NetflowPacketIterator<'a> {
524611
type Item = NetflowPacket;
525612

0 commit comments

Comments
 (0)