use bnb::{BitEnum, bin, bitfield, u2, u3, u4, u6, u13};
use criterion::{Criterion, black_box, criterion_group, criterion_main};
#[bitfield(u8, bits = msb, bytes = big)]
#[derive(Clone, Copy)]
struct VersionIhl {
version: u4,
ihl: u4,
}
#[bitfield(u16, bits = msb, bytes = big)]
#[derive(Clone, Copy)]
struct FlagsFrag {
flags: u3,
frag_offset: u13,
}
#[bitfield(u8, bits = msb, bytes = big)]
#[derive(Clone, Copy)]
struct Tos {
dscp: DiffServ,
ecn: u2,
}
#[derive(BitEnum, Clone, Copy, PartialEq, Debug)]
#[bit_enum(u6)]
enum DiffServ {
Default,
Cs1,
Af11,
Ef,
#[catch_all]
Other(u6),
}
#[bin(big)]
#[derive(Clone)]
struct Ipv4ish {
vi: VersionIhl,
tos: Tos,
total_len: u16,
ident: u16,
flags_frag: FlagsFrag,
ttl: u8,
protocol: u8,
checksum: u16,
src: u32,
dst: u32,
#[brw(count_prefix = u16)]
options: Vec<u8>,
}
fn sample() -> Ipv4ish {
Ipv4ish {
vi: VersionIhl::new()
.with_version(u4::new(4))
.with_ihl(u4::new(5)),
tos: Tos::new().with_dscp(DiffServ::Ef).with_ecn(u2::new(0)),
total_len: 20 + 40,
ident: 0x1C46,
flags_frag: FlagsFrag::new()
.with_flags(u3::new(0b010))
.with_frag_offset(u13::new(0)),
ttl: 64,
protocol: 17, checksum: 0xB1E6,
src: 0xC0A8_0001, dst: 0xC0A8_00C8, options: (0..40u8).collect(),
}
}
fn bench_message(c: &mut Criterion) {
let msg = sample();
let bytes = msg.to_bytes().unwrap();
let mut g = c.benchmark_group("ipv4ish_message");
g.bench_function("encode", |b| {
b.iter(|| black_box(&msg).to_bytes().unwrap());
});
g.bench_function("decode", |b| {
b.iter(|| Ipv4ish::decode_exact(black_box(&bytes)).unwrap());
});
g.finish();
}
criterion_group! {
name = benches;
config = Criterion::default();
targets = bench_message
}
criterion_main!(benches);