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:
| Form | When |
|---|---|
[] | the set is empty |
. | the set holds every char |
\n, \r, \t, \v | the set holds only that one char |
\d, \s, \w, \D, \S, \W | the 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 aucd-*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: implementSerializeandDeserializeforChar, and enable the same feature onirangeso that aRangeSet<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 namesto_regexcan return and thechareach of them covers. Pick the one matching the engine that will read the output; the version in use isUCD_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§
Modules§
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 onirangenor a version kept in step with this crate’s. A range of integers, held as an inclusive(min, max)pair. - Range
Set - 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 onirangenor a version kept in step with this crate’s. A structure holding a collection ofu8,u16,u32,u64,u128,usize,i8,i16,i32,i64,i128orisize.
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§
- Character
Class - The
charset operations aRangeSet<Char>gains.