use winnow::error::{ErrMode, InputError};
use crate::parse;
pub fn is_valid_field_name(name: &str) -> bool {
parses_fully(parse::field_name, name)
}
pub fn is_valid_type_name(name: &str) -> bool {
parses_fully(parse::type_name, name)
}
pub fn is_valid_interface_name(name: &str) -> bool {
parses_fully(parse::interface_name, name)
}
fn parses_fully<'a, P, T>(mut parser: P, name: &'a str) -> bool
where
P: FnMut(&mut &'a [u8]) -> Result<T, ErrMode<InputError<&'a [u8]>>>,
{
let mut input = name.as_bytes();
parser(&mut input).is_ok() && input.is_empty()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn field_names() {
let valid = ["a", "Z", "user_name", "user0", "a_0_b", "type", "x__"];
for name in valid {
assert!(is_valid_field_name(name), "`{name}` must be valid");
}
let invalid = [
"",
"_foo",
"0foo",
"user-name",
"user name",
"user.name",
"user!",
"üser",
"user\u{e9}",
];
for name in invalid {
assert!(!is_valid_field_name(name), "`{name}` must be invalid");
}
}
#[test]
fn type_names() {
let valid = ["A", "Foo", "FileNotFound", "Foo0", "X"];
for name in valid {
assert!(is_valid_type_name(name), "`{name}` must be valid");
}
let invalid = [
"", "foo", "_Foo", "0Foo", "Foo_bar", "Foo-bar", "Foo bar", "Foo.Bar", "Foo!", "Über",
];
for name in invalid {
assert!(!is_valid_type_name(name), "`{name}` must be invalid");
}
}
#[test]
fn type_names_are_field_names() {
for name in ["A", "Foo", "FileNotFound", "Foo0"] {
assert!(is_valid_field_name(name), "`{name}` must be valid");
}
}
#[test]
fn interface_names() {
let valid = ["org.example.Foo", "a.b", "org.varlink.service", "a1.b-2.c3"];
for name in valid {
assert!(is_valid_interface_name(name), "`{name}` must be valid");
}
let invalid = [
"",
"Foo", "org.", ".org", "org..example", "org.example.", "1org.example", "org.example.Foo bar",
"org.example.Foö",
];
for name in invalid {
assert!(!is_valid_interface_name(name), "`{name}` must be invalid");
}
}
}