use core::fmt;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum DecodeErrorKind {
Truncated,
InvalidVarint,
TagOverflowed,
WrongWireType,
OutOfDomainValue,
InvalidValue,
ConflictingFields,
UnexpectedlyRepeated,
NotCanonical,
UnknownField,
RecursionLimitReached,
Oversize,
Other,
}
use DecodeErrorKind::*;
impl fmt::Display for DecodeErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Truncated => "message or region truncated",
InvalidVarint => "invalid varint",
TagOverflowed => "tag overflowed",
WrongWireType => "wrong wire-type for value type",
OutOfDomainValue => "value out of domain",
InvalidValue => "invalid value",
ConflictingFields => "conflicting mutually-exclusive fields",
UnexpectedlyRepeated => "unexpectedly repeated item",
NotCanonical => "value not encoded canonically",
UnknownField => "unknown field",
RecursionLimitReached => "recursion limit reached",
Oversize => "region too large to decode",
Other => "other error",
})
}
}
impl From<&DecodeErrorKind> for DecodeErrorKind {
fn from(value: &DecodeErrorKind) -> Self {
*value
}
}
impl From<DecodeError> for DecodeErrorKind {
fn from(value: DecodeError) -> Self {
value.kind()
}
}
impl From<&DecodeError> for DecodeErrorKind {
fn from(value: &DecodeError) -> Self {
value.kind()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct FieldName {
pub message: &'static str,
pub field: &'static str,
}
#[derive(Clone, PartialEq, Eq)]
pub struct DecodeError {
kind: DecodeErrorKind,
#[cfg(feature = "detailed-errors")]
stack: thin_vec::ThinVec<FieldName>,
}
impl DecodeError {
#[doc(hidden)]
#[cold]
pub fn new(kind: DecodeErrorKind) -> DecodeError {
DecodeError {
kind,
#[cfg(feature = "detailed-errors")]
stack: Default::default(),
}
}
pub fn kind(&self) -> DecodeErrorKind {
self.kind
}
pub fn path(&self) -> &[FieldName] {
#[cfg(feature = "detailed-errors")]
return self.stack.as_slice();
#[cfg(not(feature = "detailed-errors"))]
return &[];
}
#[doc(hidden)]
pub fn push(&mut self, message: &'static str, field: &'static str) {
#[cfg(feature = "detailed-errors")]
self.stack.push(FieldName { message, field });
_ = (message, field);
}
}
impl From<DecodeErrorKind> for DecodeError {
fn from(kind: DecodeErrorKind) -> Self {
Self::new(kind)
}
}
impl fmt::Debug for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut s = f.debug_struct("DecodeError");
s.field("description", &self.kind);
#[cfg(feature = "detailed-errors")]
s.field("stack", &self.stack);
s.finish()
}
}
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("failed to decode Bilrost message: ")?;
#[cfg(feature = "detailed-errors")]
for FieldName { message, field } in self.stack.iter() {
write!(f, "{message}.{field}: ")?;
}
self.kind.fmt(f)
}
}
#[cfg(feature = "std")]
impl std::error::Error for DecodeError {}
#[cfg(feature = "std")]
impl From<DecodeError> for std::io::Error {
fn from(error: DecodeError) -> std::io::Error {
std::io::Error::new(std::io::ErrorKind::InvalidData, error)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct EncodeError {
required: usize,
remaining: usize,
}
impl EncodeError {
pub(crate) fn new(required: usize, remaining: usize) -> EncodeError {
EncodeError {
required,
remaining,
}
}
pub fn required_capacity(&self) -> usize {
self.required
}
pub fn remaining(&self) -> usize {
self.remaining
}
}
impl fmt::Display for EncodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"failed to encode Bilrost message; insufficient buffer capacity \
(required: {}, remaining: {})",
self.required, self.remaining
)
}
}
#[cfg(feature = "std")]
impl std::error::Error for EncodeError {}
#[cfg(feature = "std")]
impl From<EncodeError> for std::io::Error {
fn from(error: EncodeError) -> std::io::Error {
std::io::Error::new(std::io::ErrorKind::InvalidInput, error)
}
}