mongol_norm/lib.rs
1#![forbid(unsafe_code)]
2#![deny(missing_docs)]
3//! # mongol-norm
4//!
5//! Shape-aware normalizer for Traditional Mongolian (Hudum) script — the engine behind the
6//! `mongol-norm` PyPI package, whose PyO3 binding lives in the same repository under `python/`.
7//!
8//! Traditional Mongolian in Unicode has a fundamental problem: the same visible word can be
9//! encoded in many different code-point sequences (letters share glyphs, FVS selectors create
10//! equivalent spellings, joiners and MVS suffixes collapse more letters together). This crate
11//! implements a lightweight shaping engine — the UTN #57 v4 Mongolian-specific phase, driven only
12//! by the rule data of UTN #57 / mongfontbuilder, no font needed — and, on top of it, a canonical
13//! normalizer: within the bundled table's domain, `shape(x) == shape(y)` implies
14//! `normalize(x) == normalize(y)`, and `shape(normalize(x)) == shape(x)`.
15//!
16//! * [`Shaper::shape`] — text → written-unit sequence (`Mvs` and `Nirugu` appear verbatim; a
17//! `Zwj` only where it changes the ink), with the nine duplicate encodings unified (see
18//! [`Shaper::shape_raw`])
19//! * [`Shaper::same_shape`] — do two encodings render identically?
20//! * [`Shaper::normalize`] / [`Shaper::normalize_text`] — canonical, FVS-pinned Unicode
21//! * [`Shaper::normalize_written_units`] / [`Shaper::normalize_positioned_written_units`] —
22//! encode written units directly
23//! * [`Shaper::trace`] — per-rule condition transitions, for debugging and the golden fixtures
24//! * [`FontShaper`] (Cargo feature `font`) — the same `shape` through HarfBuzz rules: harfrust
25//! running mongfontbuilder's unified font, bundled without its outlines, for every writing
26//! system of the block
27//!
28//! The crate has no dependencies by default and builds for `wasm32-unknown-unknown` (the `font`
29//! feature adds harfrust and needs Rust 1.85). Its data tables are generated from the
30//! repository's JSON by `python/scripts/gen_rust_tables.py`, and the Python package of the same
31//! version calls straight into this crate. Design:
32//! <https://github.com/Satsrag/mongol-norm/blob/main/docs/superpowers/specs/2026-09-01-rust-core-design.md>.
33
34/// The crate README is compiled and run as a doctest, so its example cannot rot.
35#[cfg(doctest)]
36#[doc = include_str!("../README.md")]
37struct ReadmeDoctests;
38
39mod duplicates;
40mod error;
41#[cfg(feature = "font")]
42mod font;
43// clippy::all silences style lints on generated code (see the design doc).
44#[allow(clippy::all)]
45mod generated;
46mod normalize;
47mod redundant_zwj;
48mod rules;
49mod shaper;
50mod tables;
51mod token;
52mod unicode;
53mod written_units;
54
55#[doc(hidden)]
56pub mod cli;
57
58pub use error::Error;
59#[cfg(feature = "font")]
60pub use font::{FontShaper, ShapedGlyph};
61pub use generated::enums::{Alias, Condition, WrittenUnit};
62pub use shaper::{ConditionChange, RuleTransition, ShapeTrace, Shaper, TokenDetail};
63pub use tables::{Fvs, Locale, Position, UnitPosition};
64pub use unicode::{is_mongolian_letter, is_mongolian_word_char};
65pub use written_units::{PositionedWrittenUnit, MAX_POSITIONED_RECORDS};
66
67/// Crate version (the Cargo package version; lockstep with the Python package version).
68pub fn version() -> &'static str {
69 env!("CARGO_PKG_VERSION")
70}