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}