1use core::fmt;
4
5pub(crate) type Result<T> = core::result::Result<T, Kind>;
6
7#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
9pub struct Error<'a> {
10 kind: Kind,
11 input: &'a str,
12}
13
14impl<'a> Error<'a> {
15 pub const fn kind(&self) -> Kind {
17 self.kind
18 }
19
20 pub const fn input(&self) -> &'a str {
22 self.input
23 }
24}
25
26impl<'a> fmt::Display for Error<'a> {
27 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28 match self.kind {
29 Kind::NameTooLong => write!(f, "'{}' is too long", self.input),
30 Kind::NetDisabled => write!(f, "'{}'; can't parse email addresses containing IP addresses when `net` feature is disabled", self.input),
31 Kind::EmptyLabel => write!(f, "'{}' contains an empty label", self.input),
32 Kind::EmailLocalTooLong => {
33 write!(f, "the user local part in '{}' is too long", self.input)
34 }
35 Kind::EmailTooLong => write!(f, "'{}' is too long for an email address", self.input),
36 Kind::EmptyName => write!(f, "name is empty"),
37 Kind::IllegalCharacter => write!(f, "'{}' contains an illegal character", self.input),
38 Kind::InvalidDomain => write!(f, "'{}' is not a valid domain name", self.input),
39 Kind::InvalidIpAddr => write!(f, "'{}' contains an invalid IP address", self.input),
40 Kind::LabelEndNotAlnum => {
41 write!(
42 f,
43 "'{}' has a label that does not end with an alphanumeric character",
44 self.input
45 )
46 }
47 Kind::LabelStartNotAlnum => {
48 write!(
49 f,
50 "'{}' has a label that does not start with an alphanumeric character",
51 self.input
52 )
53 }
54 Kind::LabelTooLong => write!(f, "'{}' has a label that is too long", self.input),
55 Kind::NoAtSign => write!(f, "'{}' does not have an @ sign", self.input),
56 Kind::NoHostPart => write!(f, "'{}' does not have a host part", self.input),
57 Kind::NoUserPart => write!(f, "'{}' does not have a user local part", self.input),
58 Kind::NumericTld => write!(f, "'{}' has a numeric TLD", self.input),
59 Kind::QuoteUnclosed => write!(f, "'{}' has an unclosed quotation mark", self.input),
60 Kind::TooManyLabels => write!(f, "'{}' contains too many labels", self.input),
61 }
62 }
63}
64
65#[cfg(feature = "std")]
66impl<'a> std::error::Error for Error<'a> {}
67
68#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
70#[non_exhaustive]
71pub enum Kind {
72 NameTooLong,
73 NetDisabled,
74 EmptyLabel,
75 EmailLocalTooLong,
76 EmailTooLong,
77 EmptyName,
78 IllegalCharacter,
79 InvalidDomain,
80 InvalidIpAddr,
81 LabelEndNotAlnum,
82 LabelStartNotAlnum,
83 LabelTooLong,
84 NoAtSign,
85 NoHostPart,
86 NoUserPart,
87 NumericTld,
88 QuoteUnclosed,
89 TooManyLabels,
90}
91
92impl Kind {
93 pub(crate) const fn error_with(self, input: &str) -> Error<'_> {
94 Error { kind: self, input }
95 }
96}
97
98#[cfg(feature = "std")]
99impl From<std::net::AddrParseError> for Kind {
100 fn from(_: std::net::AddrParseError) -> Self {
101 Self::InvalidIpAddr
102 }
103}