//! Shared helpers for the test suite.
//!
//! Each integration test binary pulls in this whole module but uses only part
//! of it, so unused items are expected here.
#![allow(dead_code)]

use serde::Deserialize;

/// One parity vector: an input and its expected base-62 output.
///
/// `input_units` holds the input as UTF-16 code units so control characters are
/// unambiguous in JSON. None of the vectors contain lone surrogates, so the
/// units always form a valid string.
#[derive(Deserialize)]
pub struct Vector {
    pub name: String,
    pub input_len: usize,
    pub input_units: Vec<u16>,
    pub compressed: String,
}

/// Load every parity vector from the bundled JSON fixture.
pub fn load_vectors() -> Vec<Vector> {
    let raw = include_str!("../fixtures/golden_vectors.json");
    serde_json::from_str(raw).expect("golden_vectors.json must parse")
}

/// Build a `String` from UTF-16 code units.
///
/// Every fixture vector is valid UTF-16, so this never loses data.
pub fn units_to_string(units: &[u16]) -> String {
    String::from_utf16(units).expect("fixture units must be valid UTF-16")
}

/// Build the printable ASCII sample: code points U+0020 through U+007E.
pub fn printable_ascii() -> String {
    (0x20u8..=0x7E).map(char::from).collect()
}

/// Compress while collecting streamed chunks. Returns the joined chunks.
///
/// `on_data` makes `compress_with` return an empty string, so the chunks are the
/// only output.
pub fn compress_streamed(input: &str) -> String {
    let mut chunks: Vec<String> = Vec::new();
    let returned = lzbase62::compress_with(
        input,
        lzbase62::Options::new().on_data(|c| chunks.push(c.to_string())),
    );
    assert_eq!(returned, "", "streaming compress returns empty string");
    chunks.join("")
}

/// Decompress while collecting streamed chunks. Returns the joined chunks.
///
/// `decompress_with` returns the full string even with `on_data`, so the joined
/// chunks must equal the return value.
pub fn decompress_streamed(input: &str) -> String {
    let mut chunks: Vec<String> = Vec::new();
    let returned = lzbase62::decompress_with(
        input,
        lzbase62::Options::new().on_data(|c| chunks.push(c.to_string())),
    );
    let joined = chunks.join("");
    assert_eq!(
        joined, returned,
        "streamed chunks equal the returned string"
    );
    joined
}
