pub trait Profile: Sized {
type BaseProfile: CharProfile;
type Segmentation: Segmentation;
const APPEND_CLOSED: AppendClosed = AppendClosed::Empty;
// Required methods
fn is_ident_start(c: char) -> bool;
fn is_chunk_start(c: char) -> bool;
fn is_chunk_continue(c: char) -> bool;
// Provided method
fn in_profile(c: char) -> bool { ... }
}Expand description
Defines the valid composition of characters for a chunk (a slice of an identifier that contains no delimiters).
§Works on Character Code Points
Character profiles are defined in accordance with the default profile in Unicode Standard Annex #31, which defines validation along a string of character code-points, not necessarily along a string of valid graphemes.
If you need more complex validation, such as the emoji profile which must validate a specific ordering of special characters for emoji handling, you need to use a wrapper type to add that extra validation.
Provided Associated Constants§
Sourceconst APPEND_CLOSED: AppendClosed = AppendClosed::Empty
const APPEND_CLOSED: AppendClosed = AppendClosed::Empty
Whether or not a fragment containing characters in this profile are append-closed.
It’s always valid to set this to Empty, it just will lead to less
optimal codegen for your identifier.
§What Is Append-Closed?
Append-closed is a string property, where if we consider a set that contains all valid permutations of a string, appending one value from that set onto another equals some other value from the set.
It’s called “Append-Closed” because the operation we’re doing is “appending” one value onto another, and the operation will never result in a value outside of the set (e.g. the set is closed given this operation).
§When Is a Profile Chunk Append-Closed?
Simply put, if is_chunk_continue is a superset (or equal to) the set
of valid characters for is_ident_start and is_chunk_start,
then you can set this to Chunk.
Imagine we represent profile characters in a chunk as:
S= Chunk/Ident Start CharacterC= Chunk Continue Character
Abstractly, all valid chunks would be:
andSC*(empty string, orSfollowed by one or moreC)
A valid chunk of characters may be SCC, after appending some other
string we may be left with SCCSC, but if S ⊆ C, then we can
interpret any S character as a C character, and thus it’s
syntactically SCCCC (which is still valid and within this set).
§When Is a Profile Fragment Append-Closed?
This is a wider promise, which states that when used with a delimiter
that is APPEND_CLOSED, then all valid fragments are themselves also
append-closed (regardless of whether they contain delimiters or not).
Simply put, the profile needs to have the following properties:
- It must be
Chunkappend-closed (see above), and… is_chunk_startmust be identical tois_chunk_continue.
It’s easiest to understand this by looking at a case where it’s not
true - UpperCamel (or lowerCamel, but let’s just focus on upper).
Two valid UpperCamel fragments are:
Upper_(a perfectly valid start, but also has a trailing delimiter).camel(a continuation of a chunk, not the start of one)
If we append one onto the other, it may lead to an invalid fragment:
Upper_+camel=Upper_camel(which is not valid)
§When Is a Profile Identifier Append-Closed?
This is a wider promise, which states that if the profile were used
with a delimiter that also claimed to be Identifier append-closed,
then even identifiers themselves would be append-closed.
Simply put, the profile needs to have the following properties:
- It must be
Fragmentappend-closed (see above), and… is_ident_startmust be identical tois_chunk_startandis_chunk_continue.
§What Happens If This Is Set Incorrectly?
If this is set incorrectly, then it may be possible for some invalid fragments (and thus, identifiers) to be formed. It cannot lead to any memory issues or anything like that, just logical issues.
Required Associated Types§
Sourcetype BaseProfile: CharProfile
type BaseProfile: CharProfile
The underlying profile that this profile is based on.
This can be useful in identifying the core underlying profile for a type in a generic way (instead of handling each profile type specially). It comes in handy when there are case-conversions already present overtop of a profile.
§Implementation Suggestion
If you are defining a new profile (e.g., like Ascii, Unicode),
then you should set this to Self. If you are defining a new
CasedProfile (e.g., like Lower, Upper, etc). This should be
set to the profile that the cased profile wraps.
Sourcetype Segmentation: Segmentation
type Segmentation: Segmentation
The segmentation strategy that this profile uses.
Depending on the valid characters, different segmentation strategies
could apply. For instance, the Ascii profile rightly uses the
Char segmentation strategy (because it’s safe for it to).
The recommendation is:
- If your profile only consists of ASCII characters, use
Char. - Otherwise you should use the
Graphemestrategy.
§What Happens If This Is Set Incorrectly?
If this is set incorrectly, validation will not be impacted, but things
relating to segmentation would be (so any of the segments-like
methods may appear to be missing boundaries, for instance).
Required Methods§
Sourcefn is_ident_start(c: char) -> bool
fn is_ident_start(c: char) -> bool
Whether or not the provided character can appear at the absolute start of an identifier.
§Important
This is at the start of an identifier, not at the start of a
fragment or chunk. Valid at fragment-start is defined by
in_profile. Valid at chunk-start is defined by is_chunk_start.
However, note that it doesn’t require presence. So it would be bad to depend on this for a required character (like PHP’s dollar sign).
Sourcefn is_chunk_start(c: char) -> bool
fn is_chunk_start(c: char) -> bool
Whether or not the provided character can appear at the start of a new chunk (e.g. right after a delimiter).
§Important
This is at the start of a chunk, not at the start of a fragment or
identifier. Valid at fragment-start is defined by in_profile.
Valid at identifier-start is defined by is_ident_start.
However, note that it doesn’t require presence. So it would be bad to depend on this for a required character (like PHP’s dollar sign).
Sourcefn is_chunk_continue(c: char) -> bool
fn is_chunk_continue(c: char) -> bool
Whether or not the provided character is valid at any position after the first character of a chunk (a run of non-delimiter characters).
Provided Methods§
Sourcefn in_profile(c: char) -> bool
fn in_profile(c: char) -> bool
Whether or not the provided character can appear at any point in a chunk.
This should always be a superset (or equal-to) is_ident_start,
is_chunk_start, AND is_chunk_continue.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".