squitter 0.1.1

no_std, no_alloc parser and encoder for 1090ES/DF17 (ADS-B extended squitter) messages
Documentation
//! Benchmarks for the decode/encode/CPR hot paths.
//!
//! Run with `cargo bench -p squitter`.

use std::hint::black_box;

use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use squitter::message::{self, CprFormat, SurfacePosition};
use squitter::{Frame, decode_line, encode_frame};

/// Real captured DF17 hex frames (see `tests/real_world_corpus.rs` and each
/// message module's own tests), one per message family. There's no real
/// DF17 surface-position capture on hand (see `lib.rs`'s own test for why),
/// so that one is built once via `encode_frame` from real field values
/// instead of hand-invented ones.
fn lines() -> [(&'static str, String); 4] {
    let surface = SurfacePosition {
        type_code: 8,
        movement_raw: 38,
        track_status: true,
        track_raw: 35,
        utc_synced: true,
        cpr_format: CprFormat::Even,
        lat_cpr: 11052,
        lon_cpr: 86083,
    };
    let frame = encode_frame(
        &squitter::AdsbMessage::SurfacePosition(surface),
        0x003A_23FF,
        5,
    )
    .unwrap();
    let mut buf = [0u8; 28];
    let surface_hex = frame.write_hex(&mut buf).to_owned();

    [
        ("identification", "8D4840D6202CC371C32CE0576098".to_owned()),
        ("surface_position", surface_hex),
        (
            "airborne_position",
            "8D40058B58C901375147EFD09357".to_owned(),
        ),
        (
            "airborne_velocity",
            "8D485020994409940838175B284F".to_owned(),
        ),
    ]
}

fn decode_line_bench(c: &mut Criterion) {
    let mut group = c.benchmark_group("decode_line");
    for (name, line) in lines() {
        group.bench_with_input(BenchmarkId::from_parameter(name), &line, |b, line| {
            b.iter(|| decode_line(black_box(line)).unwrap());
        });
    }
    group.finish();
}

fn frame_parse_bench(c: &mut Criterion) {
    let mut group = c.benchmark_group("frame_parse");
    for (name, line) in lines() {
        group.bench_with_input(BenchmarkId::from_parameter(name), &line, |b, line| {
            b.iter(|| Frame::parse(black_box(line)).unwrap());
        });
    }
    group.finish();
}

fn encode_frame_bench(c: &mut Criterion) {
    let mut group = c.benchmark_group("encode_frame");
    for (name, line) in lines() {
        let msg = decode_line(&line).unwrap();
        group.bench_with_input(BenchmarkId::from_parameter(name), &msg, |b, msg| {
            b.iter(|| encode_frame(black_box(msg), 0x0048_40D6, 5).unwrap());
        });
    }
    group.finish();
}

/// A real even/odd airborne-position pair (see
/// `message::airborne_position`'s own tests), used to benchmark CPR global
/// decode, the only part of this crate doing non-trivial float math
/// (hand-rolled `floor`/`rem_euclid`/`NL(lat)` lookup).
fn cpr_global_decode_bench(c: &mut Criterion) {
    c.bench_function("cpr_global_decode", |b| {
        b.iter(|| {
            message::cpr::global_decode(
                black_box(39848),
                black_box(83951),
                black_box(21567),
                black_box(81965),
                black_box(false),
            )
            .unwrap()
        });
    });
}

criterion_group!(
    benches,
    decode_line_bench,
    frame_parse_bench,
    encode_frame_bench,
    cpr_global_decode_bench,
);
criterion_main!(benches);