structured_email_address/
error.rs1use alloc::string::String;
4use core::fmt;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct Error {
9 kind: ErrorKind,
10 position: usize,
11}
12
13#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum ErrorKind {
16 Empty,
18 MissingAtSign,
20 EmptyLocalPart,
22 EmptyDomain,
24 LocalPartTooLong { len: usize },
26 AddressTooLong { len: usize },
28 DomainLabelTooLong { label: String, len: usize },
30 InvalidLocalPartChar { ch: char },
32 InvalidDomainChar { ch: char },
34 DomainLabelHyphen,
36 DomainNoDot,
38 UnterminatedQuotedString,
40 InvalidQuotedPair,
42 UnterminatedComment,
44 UnterminatedDomainLiteral,
46 InvalidAddressLiteral,
49 IdnaError(String),
51 UnknownTld(String),
53 Unexpected { ch: char },
55}
56
57impl Error {
58 pub(crate) fn new(kind: ErrorKind, position: usize) -> Self {
60 Self { kind, position }
61 }
62
63 pub fn kind(&self) -> &ErrorKind {
65 &self.kind
66 }
67
68 pub fn position(&self) -> usize {
70 self.position
71 }
72}
73
74impl fmt::Display for Error {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 match &self.kind {
77 ErrorKind::Empty => write!(f, "empty input"),
78 ErrorKind::MissingAtSign => write!(f, "missing '@' separator"),
79 ErrorKind::EmptyLocalPart => write!(f, "empty local part"),
80 ErrorKind::EmptyDomain => write!(f, "empty domain"),
81 ErrorKind::LocalPartTooLong { len } => {
82 write!(f, "local part too long: {len} octets (max 64)")
83 }
84 ErrorKind::AddressTooLong { len } => {
85 write!(f, "address too long: {len} octets (max 254)")
86 }
87 ErrorKind::DomainLabelTooLong { label, len } => {
88 write!(f, "domain label '{label}' too long: {len} octets (max 63)")
89 }
90 ErrorKind::InvalidLocalPartChar { ch } => {
91 write!(f, "invalid character in local part: '{ch}'")
92 }
93 ErrorKind::InvalidDomainChar { ch } => {
94 write!(f, "invalid character in domain: '{ch}'")
95 }
96 ErrorKind::DomainLabelHyphen => {
97 write!(f, "domain label starts or ends with hyphen")
98 }
99 ErrorKind::DomainNoDot => write!(f, "domain has no dot"),
100 ErrorKind::UnterminatedQuotedString => write!(f, "unterminated quoted string"),
101 ErrorKind::InvalidQuotedPair => write!(f, "invalid quoted-pair escape"),
102 ErrorKind::UnterminatedComment => write!(f, "unterminated comment"),
103 ErrorKind::UnterminatedDomainLiteral => write!(f, "unterminated domain literal"),
104 ErrorKind::InvalidAddressLiteral => {
105 write!(
106 f,
107 "domain literal is not a valid IPv4 or IPv6 address literal"
108 )
109 }
110 ErrorKind::IdnaError(msg) => write!(f, "IDNA encoding failed: {msg}"),
111 ErrorKind::UnknownTld(tld) => write!(f, "unknown TLD: .{tld}"),
112 ErrorKind::Unexpected { ch } => {
113 write!(
114 f,
115 "unexpected character '{ch}' at position {}",
116 self.position
117 )
118 }
119 }
120 }
121}
122
123impl core::error::Error for Error {}
127
128#[cfg(test)]
129mod tests;