Skip to main content

Crate regex_charclass

Crate regex_charclass 

Source
Expand description

Manipulate and convert regular expression character classes.

A character class is a set of char values. This crate stores one as an irange::RangeSet of Char, which keeps it as a sorted collection of non-overlapping inclusive ranges, and adds the operations a regular expression engine needs on top of it through the CharacterClass trait: building a set from a range of char or of codepoints, counting its members, and rendering it back as the shortest character class it can.

Set algebra — union, intersection, difference and complement — comes from irange. RangeSet, AnyRange and Char are re-exported at the crate root, so a dependent needs neither its own dependency on irange nor a version kept in step with this crate’s. The whole crate is also re-exported as regex_charclass::irange.

§Example

use regex_charclass::{AnyRange, Char, CharacterClass, RangeSet};

let letters = RangeSet::new_from_range_char('a'..='z');
assert_eq!(26, letters.get_cardinality());
assert_eq!("[a-z]", letters.to_regex());

let hex = RangeSet::new_from_ranges(&[
    AnyRange::from(Char::new('0')..=Char::new('9')),
    AnyRange::from(Char::new('A')..=Char::new('F')),
    AnyRange::from(Char::new('a')..=Char::new('f')),
]);
// A set matching a named Unicode property is rendered as that property.
assert_eq!("\\p{ASCII_Hex_Digit}", hex.to_regex());
assert_eq!("\\P{ASCII_Hex_Digit}", hex.complement().to_regex());

assert_eq!(".", hex.union(&hex.complement()).to_regex());
assert_eq!("[]", hex.intersection(&hex.complement()).to_regex());
assert_eq!("[g-z]", letters.difference(&hex).to_regex());

§The generated regular expression

to_regex returns the shortest form it finds for a set, in this order:

FormWhen
[]the set is empty
.the set holds every char
\n, \r, \t, \vthe set holds only that one char
\d, \s, \w, \D, \S, \Wthe set is exactly that Perl class
\p{Name}, \P{Name}the set is exactly a Unicode general category, script or boolean property
a, \.the set holds one char, escaped if it is a metacharacter
[a-z0-9], [^a-z]otherwise, complemented when that is shorter

Three of them need care from whoever reads them back:

  • [] is a placeholder for the empty set, not a pattern. An empty bracketed class is a parse error in every engine, so a set that may be empty has to be handled before the output reaches one. [^\s\S] is the usual pattern for a class matching nothing.
  • . stands for the total set, which includes \n, so the pattern needs dot-matches-newline ((?s)).
  • \p{Name} and the Perl classes stand for Unicode sets, so the pattern needs Unicode mode, which is the default in most engines. The tables here are generated from the Unicode character database a ucd-* feature selects, UCD_VERSION, so an engine built against another version may resolve a name to a slightly different set.

§The surrogate block

char is not contiguous: the codepoints U+D800..=U+DFFF are surrogates and hold no char. Char counts by index rather than by codepoint and skips that block, so '\u{D7FF}' and '\u{E000}' are adjacent and the total set is one range of 1,112,064 values rather than two. See Char for the details.

§Feature flags

The crate has no default features.

  • serde: implement Serialize and Deserialize for Char, and enable the same feature on irange so that a RangeSet<Char> round-trips.
  • ucd-17, ucd-16: the version of the Unicode character database the named classes are generated from, which decides both the set of names to_regex can return and the char each of them covers. Pick the one matching the engine that will read the output; the version in use is UCD_VERSION.

A build that names none of them gets the newest version. Only the selected version is compiled into the crate, so an unused one costs neither build time nor binary size.

Naming a version is what pins it: since none of them is a default feature, features = ["ucd-16"] selects Unicode 16 rather than being unified with a default that outranks it, and it stays on 16 when a later release adds a newer version. A build that names none floats to the newest version each release.

Cargo features are additive, though, so this only pins the version for a binary. If one dependent asks for ucd-16 while another asks for ucd-17, both features are enabled and the highest wins for the whole build. That keeps the outcome deterministic, but it does mean a library cannot pin the UCD version its dependents get. Where the exact version matters, assert on UCD_VERSION rather than assuming the feature you named is the one in force.

Re-exports§

pub use crate::char::Char;
pub use irange;

Modules§

char
The char wrapper a RangeSet stores.

Structs§

AnyRange
The set type this crate operates on, and the range type its constructors take, are irange’s. They are re-exported here so that a dependent needs neither its own dependency on irange nor a version kept in step with this crate’s. A range of integers, held as an inclusive (min, max) pair.
RangeSet
The set type this crate operates on, and the range type its constructors take, are irange’s. They are re-exported here so that a dependent needs neither its own dependency on irange nor a version kept in step with this crate’s. A structure holding a collection of u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128 or isize.

Constants§

UCD_VERSION
The version of the Unicode character database the named classes come from, as it is written in the UCD itself, for instance "17.0.0".

Traits§

CharacterClass
The char set operations a RangeSet<Char> gains.