pub const WINDOWS_RESERVED_NAMES: &[&str] = &[
"CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2",
"LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
];
pub fn is_valid_name_chars(name: &str) -> bool {
for ch in name.chars() {
match ch {
'/' | '\\' => return false,
'\0' ..= '\x1F' | '\x7F' => return false,
'<' | '>' | ':' | '"' | '|' | '?' | '*' => return false,
'a' ..= 'z' | 'A' ..= 'Z' | '0' ..= '9' | '_' | '-' | '.' => {},
_ => return false,
}
}
true
}
pub fn is_valid_document_id_chars(name: &str) -> bool {
for ch in name.chars() {
match ch {
'/' | '\\' => return false,
'\0' ..= '\x1F' | '\x7F' => return false,
'<' | '>' | ':' | '"' | '|' | '?' | '*' => return false,
'a' ..= 'z' | 'A' ..= 'Z' | '0' ..= '9' | '_' | '-' => {},
_ => return false,
}
}
true
}
pub fn is_reserved_name(name: &str) -> bool {
let name_upper = name.to_uppercase();
let base_name = name_upper.split('.').next().unwrap_or(&name_upper);
WINDOWS_RESERVED_NAMES.contains(&name_upper.as_str()) || WINDOWS_RESERVED_NAMES.contains(&base_name)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_valid_name_chars() {
assert!(is_valid_name_chars("valid_name-123.txt"));
assert!(!is_valid_name_chars("invalid/name"));
assert!(!is_valid_name_chars("invalid\\name"));
assert!(!is_valid_name_chars("invalid<name>"));
assert!(!is_valid_name_chars("invalid:name"));
assert!(!is_valid_name_chars("invalid|name"));
assert!(!is_valid_name_chars("invalid?name"));
assert!(!is_valid_name_chars("invalid*name"));
assert!(!is_valid_name_chars("invalid\u{0001}name")); assert!(!is_valid_name_chars("invalid\u{FFFF}name")); }
}