inputx-wubi 1.4.0

Self-developed Wubi 86 encoder, dictionary, and dataset — zero-dependency, self-built finite-state index (inputx-fsa), WASM-ready. Powers the Inputx IME.
Documentation
//! 字根 → letter lookup, backed by a compile-time sorted `&[(char, u8)]`
//! table generated by `build.rs` from `data/zigen86.txt`. Binary search,
//! zero external deps (replaces the former phf::Map).

include!(concat!(env!("OUT_DIR"), "/zigen.phf.rs"));

/// Look up the key letter (lowercase ASCII) for a 字根.
///
/// Binary search over the sorted static table — no allocation, no sync.
#[inline]
pub fn lookup(zigen: char) -> Option<u8> {
    ZIGEN
        .binary_search_by_key(&zigen, |&(k, _)| k)
        .ok()
        .map(|i| ZIGEN[i].1)
}

/// Iterate all (字根, key letter) pairs in the embedded table (sorted by 字根).
pub fn iter() -> impl Iterator<Item = (char, u8)> + 'static {
    ZIGEN.iter().map(|&(k, v)| (k, v))
}

#[doc(hidden)]
pub fn entries_for_test() -> usize {
    ZIGEN.len()
}

#[cfg(test)]
#[test]
fn zigen_table_is_sorted() {
    // binary_search correctness depends on sort order — guard it.
    assert!(ZIGEN.windows(2).all(|w| w[0].0 < w[1].0), "ZIGEN must be sorted by char key");
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parses_canonical_25_plus_extras() {
        assert!(entries_for_test() >= 25);
        assert_eq!(lookup(''), Some(b'g'));
        assert_eq!(lookup(''), Some(b'f'));
        assert_eq!(lookup(''), Some(b'd'));
        assert_eq!(lookup(''), Some(b'x'));
        assert_eq!(lookup(''), Some(b'o'));
        assert_eq!(lookup(''), Some(b'g'));
        assert_eq!(lookup(''), Some(b'h'));
        assert_eq!(lookup('丿'), Some(b't'));
        assert_eq!(lookup(''), Some(b'y'));
        assert_eq!(lookup(''), Some(b'n'));
    }

    #[test]
    fn unknown_returns_none() {
        assert_eq!(lookup('Z'), None);
        assert_eq!(lookup('🍌'), None);
    }
}