Module attribute_text
Expand description
Lexical scanning of .cstack attribute text: where string literals
are, where a trailing // comment starts, and where one attribute
ends and the next begins.
Shared by cratestack-parser (which strips comments and splits
attributes when it builds super::Attribute::raw, and refuses
shapes no generator reads) and cratestack-macros (which re-checks
every policy attribute before generating code, GHSA-69g4-xvcm-vm2j),
so the two cannot disagree about what is inside a string.
Three string forms, matching what the readers accept:
"""…"""is verbatim (a SQL body,super::sql_body): nothing escapes, a lone"inside is ordinary, only"""closes it."…"and'…'(policy literals may be single-quoted): only the same quote closes, and a backslash escapes the next character.
Outside strings, (/) and [/] nest.
Invisible characters are refused in attribute text wherever they
stand, strings included (invisible_character), and a diagnostic
never quotes one raw (escape_for_diagnostic).
Structs§
- Unquoted
- A character of attribute text that lies outside every string literal.
Constants§
- PRIMARY_
KEY_ ATTRIBUTE - The one spelling that marks a field as its model’s (or view’s) primary key.
Functions§
- attribute_
starts - Byte offsets of every
@inrawthat starts another attribute: one outside any string literal and any(...)/[...]group, after the text’s own leading@s, and not the second@of an@@. - comment_
start - Byte offset of the first
//outside a string literal: the start of a trailing comment, which runs to the end of the line. - describe_
invisible_ character U+200B (zero width space): the code point, with a name for the ones most likely to be met.- escape_
for_ diagnostic textwith every invisible or control character except line feed and tab written as\u{…}(module doc).- field_
attribute_ name - The bare name of a field-level attribute, with the
@sigil and any(...)argument list removed:@length(min: 1)->Some("length").Nonefor model-level@@...text or text without the sigil. - group_
end - Byte offset just past the
)/]that closes the group opened atopen(which must be a(or[outside any string), orNonewhen the text ends first. - invisible_
character - The byte offset and value of the first invisible character in the
attribute text
raw, inside a string literal or not. Whetherrawis a policy attribute (is_policy_attribute) is read fromrawitself. - invisible_
character_ in_ policy invisible_characterfor text the caller has read as a policy attribute itself: every variation selector is refused.- is_
default_ ignorable - Whether
chis a Unicode 16.0Default_Ignorable_Code_Point. - is_
policy_ attribute - Whether any attribute name in
raw, read loosely (super::loose_attribute_names: any case, invisible and punctuation characters dropped), isallow,denyorauthorize. - is_
primary_ key_ attribute - Whether
attributemarks its field as the primary key. Exact match onPRIMARY_KEY_ATTRIBUTE:@identity,@idxand@id_fooare other (unknown) attributes, not a primary key. - is_
relation_ attribute - Whether
attributeis a@relation/@relation(...)declaration — by name, so a bare@relationcounts too.@relationshipdoes not. - loose_
attribute_ names - The name of every attribute in
raw, read loosely: after each run of@s outside strings and groups, whitespace is skipped, the text up to the next(, whitespace,@or quote is taken, everything in it but letters, digits and_is dropped, and the rest is lower-cased. A default-ignorable character is dropped even when it counts as a letter (the Hangul filler U+3164 does).@ Deny (x)givesdeny, and so do@@de\u{200B}ny(x)(a zero-width space) and@@de-ny(x): an invisible or punctuation character inside the name must not turn a policy into an unknown, inert attribute. For re-checking that no attribute a reader would take for a policy was skipped, whatever its spelling. - split_
attributes rawcut into attributes at everyattribute_startsoffset that whitespace precedes, each with its byte offset inrawand trimmed. An@with no whitespace before it (@deny(x)@allow(y)) does not cut, so the run-together text reaches the validators whole and is refused there with a message naming both halves.- strip_
comment rawwithout its trailing//comment, if any, and without the whitespace before it.- substitute_
for_ display textwith every invisible character that is not whitespace replaced by one visible character, so it keeps its length in characters (module doc).- unquoted
- Every character of
rawoutside a string literal, in order. Quote characters themselves are not included.