use crate::{Error, ErrorKind};
pub(crate) fn split_name(s: &str) -> (&str, &str) {
let s = s.trim_ascii_start();
let Some(split_at) = s.as_bytes().iter().position(|&c| c == b' ') else {
return (s, "");
};
unsafe { (s.get_unchecked(..split_at), s.get_unchecked(split_at + 1..)) }
}
pub(crate) fn strip_terminating_slash(s: &str) -> (&str, bool) {
match s.as_bytes() {
[s @ .., b' ', b'/'] | [s @ .., b'/'] => (unsafe { str::from_utf8_unchecked(s) }, true),
_ => (s, false),
}
}
pub fn validate(target: &str, error: ErrorKind) -> crate::Result<()> {
if is_valid(target) {
Ok(())
} else {
Err(Error::new(target, error))
}
}
pub fn validate_utf8(bytes: &[u8]) -> crate::Result<&str> {
if let Ok(utf8) = str::from_utf8(bytes) {
return Ok(utf8);
}
Err(Error::new(
String::from_utf8_lossy(bytes),
ErrorKind::InvalidUtf8,
))
}
pub const fn is_valid(target: &str) -> bool {
let [b'A'..=b'Z' | b'a'..=b'z', rest @ ..] = target.as_bytes() else {
return false;
};
let mut target = rest;
while let [first, rest @ ..] = target {
if !matches!(first, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z' | b'_' | b'-'| b'.') {
return false;
}
target = rest;
}
true
}