1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
use std::fmt;
/// When implementing the configure method of the Rule trait, the method returns a result that uses
/// this error type.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum RuleConfigurationError {
/// When a rule gets an unknown property. The string should be the unknown field name.
UnexpectedProperty(String),
/// When a rule has a required property. The string should be the field name.
MissingProperty(String),
/// When a property is associated with something else than an expected boolean. The string is
/// the property name.
BooleanExpected(String),
/// When a property is associated with something else than an expected string. The string is
/// the property name.
StringExpected(String),
/// When a property is associated with something else than an expected unsigned number. The
/// string is the property name.
UsizeExpected(String),
/// When a property is associated with something else than an expected float. The string is the
/// property name.
FloatExpected(String),
/// When a property is associated with something else than an expected list of strings. The
/// string is the property name.
StringListExpected(String),
/// When a property is associated with something else than an expected require mode. The
/// string is the property name.
RequireModeExpected(String),
/// When the value type is invalid. The string is the property name that was given the wrong
/// value type.
UnexpectedValueType(String),
/// When the value is invalid.
UnexpectedValue { property: String, message: String },
/// When a rule cannot have multiple properties defined at the same time.
PropertyCollision(Vec<String>),
/// When a rule can only be used internally by darklua. The string is the rule name
/// (this error should not surface to external consumers)
InternalUsageOnly(String),
}
fn enumerate_properties(properties: &[String]) -> String {
let last_index = properties.len().saturating_sub(1);
properties
.iter()
.enumerate()
.map(|(i, name)| {
if i == 0 {
format!("`{}`", name)
} else if i == last_index {
format!(" and `{}`", name)
} else {
format!(", `{}`", name)
}
})
.collect()
}
impl fmt::Display for RuleConfigurationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use RuleConfigurationError::*;
match self {
UnexpectedProperty(property) => write!(f, "unexpected field '{}'", property),
MissingProperty(property) => write!(f, "missing required field '{}'", property),
BooleanExpected(property) => {
write!(f, "boolean value expected for field '{}'", property)
}
StringExpected(property) => write!(f, "string value expected for field '{}'", property),
UsizeExpected(property) => {
write!(f, "unsigned integer expected for field '{}'", property)
}
FloatExpected(property) => write!(f, "float value expected for field '{}'", property),
StringListExpected(property) => {
write!(f, "list of string expected for field '{}'", property)
}
RequireModeExpected(property) => {
write!(f, "require mode value expected for field `{}`", property)
}
UnexpectedValueType(property) => write!(f, "unexpected type for field '{}'", property),
UnexpectedValue { property, message } => {
write!(f, "unexpected value for field '{}': {}", property, message)
}
PropertyCollision(properties) => write!(
f,
"the properties {} cannot be defined together",
enumerate_properties(properties)
),
InternalUsageOnly(rule_name) => {
write!(
f,
"usage of rule `{}` is reserved for darklua internal processing",
rule_name
)
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn enumerate_one_property() {
assert_eq!(enumerate_properties(&["prop".to_owned()]), "`prop`")
}
#[test]
fn enumerate_two_properties() {
assert_eq!(
enumerate_properties(&["prop".to_owned(), "prop2".to_owned()]),
"`prop` and `prop2`"
)
}
#[test]
fn enumerate_three_properties() {
assert_eq!(
enumerate_properties(&["prop".to_owned(), "prop2".to_owned(), "prop3".to_owned()]),
"`prop`, `prop2` and `prop3`"
)
}
}