Skip to main content

fpr_ff1/
error.rs

1//! The crate's error type (plan 00009 STEP-05).
2
3use core::fmt;
4
5/// What kind of input was rejected.
6///
7/// One variant per exception class in the `fpr-ff1` Python package, so code
8/// ported between the two maps each exception to exactly one kind:
9///
10/// | Kind | Python exception |
11/// |---|---|
12/// | [`KeyLength`](ErrorKind::KeyLength) | `KeyLengthError` |
13/// | [`Radix`](ErrorKind::Radix) | `RadixError` |
14/// | [`Length`](ErrorKind::Length) | `LengthError` |
15/// | [`ValueRange`](ErrorKind::ValueRange) | `ValueRangeError` |
16/// | [`TweakLength`](ErrorKind::TweakLength) | `TweakLengthError` |
17/// | [`Alphabet`](ErrorKind::Alphabet) | `AlphabetError` |
18/// | [`AlphabetRequired`](ErrorKind::AlphabetRequired) | `FF1Error` (the base class) |
19///
20/// Python's `BackendError` has no counterpart: backend selection is a
21/// Python-side concern.
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23#[non_exhaustive]
24pub enum ErrorKind {
25    /// The key is not 16, 24 or 32 bytes.
26    KeyLength,
27    /// The radix is outside `2 <= radix < 2**16`.
28    Radix,
29    /// The input length is below the minimum domain for the radix, or above
30    /// `2**32 - 1`.
31    Length,
32    /// A numeral is not less than the radix, or a character is not in the
33    /// alphabet.
34    ValueRange,
35    /// A tweak or a tweak-length bound is outside the configured bounds or
36    /// above the four-byte encodable maximum.
37    TweakLength,
38    /// The alphabet's length does not equal the radix, or a character repeats.
39    Alphabet,
40    /// The string interface was used without an alphabet.
41    AlphabetRequired,
42}
43
44/// A rejected input.
45///
46/// The message matches the Python package's for the same rejection. It never
47/// contains key material, a numeral value or a character from the input:
48/// validation errors are routinely logged, and those are secrets or
49/// plaintext. It names the offending position or length instead.
50#[derive(Debug, Clone, PartialEq, Eq)]
51pub struct Error {
52    kind: ErrorKind,
53    message: String,
54}
55
56impl Error {
57    pub(crate) fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
58        Self {
59            kind,
60            message: message.into(),
61        }
62    }
63
64    /// The kind of rejection.
65    pub fn kind(&self) -> ErrorKind {
66        self.kind
67    }
68}
69
70impl fmt::Display for Error {
71    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72        f.write_str(&self.message)
73    }
74}
75
76impl core::error::Error for Error {}