blob: b283771798f98ed0f40f4d92ae5a32a917a146db [file] [log] [blame]
use std::fmt;
use std::str;
use std::string::FromUtf8Error;
use crate::raw::FstType;
/// An error that occurred while using a finite state transducer.
///
/// This enum is non-exhaustive. New variants may be added to it in
/// compatible releases.
pub enum Error {
/// A version mismatch occurred while reading a finite state transducer.
///
/// This occurs when the API version (of the crate) does not match the
/// version encoded in the finite state transducer.
///
/// When this error is encountered, there are only two ways to fix it:
///
/// 1. Change the version of the library to one that is compatible with
/// the given finite state transducer.
/// 2. Rebuild the finite state transducer.
Version {
/// The expected version, which is hard-coded into the current version
/// of this crate.
expected: u64,
/// The version read from the finite state transducer.
got: u64,
},
/// An unexpected error occurred while reading a finite state transducer.
/// Usually this occurs because the data is corrupted or is not actually
/// a finite state transducer serialized by this library.
Format {
/// The number of bytes given to the FST constructor.
size: usize,
},
/// An error that is returned if verification of an FST fails because of a
/// checksum mismatch.
ChecksumMismatch {
/// The checksum that was expected.
expected: u32,
/// The checksum that was actually computed.
got: u32,
},
/// An error that is returned if the caller attempts to verify an FST
/// that does not have a checksum, as is the case for all FSTs generated
/// by this crate before version `0.4`.
ChecksumMissing,
/// A duplicate key was inserted into a finite state transducer, which is
/// not allowed.
DuplicateKey {
/// The duplicate key.
got: Vec<u8>,
},
/// A key was inserted out of order into a finite state transducer.
///
/// Keys must always be inserted in lexicographic order.
OutOfOrder {
/// The last key successfully inserted.
previous: Vec<u8>,
/// The key that caused this error to occur.
got: Vec<u8>,
},
/// A finite state transducer with an unexpected type was found.
///
/// This is not currently used in this crate, but callers may wish to
/// employ its use for alternative data structures implemented on top of
/// finite state transducers.
WrongType {
/// The expected finite state transducer type.
expected: FstType,
/// The type read from a finite state transducer.
got: FstType,
},
/// An error that occurred when trying to decode a UTF-8 byte key.
FromUtf8(FromUtf8Error),
/// Hints that destructuring should not be exhaustive.
///
/// This enum may grow additional variants, so this makes sure clients
/// don't count on exhaustive matching. (Otherwise, adding a new variant
/// could break existing code.)
#[doc(hidden)]
__Nonexhaustive,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Error::FromUtf8(ref err) => err.fmt(f),
Error::Version { expected, got } => write!(
f,
"\
Error opening FST: expected API version {}, got API version {}. \
It looks like the FST you're trying to open is either not an FST file or it \
was generated with a different version of the 'fst' crate. You'll either need \
to change the version of the 'fst' crate you're using, or re-generate the
FST.",
expected, got
),
Error::Format { size } => write!(
f,
"\
Error opening FST with size {} bytes: An unknown error occurred. This \
usually means you're trying to read data that isn't actually an encoded FST.",
size
),
Error::ChecksumMismatch { expected, got } => write!(
f,
"FST verification failed: expected checksum of {} but got {}",
expected, got,
),
Error::ChecksumMissing => write!(
f,
"FST verification failed: FST does not contain a checksum",
),
Error::DuplicateKey { ref got } => write!(
f,
"Error inserting duplicate key: '{}'.",
format_bytes(&*got)
),
Error::OutOfOrder { ref previous, ref got } => write!(
f,
"\
Error inserting out-of-order key: '{}'. (Previous key was '{}'.) Keys must be \
inserted in lexicographic order.",
format_bytes(&*got),
format_bytes(&*previous)
),
Error::WrongType { expected, got } => write!(
f,
"\
Error opening FST: expected type '{}', got type '{}'.",
expected, got
),
Error::__Nonexhaustive => unreachable!(),
}
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match *self {
Error::FromUtf8(ref err) => Some(err),
_ => None,
}
}
}
impl From<FromUtf8Error> for Error {
#[inline]
fn from(err: FromUtf8Error) -> Error {
Error::FromUtf8(err)
}
}
/// Attempt to convert an arbitrary byte string to a more convenient display
/// form.
///
/// Essentially, try to decode the bytes as UTF-8 and show that. Failing that,
/// just show the sequence of bytes.
fn format_bytes(bytes: &[u8]) -> String {
match str::from_utf8(bytes) {
Ok(s) => s.to_owned(),
Err(_) => format!("{:?}", bytes),
}
}