fst/raw/
error.rs

1use std::fmt;
2use std::str;
3use std::string::FromUtf8Error;
4
5use crate::raw::FstType;
6
7/// An error that occurred while using a finite state transducer.
8///
9/// This enum is non-exhaustive. New variants may be added to it in
10/// compatible releases.
11pub enum Error {
12    /// A version mismatch occurred while reading a finite state transducer.
13    ///
14    /// This occurs when the API version (of the crate) does not match the
15    /// version encoded in the finite state transducer.
16    ///
17    /// When this error is encountered, there are only two ways to fix it:
18    ///
19    /// 1. Change the version of the library to one that is compatible with
20    ///    the given finite state transducer.
21    /// 2. Rebuild the finite state transducer.
22    Version {
23        /// The expected version, which is hard-coded into the current version
24        /// of this crate.
25        expected: u64,
26        /// The version read from the finite state transducer.
27        got: u64,
28    },
29    /// An unexpected error occurred while reading a finite state transducer.
30    /// Usually this occurs because the data is corrupted or is not actually
31    /// a finite state transducer serialized by this library.
32    Format {
33        /// The number of bytes given to the FST constructor.
34        size: usize,
35    },
36    /// An error that is returned if verification of an FST fails because of a
37    /// checksum mismatch.
38    ChecksumMismatch {
39        /// The checksum that was expected.
40        expected: u32,
41        /// The checksum that was actually computed.
42        got: u32,
43    },
44    /// An error that is returned if the caller attempts to verify an FST
45    /// that does not have a checksum, as is the case for all FSTs generated
46    /// by this crate before version `0.4`.
47    ChecksumMissing,
48    /// A duplicate key was inserted into a finite state transducer, which is
49    /// not allowed.
50    DuplicateKey {
51        /// The duplicate key.
52        got: Vec<u8>,
53    },
54    /// A key was inserted out of order into a finite state transducer.
55    ///
56    /// Keys must always be inserted in lexicographic order.
57    OutOfOrder {
58        /// The last key successfully inserted.
59        previous: Vec<u8>,
60        /// The key that caused this error to occur.
61        got: Vec<u8>,
62    },
63    /// A finite state transducer with an unexpected type was found.
64    ///
65    /// This is not currently used in this crate, but callers may wish to
66    /// employ its use for alternative data structures implemented on top of
67    /// finite state transducers.
68    WrongType {
69        /// The expected finite state transducer type.
70        expected: FstType,
71        /// The type read from a finite state transducer.
72        got: FstType,
73    },
74    /// An error that occurred when trying to decode a UTF-8 byte key.
75    FromUtf8(FromUtf8Error),
76    /// Hints that destructuring should not be exhaustive.
77    ///
78    /// This enum may grow additional variants, so this makes sure clients
79    /// don't count on exhaustive matching. (Otherwise, adding a new variant
80    /// could break existing code.)
81    #[doc(hidden)]
82    __Nonexhaustive,
83}
84
85impl fmt::Display for Error {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        match *self {
88            Error::FromUtf8(ref err) => err.fmt(f),
89            Error::Version { expected, got } => write!(
90                f,
91                "\
92Error opening FST: expected API version {}, got API version {}. \
93It looks like the FST you're trying to open is either not an FST file or it \
94was generated with a different version of the 'fst' crate. You'll either need \
95to change the version of the 'fst' crate you're using, or re-generate the
96FST.",
97                expected, got
98            ),
99            Error::Format { size } => write!(
100                f,
101                "\
102Error opening FST with size {} bytes: An unknown error occurred. This \
103usually means you're trying to read data that isn't actually an encoded FST.",
104                size
105            ),
106            Error::ChecksumMismatch { expected, got } => write!(
107                f,
108                "FST verification failed: expected checksum of {} but got {}",
109                expected, got,
110            ),
111            Error::ChecksumMissing => write!(
112                f,
113                "FST verification failed: FST does not contain a checksum",
114            ),
115            Error::DuplicateKey { ref got } => write!(
116                f,
117                "Error inserting duplicate key: '{}'.",
118                format_bytes(&*got)
119            ),
120            Error::OutOfOrder { ref previous, ref got } => write!(
121                f,
122                "\
123Error inserting out-of-order key: '{}'. (Previous key was '{}'.) Keys must be \
124inserted in lexicographic order.",
125                format_bytes(&*got),
126                format_bytes(&*previous)
127            ),
128            Error::WrongType { expected, got } => write!(
129                f,
130                "\
131Error opening FST: expected type '{}', got type '{}'.",
132                expected, got
133            ),
134            Error::__Nonexhaustive => unreachable!(),
135        }
136    }
137}
138
139impl fmt::Debug for Error {
140    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141        fmt::Display::fmt(self, f)
142    }
143}
144
145impl std::error::Error for Error {
146    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
147        match *self {
148            Error::FromUtf8(ref err) => Some(err),
149            _ => None,
150        }
151    }
152}
153
154impl From<FromUtf8Error> for Error {
155    #[inline]
156    fn from(err: FromUtf8Error) -> Error {
157        Error::FromUtf8(err)
158    }
159}
160
161/// Attempt to convert an arbitrary byte string to a more convenient display
162/// form.
163///
164/// Essentially, try to decode the bytes as UTF-8 and show that. Failing that,
165/// just show the sequence of bytes.
166fn format_bytes(bytes: &[u8]) -> String {
167    match str::from_utf8(bytes) {
168        Ok(s) => s.to_owned(),
169        Err(_) => format!("{:?}", bytes),
170    }
171}