1pub use base64ct::Error as B64Error;
4
5use core::cmp::Ordering;
6use core::fmt;
7
8pub type Result<T> = core::result::Result<T, Error>;
10
11#[derive(Copy, Clone, Debug, Eq, PartialEq)]
13#[non_exhaustive]
14pub enum Error {
15 Algorithm,
17
18 B64Encoding(B64Error),
20
21 Crypto,
23
24 OutputSize {
26 provided: Ordering,
32 expected: usize,
38 },
39
40 ParamNameDuplicated,
42
43 ParamNameInvalid,
45
46 ParamValueInvalid(InvalidValue),
48
49 ParamsMaxExceeded,
51
52 Password,
54
55 PhcStringField,
57
58 PhcStringTrailingData,
60
61 SaltInvalid(InvalidValue),
63
64 Version,
66
67 OutOfMemory,
69}
70
71impl fmt::Display for Error {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::result::Result<(), fmt::Error> {
73 match self {
74 Self::Algorithm => write!(f, "unsupported algorithm"),
75 Self::B64Encoding(err) => write!(f, "{err}"),
76 Self::Crypto => write!(f, "cryptographic error"),
77 Self::OutputSize { provided, expected } => match provided {
78 Ordering::Less => write!(
79 f,
80 "output size too short, expected at least {expected} bytes",
81 ),
82 Ordering::Equal => write!(f, "output size unexpected, expected {expected} bytes"),
83 Ordering::Greater => {
84 write!(f, "output size too long, expected at most {expected} bytes")
85 }
86 },
87 Self::ParamNameDuplicated => f.write_str("duplicate parameter"),
88 Self::ParamNameInvalid => f.write_str("invalid parameter name"),
89 Self::ParamValueInvalid(val_err) => write!(f, "invalid parameter value: {val_err}"),
90 Self::ParamsMaxExceeded => f.write_str("maximum number of parameters reached"),
91 Self::Password => write!(f, "invalid password"),
92 Self::PhcStringField => write!(f, "password hash string missing field"),
93 Self::PhcStringTrailingData => {
94 write!(f, "password hash string contains trailing characters")
95 }
96 Self::SaltInvalid(val_err) => write!(f, "salt invalid: {val_err}"),
97 Self::Version => write!(f, "invalid algorithm version"),
98 Self::OutOfMemory => write!(f, "out of memory"),
99 }
100 }
101}
102
103impl core::error::Error for Error {
104 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
105 match self {
106 Self::B64Encoding(err) => Some(err),
107 Self::ParamValueInvalid(err) => Some(err),
108 Self::SaltInvalid(err) => Some(err),
109 _ => None,
110 }
111 }
112}
113
114impl From<B64Error> for Error {
115 fn from(err: B64Error) -> Error {
116 Error::B64Encoding(err)
117 }
118}
119
120impl From<base64ct::InvalidLengthError> for Error {
121 fn from(_: base64ct::InvalidLengthError) -> Error {
122 Error::B64Encoding(B64Error::InvalidLength)
123 }
124}
125
126#[derive(Copy, Clone, Debug, Eq, PartialEq)]
128#[non_exhaustive]
129pub enum InvalidValue {
130 InvalidChar(char),
132
133 InvalidFormat,
135
136 Malformed,
138
139 TooLong,
141
142 TooShort,
144}
145
146impl InvalidValue {
147 pub fn param_error(self) -> Error {
149 Error::ParamValueInvalid(self)
150 }
151
152 pub fn salt_error(self) -> Error {
154 Error::SaltInvalid(self)
155 }
156}
157
158impl fmt::Display for InvalidValue {
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::result::Result<(), fmt::Error> {
160 match self {
161 Self::InvalidChar(c) => write!(f, "contains invalid character: '{c}'"),
162 Self::InvalidFormat => f.write_str("value format is invalid"),
163 Self::Malformed => f.write_str("value malformed"),
164 Self::TooLong => f.write_str("value to long"),
165 Self::TooShort => f.write_str("value to short"),
166 }
167 }
168}
169
170impl core::error::Error for InvalidValue {}