1use core::fmt;
2
3pub type Result<T> = core::result::Result<T, Error>;
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub enum LengthRequirement {
9 Exactly(usize),
11 AtLeast(usize),
13 AtMost(usize),
15 Between { minimum: usize, maximum: usize },
17}
18
19impl fmt::Display for LengthRequirement {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 match self {
22 Self::Exactly(length) => write!(f, "exactly {length}"),
23 Self::AtLeast(length) => write!(f, "at least {length}"),
24 Self::AtMost(length) => write!(f, "at most {length}"),
25 Self::Between { minimum, maximum } => {
26 write!(f, "between {minimum} and {maximum}")
27 }
28 }
29 }
30}
31
32#[derive(Clone, Debug, Eq, PartialEq)]
34#[non_exhaustive]
35pub enum Error {
36 InvalidKeyLength { actual: usize },
38 InvalidParameters,
40 InvalidSegmentLength { actual: u32 },
43 InvalidPlaintextLength {
45 actual: usize,
46 required: LengthRequirement,
47 },
48 InvalidHeaderLength { actual: usize },
50 InvalidHeaderParameters,
52 InvalidHeaderTag,
54 InvalidCiphertextLength {
57 actual: usize,
58 required: LengthRequirement,
59 },
60 InvalidSegmentPrefix,
62 AuthenticationFailed,
64 Closed,
66 Truncated,
69 SegmentLimit,
71 OutputTooSmall { actual: usize, required: usize },
73 InvalidBufferState,
75 ProviderSelectionRequired,
77 LengthOverflow,
79 RngFailure,
81 CryptoFailure,
83}
84
85impl fmt::Display for Error {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 match self {
88 Self::InvalidKeyLength { actual } => {
89 write!(f, "FLOE keys must be 32 bytes, got {actual}")
90 }
91 Self::InvalidParameters => f.write_str("FLOE parameter sets do not match"),
92 Self::InvalidSegmentLength { actual } => {
93 let supported = crate::Parameters::VALID_SEGMENT_LENGTHS;
94 write!(
95 f,
96 "invalid FLOE segment length {actual}; supported lengths are {} through {}",
97 supported.start,
98 supported.end - 1
99 )
100 }
101 Self::InvalidPlaintextLength { actual, required } => write!(
102 f,
103 "invalid plaintext segment length {actual}; required {required}"
104 ),
105 Self::InvalidHeaderLength { actual } => write!(
106 f,
107 "FLOE headers must be {} bytes, got {actual}",
108 crate::HEADER_LENGTH
109 ),
110 Self::InvalidHeaderParameters => {
111 f.write_str("header parameters do not match the selected FLOE parameters")
112 }
113 Self::InvalidHeaderTag => f.write_str("invalid FLOE header tag"),
114 Self::InvalidCiphertextLength { actual, required } => write!(
115 f,
116 "invalid ciphertext segment length {actual}; required {required}"
117 ),
118 Self::InvalidSegmentPrefix => {
119 f.write_str("non-final FLOE segment has an invalid prefix")
120 }
121 Self::AuthenticationFailed => f.write_str("FLOE segment authentication failed"),
122 Self::Closed => f.write_str("FLOE online state is already closed"),
123 Self::Truncated => f.write_str("FLOE input has no authenticated final segment"),
124 Self::SegmentLimit => f.write_str("FLOE segment limit exceeded"),
125 Self::OutputTooSmall { actual, required } => {
126 write!(
127 f,
128 "output buffer is {actual} bytes; {required} bytes are required"
129 )
130 }
131 Self::InvalidBufferState => {
132 f.write_str("segment buffer is not prepared for this operation")
133 }
134 Self::ProviderSelectionRequired => {
135 f.write_str("multiple FLOE providers are compiled (")?;
136 for (index, provider) in crate::Provider::COMPILED.iter().enumerate() {
137 if index != 0 {
138 f.write_str(", ")?;
139 }
140 f.write_str(provider.name())?;
141 }
142 f.write_str(
143 ") and none was named; construct keys with \
144 Key::from_bytes_with_provider or Key::generate_with_provider",
145 )
146 }
147 Self::LengthOverflow => f.write_str("FLOE length calculation overflowed"),
148 Self::RngFailure => f.write_str("random backend generation failed"),
149 Self::CryptoFailure => f.write_str("cryptographic backend operation failed"),
150 }
151 }
152}
153
154impl std::error::Error for Error {}
155
156impl Error {
157 #[must_use]
176 pub fn io_source(error: &std::io::Error) -> Option<&Self> {
177 error
178 .get_ref()
179 .and_then(|source| source.downcast_ref::<Self>())
180 }
181}