1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
//! Serde and plain-Preserves codec errors.
use num::bigint::BigInt;
use std::convert::From;
use std::io;
/// Representation of parse, deserialization, and other conversion errors.
#[derive(Debug)]
pub enum Error {
/// Generic IO error.
Io(io::Error),
/// Generic message for the user.
Message(String),
/// Invalid unicode scalar `n` found during interpretation of a `<UnicodeScalar n>` record
/// as a Rust `char`.
InvalidUnicodeScalar(u32),
/// Preserves supports arbitrary integers; when these are converted to specific Rust
/// machine word types, sometimes they exceed the available range.
NumberOutOfRange(BigInt),
/// Serde has limited support for deserializing free-form data; this error is signalled
/// when one of the limits is hit.
CannotDeserializeAny,
/// Syntax error: missing closing delimiter (`)`, `]`, `}`, `>` in text syntax; `0x84` in binary syntax; etc.)
MissingCloseDelimiter,
/// Signalled when an expected term is not present.
MissingItem,
/// Signalled when what was received did not match expectations.
Expected(ExpectedKind, Received),
#[doc(hidden)] // TODO remove this enum variant? It isn't used
StreamingSerializationUnsupported,
}
/// Used in [Error::Expected] to indicate what was received.
#[derive(Debug)]
pub enum Received {
#[doc(hidden)] // TODO remove this enum variant? It isn't used
ReceivedSomethingElse,
/// Received a record with the given label symbol text.
ReceivedRecordWithLabel(String),
/// Received some other value, described in the `String`
ReceivedOtherValue(String),
}
/// Used in [Error::Expected] to indicate what was expected.
#[derive(Debug, PartialEq)]
pub enum ExpectedKind {
Boolean,
Float,
Double,
SignedIntegerI128,
SignedIntegerU128,
SignedInteger,
String,
ByteString,
Symbol,
/// Expected a record, either of a specific arity (length) or of no specific arity
Record(Option<usize>),
/// Expected a record with a symbol label with text `String`, perhaps of some specific arity
SimpleRecord(String, Option<usize>),
Sequence,
Set,
Dictionary,
Embedded,
SequenceOrSet, // Because of hacking up serde's data model: see open_sequence_or_set etc.
Option,
UnicodeScalar,
}
impl From<io::Error> for Error {
fn from(e: io::Error) -> Self {
Error::Io(e)
}
}
impl From<Error> for io::Error {
fn from(e: Error) -> Self {
match e {
Error::Io(ioe) => ioe,
Error::Message(str) => io::Error::new(io::ErrorKind::Other, str),
_ => io::Error::new(io::ErrorKind::Other, e.to_string()),
}
}
}
impl serde::ser::Error for Error {
fn custom<T: std::fmt::Display>(msg: T) -> Self {
Self::Message(msg.to_string())
}
}
impl serde::de::Error for Error {
fn custom<T: std::fmt::Display>(msg: T) -> Self {
Self::Message(msg.to_string())
}
}
impl std::error::Error for Error {}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
//---------------------------------------------------------------------------
/// True iff `e` is `Error::Io`
pub fn is_io_error(e: &Error) -> bool {
matches!(e, Error::Io(_))
}
/// Produce the generic "end of file" error, `Error::Io(`[io_eof]`())`
pub fn eof() -> Error {
Error::Io(io_eof())
}
/// True iff `e` is an "end of file" error; see [is_eof_io_error]
pub fn is_eof_error(e: &Error) -> bool {
if let Error::Io(ioe) = e {
is_eof_io_error(ioe)
} else {
false
}
}
/// Produce a syntax error bearing the message `s`
pub fn syntax_error(s: &str) -> Error {
Error::Io(io_syntax_error(s))
}
/// True iff `e` is a syntax error; see [is_syntax_io_error]
pub fn is_syntax_error(e: &Error) -> bool {
if let Error::Io(ioe) = e {
is_syntax_io_error(ioe)
} else {
false
}
}
//---------------------------------------------------------------------------
/// Produce an [io::Error] of [io::ErrorKind::UnexpectedEof].
pub fn io_eof() -> io::Error {
io::Error::new(io::ErrorKind::UnexpectedEof, "EOF")
}
/// True iff `e` is [io::ErrorKind::UnexpectedEof]
pub fn is_eof_io_error(e: &io::Error) -> bool {
matches!(e.kind(), io::ErrorKind::UnexpectedEof)
}
/// Produce a syntax error ([io::ErrorKind::InvalidData]) bearing the message `s`
pub fn io_syntax_error(s: &str) -> io::Error {
io::Error::new(io::ErrorKind::InvalidData, s)
}
/// True iff `e` is an [io::ErrorKind::InvalidData] (a syntax error)
pub fn is_syntax_io_error(e: &io::Error) -> bool {
matches!(e.kind(), io::ErrorKind::InvalidData)
}