fst_no_std/raw/
error.rs

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