use core::num::NonZeroUsize;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, thiserror::Error)]
#[error("not enough space available to encode value (requested {requested} but only {available} available)")]
pub struct InsufficientSpace {
requested: NonZeroUsize,
available: usize,
}
impl InsufficientSpace {
#[inline]
pub const fn new(requested: NonZeroUsize, available: usize) -> Self {
assert!(
requested.get() > available,
"InsufficientSpace: requested must be greater than available"
);
Self {
requested,
available,
}
}
#[inline]
pub const fn requested(&self) -> NonZeroUsize {
self.requested
}
#[inline]
pub const fn available(&self) -> usize {
self.available
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, thiserror::Error)]
#[non_exhaustive]
pub enum ConstEncodeError {
#[error(transparent)]
InsufficientSpace(#[from] InsufficientSpace),
#[error("{0}")]
Other(&'static str),
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl From<ConstEncodeError> for std::io::Error {
fn from(err: ConstEncodeError) -> Self {
match err {
ConstEncodeError::InsufficientSpace(_) => {
std::io::Error::new(std::io::ErrorKind::WriteZero, err)
}
ConstEncodeError::Other(msg) => std::io::Error::other(msg),
}
}
}
impl ConstEncodeError {
#[inline]
pub const fn insufficient_space(requested: NonZeroUsize, available: usize) -> Self {
Self::InsufficientSpace(InsufficientSpace::new(requested, available))
}
#[inline]
pub const fn other(msg: &'static str) -> Self {
Self::Other(msg)
}
#[inline]
pub(super) const fn update(self, requested: NonZeroUsize, available: usize) -> Self {
match self {
Self::InsufficientSpace(_) => {
Self::InsufficientSpace(InsufficientSpace::new(requested, available))
}
Self::Other(msg) => Self::Other(msg),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, thiserror::Error)]
#[non_exhaustive]
pub enum ConstDecodeError {
#[error("decoded value would overflow the target type")]
Overflow,
#[error(
"not enough bytes to decode value: only {available} were available, but more were requested"
)]
InsufficientData {
available: usize,
},
#[error("{0}")]
Other(&'static str),
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl From<ConstDecodeError> for std::io::Error {
fn from(err: ConstDecodeError) -> Self {
match err {
ConstDecodeError::Overflow => std::io::Error::new(std::io::ErrorKind::InvalidData, err),
ConstDecodeError::InsufficientData { .. } => {
std::io::Error::new(std::io::ErrorKind::UnexpectedEof, err)
}
ConstDecodeError::Other(msg) => std::io::Error::other(msg),
}
}
}
impl ConstDecodeError {
#[inline]
pub const fn overflow() -> Self {
Self::Overflow
}
#[inline]
pub const fn insufficient_data(available: usize) -> Self {
Self::InsufficientData { available }
}
#[inline]
pub const fn other(msg: &'static str) -> Self {
Self::Other(msg)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, thiserror::Error)]
#[non_exhaustive]
pub enum EncodeError {
#[error(transparent)]
InsufficientSpace(#[from] InsufficientSpace),
#[cfg(not(any(feature = "std", feature = "alloc")))]
#[error("{0}")]
Other(&'static str),
#[error("{0}")]
#[cfg(any(feature = "std", feature = "alloc"))]
Other(std::borrow::Cow<'static, str>),
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl From<EncodeError> for std::io::Error {
fn from(err: EncodeError) -> Self {
match err {
EncodeError::InsufficientSpace(_) => std::io::Error::new(std::io::ErrorKind::WriteZero, err),
EncodeError::Other(msg) => std::io::Error::other(msg),
}
}
}
impl From<ConstEncodeError> for EncodeError {
fn from(err: ConstEncodeError) -> Self {
match err {
ConstEncodeError::InsufficientSpace(iss) => EncodeError::InsufficientSpace(iss),
ConstEncodeError::Other(msg) => EncodeError::other(msg),
}
}
}
impl EncodeError {
#[inline]
pub const fn insufficient_space(requested: NonZeroUsize, available: usize) -> Self {
Self::InsufficientSpace(InsufficientSpace::new(requested, available))
}
#[inline]
#[cfg(not(any(feature = "std", feature = "alloc")))]
pub const fn other(msg: &'static str) -> Self {
Self::Other(msg)
}
#[inline]
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn other(msg: impl Into<std::borrow::Cow<'static, str>>) -> Self {
Self::Other(msg.into())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, thiserror::Error)]
#[non_exhaustive]
pub enum DecodeError {
#[error("decoded value would overflow the target type")]
Overflow,
#[error(
"not enough bytes to decode value: only {available} were available, but more were requested"
)]
InsufficientData {
available: usize,
},
#[error("{0}")]
#[cfg(not(any(feature = "std", feature = "alloc")))]
Other(&'static str),
#[error("{0}")]
#[cfg(any(feature = "std", feature = "alloc"))]
Other(std::borrow::Cow<'static, str>),
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl From<DecodeError> for std::io::Error {
fn from(err: DecodeError) -> Self {
match err {
DecodeError::Overflow => std::io::Error::new(std::io::ErrorKind::InvalidData, err),
DecodeError::InsufficientData { .. } => {
std::io::Error::new(std::io::ErrorKind::UnexpectedEof, err)
}
DecodeError::Other(msg) => std::io::Error::other(msg),
}
}
}
impl From<ConstDecodeError> for DecodeError {
fn from(err: ConstDecodeError) -> Self {
match err {
ConstDecodeError::Overflow => Self::Overflow,
ConstDecodeError::InsufficientData { available } => Self::InsufficientData { available },
ConstDecodeError::Other(msg) => Self::other(msg),
}
}
}
impl DecodeError {
#[inline]
pub const fn overflow() -> Self {
Self::Overflow
}
#[inline]
pub const fn insufficient_data(available: usize) -> Self {
Self::InsufficientData { available }
}
#[inline]
#[cfg(not(any(feature = "std", feature = "alloc")))]
pub const fn other(msg: &'static str) -> Self {
Self::Other(msg)
}
#[inline]
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn other(msg: impl Into<std::borrow::Cow<'static, str>>) -> Self {
Self::Other(msg.into())
}
}