use super::collapse_whitespace;
use super::registry::{DatatypeContext, DatatypeLibrary};
pub(crate) struct BuiltinLibrary;
impl DatatypeLibrary for BuiltinLibrary {
fn validate_params(&self, type_name: &str, params: &[(&str, &str)]) -> Result<(), String> {
if type_name != "string" && type_name != "token" {
return Err(format!(
"unknown built-in type `{type_name}` (only `string` and `token` exist)"
));
}
if let Some((name, _)) = params.first() {
return Err(format!("`{type_name}` takes no parameters, found `{name}`"));
}
Ok(())
}
fn matches(
&self,
type_name: &str,
_params: &[(&str, &str)],
_value: &str,
_context: &DatatypeContext,
) -> bool {
type_name == "string" || type_name == "token"
}
fn values_equal(
&self,
type_name: &str,
expected: &str,
_expected_context: &DatatypeContext,
actual: &str,
_actual_context: &DatatypeContext,
) -> bool {
if type_name == "token" {
collapse_whitespace(expected) == collapse_whitespace(actual)
} else {
expected == actual
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn context() -> DatatypeContext {
DatatypeContext::empty()
}
#[test]
fn string_equality_is_exact() {
assert!(!BuiltinLibrary.values_equal("string", "a b", &context(), "a b", &context()));
assert!(BuiltinLibrary.values_equal("string", "a b", &context(), "a b", &context()));
}
#[test]
fn token_equality_collapses_whitespace() {
assert!(BuiltinLibrary.values_equal("token", "a b", &context(), "a b", &context()));
assert!(BuiltinLibrary.values_equal("token", " a b ", &context(), "a b", &context()));
assert!(!BuiltinLibrary.values_equal("token", "a b", &context(), "a c", &context()));
}
#[test]
fn only_string_and_token_are_known() {
assert!(BuiltinLibrary.validate_params("string", &[]).is_ok());
assert!(BuiltinLibrary.validate_params("token", &[]).is_ok());
assert!(BuiltinLibrary.validate_params("NCName", &[]).is_err());
}
#[test]
fn no_parameters_are_accepted() {
assert!(
BuiltinLibrary
.validate_params("string", &[("pattern", "a*")])
.is_err()
);
}
}