o192 0.2.2

ORION-192: ordered, resilient, independent, URL-safe 192-bit IDs for distributed systems.
Documentation
//! Shared test helpers.
//!
//! Each integration test file in `tests/*.rs` is a separate crate, so
//! Cargo's dead-code lint may flag helpers that one file imports but
//! another does not. Suppress at the module level.

#![allow(dead_code)]

/// Decode a hex string to bytes. Panics on malformed input — fine for tests.
pub(crate) fn hex_to_bytes(hex: &str) -> Vec<u8> {
    assert!(hex.len() % 2 == 0, "hex must have even length");
    let bytes = hex.as_bytes();
    (0..hex.len())
        .step_by(2)
        .map(|i| {
            let hi = char_to_hex(bytes[i]);
            let lo = char_to_hex(bytes[i + 1]);
            (hi << 4) | lo
        })
        .collect()
}

fn char_to_hex(c: u8) -> u8 {
    match c {
        b'0'..=b'9' => c - b'0',
        b'a'..=b'f' => 10 + c - b'a',
        b'A'..=b'F' => 10 + c - b'A',
        _ => panic!("non-hex character: {c}"),
    }
}

/// One canonical conformance vector mirrored from `vectors/orion192.vectors.json`.
#[derive(Debug, Clone)]
pub(crate) struct Vector {
    pub(crate) name: &'static str,
    pub(crate) bytes_hex: &'static str,
    pub(crate) id: &'static str,
    pub(crate) relative_ms: u128,
    pub(crate) fraction4096: u16,
    pub(crate) counter: u32,
    pub(crate) random_hex: &'static str,
}

/// Hard-coded vectors. Kept in lock-step with `vectors/orion192.vectors.json`
/// and verified by `tests/vectors_json.rs` against the JSON file at build time.
pub(crate) fn vectors() -> Vec<Vector> {
    vec![
        Vector {
            name: "zero",
            bytes_hex: "000000000000000000000000000000000000000000000000",
            id: "00000000000000000000000000000000",
            relative_ms: 0,
            fraction4096: 0,
            counter: 0,
            random_hex: "0000000000000000000000000000",
        },
        Vector {
            name: "max",
            bytes_hex: "ffffffffffffffffffffffffffffffffffffffffffffffff",
            id: "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
            relative_ms: 281_474_976_710_655,
            fraction4096: 4095,
            counter: 1_048_575,
            random_hex: "ffffffffffffffffffffffffffff",
        },
        Vector {
            name: "layout-sample-1",
            bytes_hex: "0000075bcd158000303900112233445566778899aabbccdd",
            id: "0007MxpLW00lEG0H8ZD4LMPsY9bfjxoT",
            relative_ms: 123_456_789,
            fraction4096: 2048,
            counter: 12_345,
            random_hex: "00112233445566778899aabbccdd",
        },
        Vector {
            name: "layout-sample-2",
            bytes_hex: "018bcfe5687bc8a849eaffeeddccbbaa9988776655443322",
            id: "0OkFuMXwnAX9vk~jsSnwfeb8TrPLH3CY",
            relative_ms: 1_700_000_000_123,
            fraction4096: 3210,
            counter: 543_210,
            random_hex: "ffeeddccbbaa9988776655443322",
        },
        Vector {
            name: "boundary-counter-low",
            bytes_hex: "0000000003e880000064ffffffffffffffffffffffffffff",
            id: "000000FdW000PF~~~~~~~~~~~~~~~~~~",
            relative_ms: 1_000,
            fraction4096: 2048,
            counter: 100,
            random_hex: "ffffffffffffffffffffffffffff",
        },
        Vector {
            name: "boundary-counter-high",
            bytes_hex: "0000000003e8800000650000000000000000000000000000",
            id: "000000FdW000PG000000000000000000",
            relative_ms: 1_000,
            fraction4096: 2048,
            counter: 101,
            random_hex: "0000000000000000000000000000",
        },
    ]
}