SIDN
rust workshop
How did we get here?
RustNL
Our rust projects
Our rust projects
Program
- we have ~2 hours
- first, some slides
- then, hands-on workshop
Useful tools
- doc.rust-lang.org/std/
- cargo check
- "go to source"
- pcapng.com/
Today: PCAP parsing
Today: PCAP parsing
#[derive(Debug)]
struct SectionHeaderBlock {
major_version: u16,
minor_version: u16,
options: &[u8]
}
impl SectionHeaderBlock {
fn parse(data: &[u8]) -> Self {
todo!()
}
}
For now, just panic
fn parse(data: &[u8]) -> Self {
let preamble = 4 + 4 + 4 + 2 + 2 + 8;
if data.len() < preamble {
panic!("invalid size")
}
todo!()
}
from bytes to values
// fn from_le_bytes(bytes: [u8; 4]) -> u32;
let byte_order_magic =
u32::from_le_bytes(
data[8..][..4].try_into().unwrap()
);
endianness
enum Endianness { Le, Be }
let endianness = match byte_order_magic {
0x1a2b3c4d => Endianness::Le,
0x4d3c2b1a => Endianness::Be,
_ => panic!("invalid byte order magic"),
};
let bytes = data[4..][..4].try_into().unwrap();
let block_length = match endianness {
Endianness::Le => u32::from_le_bytes(bytes),
Endianness::Be => u32::from_be_bytes(bytes),
};
slices and lifetimes
// pub fn get<I>(slice: &[T], index: I)
// -> Option<&<I as SliceIndex<[T]>>::Output>
// where
// I: SliceIndex<[T]>,
let end = block_length as usize - preamble - 4;
let options = data.get(preamble..end).unwrap();
slices and lifetimes
impl<'a> SectionHeaderBlock<'a> {
fn parse(data: &'a [u8]) -> Self {
// ...
Self {
major_version,
minor_version,
options,
}
}
}
tests
#[cfg(test)]
mod tests {
use super::*;
const DATA: &[u8] = &[ /* bytes */ ];
#[test]
fn it_works() {
let block = SectionHeaderBlock::parse(DATA);
assert_eq!(
Ok(""),
std::str::from_utf8(block.options),
);
}
}
run a test
> cargo test
Running unittests src/main.rs (target/debug/deps/pcap_parser-d6f024d854d6a202)
running 1 test
test tests::it_works ... FAILED
failures:
---- tests::it_works stdout ----
thread 'tests::it_works' panicked at 'assertion failed: `(left == right)`
left: `Ok("")`,
right: `Ok("\u{3}\0-\0Mac OS X 10.10.4, build 14E46 (Darwin 14.4.0)\0\0\0\u{4}\04\0Dumpcap 1.12.6 (v1.12.6-0-gee1fc")`', src/main.rs:69:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error handling: Option
enum Option<T> {
Some(T),
None,
}
impl<'a> SectionHeaderBlock<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let preamble = 4 + 4 + 4 + 2 + 2 + 8;
if data.len() < preamble {
return None;
}
// ...
Some(Self {
major_version: 0,
minor_version: 0,
options,
})
}
}
error handling: Result
enum Result<T, E> {
Ok(T),
Err(E),
}
enum ParseError {
TooShort,
InvalidByteOrder,
}
impl<'a> SectionHeaderBlock<'a> {
fn parse(data: &'a [u8]) -> Result<Self, ParseError> {
let preamble = 4 + 4 + 4 + 2 + 2 + 8;
if data.len() < preamble {
return Err(ParseError::TooShort);
}
// ...
Exercises
- doc.rust-lang.org/std/
- cargo check
- "go to source"
- pcapng.com/
SIDN workshop
By folkert de vries
SIDN workshop
- 49