pub fn is_safe_name(name: &str) -> bool {
!name.is_empty() &&
!name.starts_with('.') &&
!name.starts_with('#') &&
!name.chars().any(is_forbidden_char)
}
fn is_forbidden_char(ch: char) -> bool {
match ch {
'/' |
'\\' |
'\0'..='\x1F' | '\x7F' |
'*' | '%' |
'\u{80}'..='\u{9F}' |
'\u{2028}' | '\u{2029}' => true,
_ => false,
}
}
#[cfg(test)]
mod test {
use super::is_safe_name;
#[test]
fn test_is_safe_name() {
assert!(is_safe_name("foo"));
assert!(is_safe_name("PRN"));
assert!(is_safe_name("Entwürfe"));
assert!(is_safe_name("郵便"));
assert!(is_safe_name("foo.bar"));
assert!(is_safe_name("folder #1"));
assert!(!is_safe_name("."));
assert!(!is_safe_name(".."));
assert!(!is_safe_name(".hidden"));
assert!(!is_safe_name("foo/bar"));
assert!(!is_safe_name("/foo"));
assert!(!is_safe_name("foo/"));
assert!(!is_safe_name("foo\\bar"));
assert!(!is_safe_name("#news"));
assert!(!is_safe_name("foo\0"));
assert!(!is_safe_name("foo\r"));
assert!(!is_safe_name("fo\x7Fo"));
assert!(!is_safe_name("foo*bar"));
assert!(!is_safe_name("foo%bar"));
assert!(!is_safe_name(""));
}
}