pub const NUL_CHARACTER: u16 = 1;
pub const UNESCAPED_CLOSE_BRACE: u16 = 2;
pub const INVALID_ESCAPE: u16 = 3;
pub const UNTERMINATED_PLACEHOLDER: u16 = 4;
pub const EMPTY_PLACEHOLDER: u16 = 5;
pub const UNEXPECTED_CHARACTER: u16 = 6;
pub const MISSING_WHITESPACE: u16 = 7;
pub const EXPECTED_NAME: u16 = 8;
pub const EXPECTED_EQUALS: u16 = 9;
pub const EXPECTED_OPTION_VALUE: u16 = 10;
pub const EXPECTED_LITERAL: u16 = 11;
pub const UNTERMINATED_QUOTED_LITERAL: u16 = 12;
pub const UNKNOWN_KEYWORD: u16 = 13;
pub const EXPECTED_EXPRESSION: u16 = 14;
pub const EXPECTED_VARIABLE_EXPRESSION: u16 = 15;
pub const EXPECTED_VARIABLE: u16 = 16;
pub const MISSING_BODY: u16 = 17;
pub const CONTENT_AFTER_BODY: u16 = 18;
pub const UNTERMINATED_QUOTED_PATTERN: u16 = 19;
pub const EXPECTED_SELECTOR: u16 = 20;
pub const EXPECTED_VARIANT: u16 = 21;
pub const EXPECTED_KEY: u16 = 22;
pub const EXPECTED_QUOTED_PATTERN: u16 = 23;
pub const MARKUP_NOT_ALLOWED: u16 = 24;
pub const EXPECTED_OPERAND: u16 = 25;
pub const SOURCE_TOO_LONG: u16 = 26;
pub const VARIANT_KEY_MISMATCH: u16 = 101;
pub const MISSING_FALLBACK_VARIANT: u16 = 102;
pub const MISSING_SELECTOR_ANNOTATION: u16 = 103;
pub const DUPLICATE_DECLARATION: u16 = 104;
pub const SELF_REFERENCING_DECLARATION: u16 = 105;
pub const DUPLICATE_OPTION_NAME: u16 = 106;
pub const DUPLICATE_VARIANT: u16 = 107;
pub fn describe(code: u16) -> Option<&'static str> {
Some(match code {
NUL_CHARACTER => "U+0000 is not allowed anywhere in a message",
UNESCAPED_CLOSE_BRACE => "`}` in text must be escaped as `\\}`",
INVALID_ESCAPE => "`\\` must be followed by `\\`, `{`, `|` or `}`",
UNTERMINATED_PLACEHOLDER => "a placeholder is missing its closing `}`",
EMPTY_PLACEHOLDER => "a placeholder is empty (`{}`)",
UNEXPECTED_CHARACTER => "a character that cannot appear here",
MISSING_WHITESPACE => "whitespace is required here",
EXPECTED_NAME => "a name must start here",
EXPECTED_EQUALS => "`=` expected",
EXPECTED_OPTION_VALUE => "an option needs a value: a literal or a variable",
EXPECTED_LITERAL => "an attribute's value must be a literal",
UNTERMINATED_QUOTED_LITERAL => "a quoted literal is missing its closing `|`",
UNKNOWN_KEYWORD => "not a keyword (`.input`, `.local`, `.match`)",
EXPECTED_EXPRESSION => "an expression `{…}` expected",
EXPECTED_VARIABLE_EXPRESSION => "`.input` needs a variable expression `{$name …}`",
EXPECTED_VARIABLE => "`.local` needs a variable `$name`",
MISSING_BODY => "a complex message needs a body: `{{…}}` or `.match`",
CONTENT_AFTER_BODY => "nothing may follow the body of a complex message",
UNTERMINATED_QUOTED_PATTERN => "a quoted pattern is missing its closing `}}`",
EXPECTED_SELECTOR => "`.match` needs at least one selector `$name`",
EXPECTED_VARIANT => "`.match` needs at least one variant",
EXPECTED_KEY => "a variant needs at least one key",
EXPECTED_QUOTED_PATTERN => "a variant needs a quoted pattern `{{…}}`",
MARKUP_NOT_ALLOWED => "markup is not allowed in a declaration",
EXPECTED_OPERAND => "an expression needs an operand or a function before attributes",
SOURCE_TOO_LONG => "the source is longer than u32::MAX bytes",
VARIANT_KEY_MISMATCH => "a variant's key count differs from the selector count",
MISSING_FALLBACK_VARIANT => "no variant has only catch-all keys",
MISSING_SELECTOR_ANNOTATION => {
"the selector does not reference a declaration with a function"
}
DUPLICATE_DECLARATION => "the variable was declared, or used, in a previous declaration",
SELF_REFERENCING_DECLARATION => {
"the declaration's own expression uses the variable it binds"
}
DUPLICATE_OPTION_NAME => "two options have the same name",
DUPLICATE_VARIANT => "two variants have the same keys",
_ => return None,
})
}
#[cfg(test)]
mod tests {
use super::describe;
#[test]
fn every_code_is_described_and_zero_is_not() {
for code in (1..=26).chain(101..=107) {
assert!(describe(code).is_some(), "{code}");
}
for code in [0, 27, 100, 108, u16::MAX] {
assert!(describe(code).is_none(), "{code}");
}
}
}