use crate::{Length, Tag};
use core::{convert::Infallible, fmt};
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Error {
kind: ErrorKind,
position: Option<Length>,
}
impl Error {
pub fn new(kind: ErrorKind, position: Length) -> Error {
Error {
kind,
position: Some(position),
}
}
pub fn kind(self) -> ErrorKind {
self.kind
}
pub fn position(self) -> Option<Length> {
self.position
}
pub fn nested(self, nested_position: Length) -> Self {
let position = (nested_position + self.position.unwrap_or_default()).ok();
Self {
kind: self.kind,
position,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.kind)?;
if let Some(pos) = self.position {
write!(f, " at SIMPLE-TLV byte {}", pos)?;
}
Ok(())
}
}
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Error {
Error {
kind,
position: None,
}
}
}
impl From<core::convert::Infallible> for Error {
fn from(_: Infallible) -> Error {
unreachable!()
}
}
#[cfg(feature = "std")]
impl std::error::Error for ErrorKind {}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum ErrorKind {
Failed,
InvalidTag {
byte: u8,
},
InvalidLength,
Length {
tag: Tag,
},
Overflow,
Overlength,
TrailingData {
decoded: Length,
remaining: Length,
},
Truncated,
Underlength {
expected: Length,
actual: Length,
},
UnexpectedTag {
expected: Option<Tag>,
actual: Tag,
},
}
impl ErrorKind {
pub fn at(self, position: Length) -> Error {
Error::new(self, position)
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorKind::Failed => write!(f, "operation failed"),
ErrorKind::InvalidLength => write!(f, "length greater than protocol maximum"),
ErrorKind::Length { tag } => write!(f, "incorrect length for {}", tag),
ErrorKind::Overflow => write!(f, "integer overflow"),
ErrorKind::Overlength => write!(f, "SIMPLE-TLV message is too long"),
ErrorKind::TrailingData { decoded, remaining } => {
write!(
f,
"trailing data at end of SIMPLE-TLV message: decoded {} bytes, {} bytes remaining",
decoded, remaining
)
}
ErrorKind::Truncated => write!(f, "SIMPLE-TLV message is truncated"),
ErrorKind::Underlength { expected, actual } => write!(
f,
"SIMPLE-TLV message too short: expected {}, got {}",
expected, actual
),
ErrorKind::UnexpectedTag { expected, actual } => {
write!(f, "unexpected SIMPLE-TLV tag: ")?;
if let Some(tag) = expected {
write!(f, "expected {}, ", tag)?;
}
write!(f, "got {}", actual)
}
ErrorKind::InvalidTag { byte } => {
write!(f, "invalid SIMPLE-TLV tag: 0x{:02x}", byte)
}
}
}
}