1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
use std::num::NonZeroU8;
use crate::{parse_id, Error};
pub fn validate(s: &str) -> Result<(NonZeroU8, bool), Error> {
let colon_idx = parse_id(s, &['@'])?;
let localpart = &s[1..colon_idx.get() as usize];
let is_historical = localpart_is_fully_comforming(localpart)?;
Ok((colon_idx, is_historical))
}
pub fn localpart_is_fully_comforming(localpart: &str) -> Result<bool, Error> {
let is_fully_conforming = localpart
.bytes()
.all(|b| matches!(b, b'0'..=b'9' | b'a'..=b'z' | b'-' | b'.' | b'=' | b'_' | b'/'));
if !is_fully_conforming && localpart.bytes().any(|b| b < 0x21 || b == b':' || b > 0x7E) {
Err(Error::InvalidCharacters)
} else {
Ok(is_fully_conforming)
}
}