Skip to main content

sup_xml_core/regex/ucd/
mod.rs

1//! Bundled Unicode Character Database snapshots.
2//!
3//! The XSLT / XPath spec doesn't pin a Unicode version — implementations
4//! report whatever they were built against.  Most production code paths
5//! in this crate use the latest UCD via the `unicode-properties` crate
6//! dependency.  Two corners of the W3C XSLT conformance suite, however,
7//! pin their expected answers to specific historical Unicode versions:
8//!
9//! * `tests/misc/regex-classes` — Unicode 6.0 (when these tests were
10//!   first written, ~2012).  120 cases.
11//! * `tests/misc/unicode-90` — Unicode 9.0 (deliberately added to
12//!   probe Unicode 9.0-only digits).  ~1440 cases.
13//!
14//! Bundling per-version `General_Category` snapshots costs ~45 KB of
15//! compiled data total and lets the regex engine answer those tests
16//! against the version they were authored for instead of skipping
17//! them.  Production users of `fn:matches` etc. continue to get the
18//! latest UCD by default.
19//!
20//! ## Provenance
21//!
22//! The static tables under `v6_0.rs` / `v9_0.rs` are generated from
23//! the official `UnicodeData.txt` files at
24//! `https://www.unicode.org/Public/<version>/ucd/UnicodeData.txt`
25//! by parsing each line's `General_Category` (field 2), merging
26//! contiguous codepoints with the same category, and emitting the
27//! result as `Range` arrays sorted by `start`.  Range markers
28//! (`<…, First>` / `<…, Last>`) expand to the inclusive span.
29
30pub mod v6_0;
31pub mod v9_0;
32
33/// A half-open inclusive codepoint range.  `start <= end`.  Used in
34/// the per-version `General_Category` tables to keep the bundled data
35/// compact (~8 bytes / entry on 32-bit codepoints).
36#[derive(Debug, Clone, Copy)]
37pub struct Range {
38    pub start: u32,
39    pub end:   u32,
40}
41
42/// Which Unicode snapshot the regex engine should consult when
43/// resolving `\p{…}` properties.  `Latest` defers to the
44/// `unicode-properties` crate (production code path); the older
45/// variants force lookup against the bundled snapshots.
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
47pub enum UnicodeVersion {
48    /// Whatever `unicode-properties` ships — what real consumers
49    /// of the library actually want (current Unicode at build time).
50    #[default]
51    Latest,
52    /// Unicode 6.0.0 — required by W3C `regex-classes` conformance.
53    V6_0,
54    /// Unicode 9.0.0 — required by W3C `unicode-90` conformance.
55    V9_0,
56}
57
58/// Look up a General_Category short-name (`Lu`, `Nd`, `Mn`, …) in the
59/// requested Unicode snapshot.  Returns the sorted range list for that
60/// category, or `None` if the name isn't a recognised category or the
61/// snapshot doesn't carry it.
62pub fn category(name: &str, version: UnicodeVersion) -> Option<&'static [Range]> {
63    match version {
64        UnicodeVersion::V6_0 => v6_0::category(name),
65        UnicodeVersion::V9_0 => v9_0::category(name),
66        // Latest is handled by the caller via the `unicode-properties`
67        // crate; this module is only consulted for the pinned versions.
68        UnicodeVersion::Latest => None,
69    }
70}