oct 0.36.2

Octonary transcodings.
Documentation
// Copyright 2024-2026 Gabriel Bjørnager Jensen.
//
// SPDX: MIT OR Apache-2.0

//! The [`Read`] trait.

use oct::serdes::Result;

#[cfg(feature = "std")]
use std::io;

#[cfg(not(feature = "std"))]
use oct::serdes::Error;

/// Trait for deserialisation buffers.
///
/// This trait serves as a stripped-down version of
/// [`std::io::Read`] intended only for
/// deserialisation.
///
#[cfg_attr(not(feature = "std"), doc = "[`std::io::Read`]: <https://doc.rust-lang.org/nightly/std/io/trait.Read.html>")]
pub trait Read {
	/// Reads from the reader into the provided buffer.
	///
	/// *See also [`std::io::Read::read`].*
	///
	#[cfg_attr(not(feature = "std"), doc = "[`std::io::Read::read`]: <https://doc.rust-lang.org/nightly/std/io/trait.Read.html#tymethod.read>")]
	///
	/// # Errors
	///
	/// This method should forward any errors that might
	/// arise from reading. An inexact read is not
	/// considered an error.
	fn read(&mut self, buf: &mut [u8]) -> Result<usize>;

	/// Reads from the reader into the provided buffer,
	/// filling it exactly.
	///
	/// *See also [`std::io::Read::read_exact`].*
	///
	#[cfg_attr(not(feature = "std"), doc = "[`std::io::Read::reaD_exact`]: <https://doc.rust-lang.org/nightly/std/io/trait.Read.html#tymethod.read_exact>")]
	///
	/// # Errors
	///
	/// This method should return an appropriate error
	/// if the buffer could not be filled exactly.
	fn read_exact(&mut self, buf: &mut [u8]) -> Result<()>;
}

#[cfg(feature = "std")]
impl<T: ?Sized + io::Read> Read for T {
	#[inline]
	fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
		io::Read::read(self, buf).map_err(Into::into)
	}

	#[inline]
	fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
		io::Read::read_exact(self, buf).map_err(Into::into)
	}
}

// SORT: reference
#[cfg(not(feature = "std"))]
impl<T: ?Sized + Read> Read for &mut T {
	#[inline]
	fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
		T::read(*self, buf)
	}

	#[inline]
	fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
		T::read_exact(*self, buf)
	}
}

// SORT: slice
#[cfg(not(feature = "std"))]
impl Read for &[u8] {
	fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
		let count = buf.len().min(self.len());

		let (slot, remaining) = self.split_at(count);
		buf.copy_from_slice(slot);

		*self = remaining;
		Ok(count)
	}

	#[inline]
	fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
		if self.read(buf)? == buf.len() {
			Ok(())
		} else {
			Err(Error::unexpected_eof())
		}
	}
}