#![allow(missing_docs)]

use std::hint::black_box;

use criterion::{Criterion, criterion_group, criterion_main};

const ORIG: &str = "abcdef\\gi\r\n🤣you know what im gonna to say but huh🤣🤣\tTabbed\x0Anewline\nanother newline\r\n\r\n\"quoted text\"'single quote'backslash\\\\unicode\u{1F600}\u{03A9}\x48\x65\x6C\x6C\x6F/path/to/file.json\\xinvalid\\uincomplete\\u{123\\u{1F914}thinking face";
const ORIG_COMPLEX: &str = "JSON-like: {\"key\": \"value\\twith tab\", \"escaped\": \"quote\\\"here\", \"path\": \"C:\\\\Users\\\\test\\\\file.txt\", \"unicode\": \"smile\u{1F600}omega\u{03A9}\", \"hex\": \"\\x48\\x65\\x6C\\x6C\\x6F\", \"mixed\": \"line1\\nline2\\r\\nline3\"}SQL: INSERT INTO table VALUES ('don\\'t panic', \"quote\\\"test\");Regex: \\\\d+\\\\.\\\\d+ URLs: https:\\/\\/example.com\\/path?q=test#frag";

fn benchmark(c: &mut Criterion) {
    let escaped = format!(
        "{}..{}",
        ORIG.escape_default(),
        ORIG_COMPLEX.escape_default()
    );

    let mut g = c.benchmark_group("simple unescape");

    g.bench_function("fast-unescape-try-into", |b| {
        b.iter(|| {
            let mut buf = String::new();
            let _ = fast_unescape::try_unescape_into(black_box(&escaped), black_box(&mut buf));
        })
    });
    g.bench_function("fast-unescape-into", |b| {
        b.iter(|| {
            let mut buf = String::new();
            fast_unescape::unescape_into(black_box(&escaped), black_box(&mut buf));
        })
    });

    g.bench_function("fast-unescape-cow", |b| {
        b.iter(|| {
            let s = fast_unescape::unescape(black_box(&escaped));
            drop(black_box(s));
        })
    });
    g.bench_function("fast-unescape-try-cow", |b| {
        b.iter(|| {
            let s = fast_unescape::try_unescape(black_box(&escaped));
            drop(black_box(s));
        })
    });

    // alternatives
    g.bench_function("unescaper", |b| {
        b.iter(|| {
            let s = unescaper::unescape(black_box(&escaped)).unwrap();
            drop(black_box(s));
        })
    });

    g.finish();
}

criterion_group!(benches, benchmark);
criterion_main!(benches);
