use core::ops::{Bound, RangeBounds};
#[cfg(any(feature = "std", feature = "alloc"))]
pub use bytes::TryGetError;
#[derive(Debug, PartialEq, Eq)]
#[cfg(not(any(feature = "std", feature = "alloc")))]
pub struct TryGetError {
pub requested: usize,
pub available: usize,
}
#[cfg(not(any(feature = "std", feature = "alloc")))]
const _: () = {
impl core::fmt::Display for TryGetError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(
f,
"Not enough bytes remaining in buffer to read value (requested {} but only {} available)",
self.requested, self.available
)
}
}
impl core::error::Error for TryGetError {}
};
#[derive(Debug, PartialEq, Eq)]
pub struct TryPutError {
pub requested: usize,
pub available: usize,
}
impl core::fmt::Display for TryPutError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(
f,
"Not enough bytes remaining in buffer to write value (requested {} but only {} available)",
self.requested, self.available
)
}
}
impl core::error::Error for TryPutError {}
#[cfg(feature = "std")]
impl From<TryPutError> for std::io::Error {
fn from(value: TryPutError) -> Self {
std::io::Error::other(value)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InvalidIntegerLength(pub usize);
impl core::fmt::Display for InvalidIntegerLength {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(
f,
"invalid integer length: {} (must be less or equal to 8)",
self.0
)
}
}
impl core::error::Error for InvalidIntegerLength {}
#[cfg(feature = "std")]
impl From<InvalidIntegerLength> for std::io::Error {
fn from(value: InvalidIntegerLength) -> Self {
std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
}
}
impl From<InvalidIntegerLength> for TryPutIntegerError {
fn from(value: InvalidIntegerLength) -> Self {
TryPutIntegerError::InvalidLength(value)
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum TryPutIntegerError {
NotEnoughSpace(TryPutError),
InvalidLength(InvalidIntegerLength),
}
impl core::fmt::Display for TryPutIntegerError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
match self {
Self::NotEnoughSpace(err) => write!(f, "{}", err),
Self::InvalidLength(len) => write!(f, "{}", len),
}
}
}
impl core::error::Error for TryPutIntegerError {}
#[cfg(feature = "std")]
impl From<TryPutIntegerError> for std::io::Error {
fn from(value: TryPutIntegerError) -> Self {
std::io::Error::other(value)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct OutOfBounds {
pub requested: usize,
pub available: usize,
}
impl OutOfBounds {
#[inline]
pub const fn new(requested: usize, available: usize) -> Self {
Self {
requested,
available,
}
}
}
impl core::fmt::Display for OutOfBounds {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(
f,
"index out of bounds: requested {} but only {} available",
self.requested, self.available
)
}
}
impl core::error::Error for OutOfBounds {}
#[cfg(feature = "std")]
impl From<OutOfBounds> for std::io::Error {
fn from(value: OutOfBounds) -> Self {
std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct RangeOutOfBounds {
pub start: usize,
pub end: usize,
pub available: usize,
}
impl RangeOutOfBounds {
#[inline]
pub const fn new(start: usize, end: usize, available: usize) -> Self {
Self {
start,
end,
available,
}
}
}
impl core::fmt::Display for RangeOutOfBounds {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(
f,
"range out of bounds: requested {}..{} but only {} available",
self.start, self.end, self.available
)
}
}
impl core::error::Error for RangeOutOfBounds {}
pub(crate) fn normalize_range(
range: impl RangeBounds<usize>,
len: usize,
) -> Result<(usize, usize), RangeOutOfBounds> {
let start = match range.start_bound() {
Bound::Included(&n) => n,
Bound::Excluded(&n) => n
.checked_add(1)
.ok_or_else(|| RangeOutOfBounds::new(n, n, len))?,
Bound::Unbounded => 0,
};
let end = match range.end_bound() {
Bound::Included(&n) => n
.checked_add(1)
.ok_or_else(|| RangeOutOfBounds::new(start, n, len))?,
Bound::Excluded(&n) => n,
Bound::Unbounded => len,
};
if start > end || end > len {
return Err(RangeOutOfBounds::new(start, end, len));
}
Ok((start, end))
}
#[cfg(feature = "std")]
impl From<RangeOutOfBounds> for std::io::Error {
fn from(value: RangeOutOfBounds) -> Self {
std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Utf8Error {
InvalidCharBoundary {
at: usize,
},
OutOfBounds {
at: usize,
len: usize,
},
}
impl core::fmt::Display for Utf8Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
match self {
Self::InvalidCharBoundary { at } => {
write!(f, "index {} does not lie on a UTF-8 character boundary", at)
}
Self::OutOfBounds { at, len } => {
write!(f, "index {} out of bounds: length is {}", at, len)
}
}
}
}
impl core::error::Error for Utf8Error {}
#[cfg(feature = "std")]
impl From<Utf8Error> for std::io::Error {
fn from(value: Utf8Error) -> Self {
std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum FromBytesError {
InvalidUtf8(core::str::Utf8Error),
TooLarge(TryPutError),
}
impl core::fmt::Display for FromBytesError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
match self {
Self::InvalidUtf8(e) => write!(f, "invalid UTF-8: {}", e),
Self::TooLarge(e) => write!(f, "{}", e),
}
}
}
impl core::error::Error for FromBytesError {}
impl From<core::str::Utf8Error> for FromBytesError {
fn from(e: core::str::Utf8Error) -> Self {
Self::InvalidUtf8(e)
}
}
impl From<TryPutError> for FromBytesError {
fn from(e: TryPutError) -> Self {
Self::TooLarge(e)
}
}
#[cfg(feature = "std")]
impl From<FromBytesError> for std::io::Error {
fn from(value: FromBytesError) -> Self {
std::io::Error::new(std::io::ErrorKind::InvalidInput, value)
}
}