use base122_fast::{decode, encode};
use criterion::{Criterion, Throughput, criterion_group, criterion_main};
use rand::RngExt;
use std::hint::black_box;

fn random_data(size: usize) -> Vec<u8> {
    let mut rng = rand::rng();
    let mut data = vec![0u8; size];
    rng.fill(&mut data[..]);
    data
}

fn bench_encode(c: &mut Criterion) {
    let mut group = c.benchmark_group("encode");
    let sizes = [16, 64, 256, 1024, 65536, 1_048_576];

    for &size in &sizes {
        let data = random_data(size);
        group.throughput(Throughput::Bytes(size as u64));
        group.bench_function(format!("{}_bytes", size), |b| {
            b.iter(|| encode(black_box(&data)));
        });
    }
    group.finish();
}

fn bench_decode(c: &mut Criterion) {
    let mut group = c.benchmark_group("decode");
    let sizes = [16, 64, 256, 1024, 65536, 1_048_576];

    for &size in &sizes {
        let data = random_data(size);
        let encoded = encode(&data);
        group.throughput(Throughput::Bytes(size as u64));
        group.bench_function(format!("{}_bytes", size), |b| {
            b.iter(|| decode(black_box(&encoded)).expect("decoding should succeed"));
        });
    }
    group.finish();
}

fn bench_roundtrip(c: &mut Criterion) {
    let mut group = c.benchmark_group("roundtrip");
    let sizes = [16, 64, 256, 1024, 65536, 1_048_576];

    for &size in &sizes {
        let data = random_data(size);
        group.throughput(Throughput::Bytes(size as u64));
        group.bench_function(format!("{}_bytes", size), |b| {
            b.iter(|| {
                let encoded = encode(black_box(&data));
                let decoded = decode(black_box(&encoded)).expect("roundtrip failed");
                black_box(decoded);
            });
        });
    }
    group.finish();
}

criterion_group!(benches, bench_encode, bench_decode, bench_roundtrip);
criterion_main!(benches);
