#![no_std]
#![allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
#![deny(missing_docs)]
use core::{fmt, marker::PhantomData, mem};
#[cfg(feature = "std")]
extern crate std;
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "std")]
use std::{error, io, vec::Vec};
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
pub mod prelude {
pub use crate::{ReadBytes, ReadBytesExt, WriteBytes, WriteBytesExt};
}
pub type Result<T> = ::core::result::Result<T, Error>;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Error {
EndOfStream,
#[doc(hidden)]
#[allow(non_camel_case_types)]
_nonexhaustive(()),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Error::EndOfStream => f.write_str("unexpected end of stream"),
_ => unreachable!(),
}
}
}
#[cfg(feature = "std")]
impl error::Error for Error {}
#[cfg(feature = "std")]
impl From<Error> for io::Error {
fn from(error: Error) -> Self {
match error {
Error::EndOfStream => io::ErrorKind::UnexpectedEof.into(),
_ => unreachable!(),
}
}
}
pub trait ReadBytes<'a>: AsRef<[u8]> {
fn read_exact(&mut self, n: usize) -> &'a [u8];
fn try_read_exact(&mut self, n: usize) -> crate::Result<&'a [u8]> {
if n > self.as_ref().len() {
Err(Error::EndOfStream)
} else {
Ok(self.read_exact(n))
}
}
}
impl<'a> ReadBytes<'a> for &'a [u8] {
fn read_exact(&mut self, n: usize) -> &'a [u8] {
let (a, b) = self.split_at(n);
*self = b;
a
}
}
impl<'a> ReadBytes<'a> for &'a mut [u8] {
fn read_exact(&mut self, n: usize) -> &'a [u8] {
let (a, b) = mem::replace(self, &mut []).split_at_mut(n);
*self = b;
a
}
}
impl<'a, R: ReadBytes<'a>> ReadBytes<'a> for &'_ mut R {
fn read_exact(&mut self, n: usize) -> &'a [u8] {
(**self).read_exact(n)
}
fn try_read_exact(&mut self, n: usize) -> crate::Result<&'a [u8]> {
(**self).try_read_exact(n)
}
}
macro_rules! impl_read {
($doc:literal, $ty:ty, $fn:ident, $from_bytes:ident $( , )?) => {
#[doc = $doc]
#[inline]
fn $fn(&mut self) -> $ty {
<$ty>::$from_bytes(unsafe {
*(self.read_exact(mem::size_of::<$ty>()).as_ptr()
as *const [u8; mem::size_of::<$ty>()])
})
}
}
}
macro_rules! impl_try_read {
($doc:literal, $ty:ty, $fn:ident, $from_bytes:ident $( , )?) => {
#[doc = $doc]
#[inline]
fn $fn(&mut self) -> crate::Result<$ty> {
Ok(<$ty>::$from_bytes(unsafe {
*(self.try_read_exact(mem::size_of::<$ty>())?.as_ptr()
as *const [u8; mem::size_of::<$ty>()])
}))
}
}
}
pub trait ReadBytesExt<'a>: ReadBytes<'a> {
fn read_u8(&mut self) -> u8 {
self.read_exact(1)[0]
}
fn try_read_u8(&mut self) -> crate::Result<u8> {
Ok(self.try_read_exact(1)?[0])
}
fn read_i8(&mut self) -> i8 {
self.read_exact(1)[0] as _
}
fn try_read_i8(&mut self) -> crate::Result<i8> {
Ok(self.try_read_exact(1)?[0] as _)
}
impl_read! {
"Reads a little endian `u16` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
u16,
read_u16_le,
from_le_bytes,
}
impl_read! {
"Reads a big endian `u16` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
u16,
read_u16_be,
from_be_bytes,
}
impl_try_read! {
"Attempts to read a little endian `u16` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u16,
try_read_u16_le,
from_le_bytes,
}
impl_try_read! {
"Attempts to read a big endian `u16` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u16,
try_read_u16_be,
from_be_bytes,
}
impl_read! {
"Reads a little endian `i16` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
i16,
read_i16_le,
from_le_bytes,
}
impl_read! {
"Reads a big endian `i16` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
i16,
read_i16_be,
from_be_bytes,
}
impl_try_read! {
"Attempts to read a little endian `i16` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i16,
try_read_i16_le,
from_le_bytes,
}
impl_try_read! {
"Attempts to read a little endian `i16` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i16,
try_read_i16_be,
from_be_bytes,
}
impl_read! {
"Reads a little endian `u32` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
u32,
read_u32_le,
from_le_bytes,
}
impl_read! {
"Reads a big endian `u32` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
u32,
read_u32_be,
from_be_bytes,
}
impl_try_read! {
"Attempts to read a little endian `u32` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u32,
try_read_u32_le,
from_le_bytes,
}
impl_try_read! {
"Attempts to read a big endian `u32` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u32,
try_read_u32_be,
from_be_bytes,
}
impl_read! {
"Reads a little endian `i32` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
i32,
read_i32_le,
from_le_bytes,
}
impl_read! {
"Reads a big endian `i32` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
i32,
read_i32_be,
from_be_bytes,
}
impl_try_read! {
"Attempts to read a little endian `i32` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i32,
try_read_i32_le,
from_le_bytes,
}
impl_try_read! {
"Attempts to read a big endian `i32` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i32,
try_read_i32_be,
from_be_bytes,
}
impl_read! {
"Reads a little endian `u64` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
u64,
read_u64_le,
from_le_bytes,
}
impl_read! {
"Reads a big endian `u64` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
u64,
read_u64_be,
from_be_bytes,
}
impl_try_read! {
"Attempts to read a little endian `u64` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u64,
try_read_u64_le,
from_le_bytes,
}
impl_try_read! {
"Attempts to read a big endian `u64` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u64,
try_read_u64_be,
from_be_bytes,
}
impl_read! {
"Reads a little endian `i64` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
i64,
read_i64_le,
from_le_bytes,
}
impl_read! {
"Reads a big endian `i64` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
i64,
read_i64_be,
from_be_bytes,
}
impl_try_read! {
"Attempts to read a little endian `i64` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i64,
try_read_i64_le,
from_le_bytes,
}
impl_try_read! {
"Attempts to read a big endian `i64` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i64,
try_read_i64_be,
from_be_bytes,
}
impl_read! {
"Reads a little endian `u128` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
u128,
read_u128_le,
from_le_bytes,
}
impl_read! {
"Reads a big endian `u128` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
u128,
read_u128_be,
from_be_bytes,
}
impl_try_read! {
"Attempts to read a little endian `u128` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u128,
try_read_u128_le,
from_le_bytes,
}
impl_try_read! {
"Attempts to read a big endian `u128` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u128,
try_read_u128_be,
from_be_bytes,
}
impl_read! {
"Reads a little endian `i128` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
i128,
read_i128_le,
from_le_bytes,
}
impl_read! {
"Reads a big endian `i128` from the underlying buffer.
# Panics
Panics if there are not enough bytes in `self`.",
i128,
read_i128_be,
from_be_bytes,
}
impl_try_read! {
"Attempts to read a little endian `i128` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i128,
try_read_i128_le,
from_le_bytes,
}
impl_try_read! {
"Attempts to read a big endian `i128` from the underlying buffer.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i128,
try_read_i128_be,
from_be_bytes,
}
fn read_f32_le(&mut self) -> f32 {
f32::from_bits(self.read_u32_le())
}
fn read_f32_be(&mut self) -> f32 {
f32::from_bits(self.read_u32_be())
}
fn try_read_f32_le(&mut self) -> crate::Result<f32> {
Ok(f32::from_bits(self.try_read_u32_le()?))
}
fn try_read_f32_be(&mut self) -> crate::Result<f32> {
Ok(f32::from_bits(self.try_read_u32_be()?))
}
fn read_f64_le(&mut self) -> f64 {
f64::from_bits(self.read_u64_le())
}
fn read_f64_be(&mut self) -> f64 {
f64::from_bits(self.read_u64_be())
}
fn try_read_f64_le(&mut self) -> crate::Result<f64> {
Ok(f64::from_bits(self.try_read_u64_le()?))
}
fn try_read_f64_be(&mut self) -> crate::Result<f64> {
Ok(f64::from_bits(self.try_read_u64_be()?))
}
}
impl<'a, R: ReadBytes<'a>> ReadBytesExt<'a> for R {}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Reader<'a, R: ReadBytes<'a>>(R, usize, PhantomData<&'a ()>);
impl<'a, R: ReadBytes<'a>> Reader<'a, R> {
#[inline]
pub fn new(reader: R) -> Self {
Self(reader, 0, PhantomData)
}
#[inline]
pub fn num_bytes_read(&self) -> usize {
self.1
}
#[inline]
pub fn into_inner(self) -> R {
self.0
}
}
impl<'a, R: ReadBytes<'a>> AsRef<[u8]> for Reader<'a, R> {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl<'a, R: ReadBytes<'a>> ReadBytes<'a> for Reader<'a, R> {
fn read_exact(&mut self, n: usize) -> &'a [u8] {
self.1 += n;
self.0.read_exact(n)
}
fn try_read_exact(&mut self, n: usize) -> crate::Result<&'a [u8]> {
match self.0.try_read_exact(n) {
res @ Ok(_) => {
self.1 += n;
res
}
res @ Err(_) => res,
}
}
}
#[cfg(feature = "std")]
impl<'a, R: ReadBytes<'a>> io::Read for Reader<'a, R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let n = ::core::cmp::min(buf.len(), self.as_ref().len());
buf[..n].copy_from_slice(<Self as ReadBytes>::read_exact(self, n));
Ok(n)
}
}
pub trait WriteBytes: AsMut<[u8]> {
fn write_exact(&mut self, buf: &[u8]);
fn try_write_exact(&mut self, buf: &[u8]) -> crate::Result<()> {
if buf.len() > self.as_mut().len() {
Err(Error::EndOfStream)
} else {
self.write_exact(buf);
Ok(())
}
}
}
impl WriteBytes for &'_ mut [u8] {
fn write_exact(&mut self, buf: &[u8]) {
let (a, b) = mem::replace(self, &mut []).split_at_mut(buf.len());
a.copy_from_slice(&buf);
*self = b;
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl WriteBytes for Vec<u8> {
fn write_exact(&mut self, buf: &[u8]) {
self.extend_from_slice(buf);
}
fn try_write_exact(&mut self, buf: &[u8]) -> crate::Result<()> {
self.write_exact(buf);
Ok(())
}
}
impl<W: WriteBytes> WriteBytes for &'_ mut W {
fn write_exact(&mut self, buf: &[u8]) {
(**self).write_exact(buf)
}
fn try_write_exact(&mut self, buf: &[u8]) -> crate::Result<()> {
(**self).try_write_exact(buf)
}
}
macro_rules! impl_write {
($doc:literal, $ty:ty, $fn:ident, $to_bytes:ident $( , )?) => {
#[doc = $doc]
#[inline]
fn $fn(&mut self, n: $ty) {
self.write_exact(&n.$to_bytes()[..]);
}
}
}
macro_rules! impl_try_write {
($doc:literal, $ty:ty, $fn:ident, $to_bytes:ident $( , )?) => {
#[doc = $doc]
#[inline]
fn $fn(&mut self, n: $ty) -> crate::Result<()> {
self.try_write_exact(&n.$to_bytes()[..])?;
Ok(())
}
}
}
pub trait WriteBytesExt: WriteBytes {
#[inline]
fn write_u8(&mut self, n: u8) {
self.write_exact(&[n]);
}
#[inline]
fn try_write_u8(&mut self, n: u8) -> crate::Result<()> {
self.try_write_exact(&[n])?;
Ok(())
}
#[inline]
fn write_i8(&mut self, n: i8) {
self.write_exact(&[n as _]);
}
#[inline]
fn try_write_i8(&mut self, n: i8) -> crate::Result<()> {
self.try_write_exact(&[n as _])?;
Ok(())
}
impl_write! {
"Writes a `u16` into the underlying buffer in little endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
u16,
write_u16_le,
to_le_bytes,
}
impl_write! {
"Writes a `u16` into the underlying buffer in big endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
u16,
write_u16_be,
to_be_bytes,
}
impl_try_write! {
"Attempts to write a `u16` into the underlying buffer in little endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u16,
try_write_u16_le,
to_le_bytes,
}
impl_try_write! {
"Attempts to write a `u16` into the underlying buffer in big endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u16,
try_write_u16_be,
to_be_bytes,
}
impl_write! {
"Writes an `i16` into the underlying buffer in little endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
i16,
write_i16_le,
to_le_bytes,
}
impl_write! {
"Writes an `i16` into the underlying buffer in big endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
i16,
write_i16_be,
to_be_bytes,
}
impl_try_write! {
"Attempts to write an `i16` into the underlying buffer in little endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i16,
try_write_i16_le,
to_le_bytes,
}
impl_try_write! {
"Attempts to write an `i16` into the underlying buffer in big endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i16,
try_write_i16_be,
to_be_bytes,
}
impl_write! {
"Writes a `u32` into the underlying buffer in little endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
u32,
write_u32_le,
to_le_bytes,
}
impl_write! {
"Writes a `u32` into the underlying buffer in big endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
u32,
write_u32_be,
to_be_bytes,
}
impl_try_write! {
"Attempts to write a `u32` into the underlying buffer in little endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u32,
try_write_u32_le,
to_le_bytes,
}
impl_try_write! {
"Attempts to write a `u32` into the underlying buffer in big endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u32,
try_write_u32_be,
to_be_bytes,
}
impl_write! {
"Writes an `i32` into the underlying buffer in little endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
i32,
write_i32_le,
to_le_bytes,
}
impl_write! {
"Writes an `i32` into the underlying buffer in big endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
i32,
write_i32_be,
to_be_bytes,
}
impl_try_write! {
"Attempts to write an `i32` into the underlying buffer in little endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i32,
try_write_i32_le,
to_le_bytes,
}
impl_try_write! {
"Attempts to write an `i32` into the underlying buffer in big endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i32,
try_write_i32_be,
to_be_bytes,
}
impl_write! {
"Writes a `u64` into the underlying buffer in little endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
u64,
write_u64_le,
to_le_bytes,
}
impl_write! {
"Writes a `u64` into the underlying buffer in big endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
u64,
write_u64_be,
to_be_bytes,
}
impl_try_write! {
"Attempts to write a `u64` into the underlying buffer in little endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u64,
try_write_u64_le,
to_le_bytes,
}
impl_try_write! {
"Attempts to write a `u64` into the underlying buffer in big endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u64,
try_write_u64_be,
to_be_bytes,
}
impl_write! {
"Writes an `i64` into the underlying buffer in little endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
i64,
write_i64_le,
to_le_bytes,
}
impl_write! {
"Writes an `i64` into the underlying buffer in big endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
i64,
write_i64_be,
to_be_bytes,
}
impl_try_write! {
"Attempts to write an `i64` into the underlying buffer in little endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i64,
try_write_i64_le,
to_le_bytes,
}
impl_try_write! {
"Attempts to write an `i64` into the underlying buffer in big endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i64,
try_write_i64_be,
to_be_bytes,
}
impl_write! {
"Writes a `u128` into the underlying buffer in little endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
u128,
write_u128_le,
to_le_bytes,
}
impl_write! {
"Writes a `u128` into the underlying buffer in big endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
u128,
write_u128_be,
to_be_bytes,
}
impl_try_write! {
"Attempts to write a `u128` into the underlying buffer in little endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u128,
try_write_u128_le,
to_le_bytes,
}
impl_try_write! {
"Attempts to write a `u128` into the underlying buffer in big endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
u128,
try_write_u128_be,
to_be_bytes,
}
impl_write! {
"Writes an `i128` into the underlying buffer in little endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
i128,
write_i128_le,
to_le_bytes,
}
impl_write! {
"Writes an `i128` into the underlying buffer in big endian byte order.
# Panics
Panics if there are not enough bytes in `self`.",
i128,
write_i128_be,
to_be_bytes,
}
impl_try_write! {
"Attempts to write an `i128` into the underlying buffer in little endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i128,
try_write_i128_le,
to_le_bytes,
}
impl_try_write! {
"Attempts to write an `i128` into the underlying buffer in big endian byte order.
If there are not enough bytes in `self` this function will return `Error::EndOfStream`.",
i128,
try_write_i128_be,
to_be_bytes,
}
fn write_f32_le(&mut self, n: f32) {
self.write_u32_le(n.to_bits());
}
fn write_f32_be(&mut self, n: f32) {
self.write_u32_be(n.to_bits());
}
fn try_write_f32_le(&mut self, n: f32) -> crate::Result<()> {
self.try_write_u32_le(n.to_bits())
}
fn try_write_f32_be(&mut self, n: f32) -> crate::Result<()> {
self.try_write_u32_be(n.to_bits())
}
fn write_f64_le(&mut self, n: f64) {
self.write_u64_le(n.to_bits());
}
fn write_f64_be(&mut self, n: f64) {
self.write_u64_be(n.to_bits());
}
fn try_write_f64_le(&mut self, n: f64) -> crate::Result<()> {
self.try_write_u64_le(n.to_bits())
}
fn try_write_f64_be(&mut self, n: f64) -> crate::Result<()> {
self.try_write_u64_be(n.to_bits())
}
}
impl<W: WriteBytes> WriteBytesExt for W {}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Writer<W: WriteBytes>(W, usize);
impl<W: WriteBytes> Writer<W> {
#[inline]
pub fn new(writer: W) -> Self {
Self(writer, 0)
}
#[inline]
pub fn num_bytes_written(&self) -> usize {
self.1
}
#[inline]
pub fn into_inner(self) -> W {
self.0
}
}
impl<W: WriteBytes> AsMut<[u8]> for Writer<W> {
fn as_mut(&mut self) -> &mut [u8] {
self.0.as_mut()
}
}
impl<W: WriteBytes> WriteBytes for Writer<W> {
fn write_exact(&mut self, buf: &[u8]) {
self.0.write_exact(buf);
self.1 += buf.len();
}
fn try_write_exact(&mut self, buf: &[u8]) -> crate::Result<()> {
match self.0.try_write_exact(buf) {
res @ Ok(_) => {
self.1 += buf.len();
res
}
res @ Err(_) => res,
}
}
}
#[cfg(feature = "std")]
impl<W: WriteBytes> io::Write for Writer<W> {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
let n = ::core::cmp::min(data.len(), self.as_mut().len());
<Self as WriteBytes>::write_exact(self, &data[..n]);
Ok(n)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
#[cfg(test)]
mod test {
#![allow(unused_imports)]
use super::*;
#[cfg(feature = "std")]
#[test]
fn io_error_from_error_end_of_stream() {
let err: io::Error = Error::EndOfStream.into();
assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof);
}
#[cfg(feature = "std")]
#[test]
#[should_panic]
fn io_error_from_error_nonexhaustive() {
let _: io::Error = Error::_nonexhaustive(()).into();
}
#[cfg(feature = "std")]
#[test]
fn display_error_end_of_stream() {
use std::string::ToString;
assert_eq!(Error::EndOfStream.to_string(), "unexpected end of stream");
}
#[cfg(feature = "std")]
#[test]
#[should_panic]
fn display_error_nonexhaustive() {
use std::string::ToString;
let _ = Error::_nonexhaustive(()).to_string();
}
}