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
68impl fmt::Display for Error {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::result::Result<(), fmt::Error> {
70 match self {
71 Self::Algorithm => write!(f, "unsupported algorithm"),
72 Self::B64Encoding(err) => write!(f, "{}", err),
73 Self::Crypto => write!(f, "cryptographic error"),
74 Self::OutputSize { provided, expected } => match provided {
75 Ordering::Less => write!(
76 f,
77 "output size too short, expected at least {} bytes",
78 expected
79 ),
80 Ordering::Equal => write!(f, "output size unexpected, expected {} bytes", expected),
81 Ordering::Greater => write!(
82 f,
83 "output size too long, expected at most {} bytes",
84 expected
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 }
99 }
100}
101
102#[cfg(feature = "std")]
103impl std::error::Error for Error {
104 fn source(&self) -> Option<&(dyn std::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
170#[cfg(feature = "std")]
171impl std::error::Error for InvalidValue {}