use {
crate::io::{BorrowKind, ReadResult, Reader, read_size_limit, slice::SliceScopedUnchecked},
core::{mem::MaybeUninit, ptr::copy_nonoverlapping},
std::io::{self, BufReader, Cursor, Read},
};
pub struct ReadAdapter<R: ?Sized>(R);
impl<R: Read> ReadAdapter<R> {
pub fn new(inner: R) -> Self {
Self(inner)
}
}
#[inline]
fn copy_into_slice<R: Read + ?Sized>(reader: &mut R, dst: &mut [u8]) -> ReadResult<()> {
#[cold]
fn maybe_eof_to_read_size_limit(err: io::Error, len: usize) -> ReadResult<()> {
if err.kind() == io::ErrorKind::UnexpectedEof {
Err(read_size_limit(len))
} else {
Err(err.into())
}
}
if let Err(e) = reader.read_exact(dst) {
return maybe_eof_to_read_size_limit(e, dst.len());
};
Ok(())
}
unsafe impl<R: Read + ?Sized> Reader<'_> for ReadAdapter<R> {
#[inline(always)]
fn copy_into_slice(&mut self, dst: &mut [u8]) -> ReadResult<()> {
copy_into_slice(&mut self.0, dst)
}
}
unsafe impl<R: Read + ?Sized> Reader<'_> for BufReader<R> {
#[inline(always)]
fn copy_into_slice(&mut self, dst: &mut [u8]) -> ReadResult<()> {
copy_into_slice(self, dst)
}
}
#[inline]
fn cursor_advance(cursor: &mut Cursor<impl AsRef<[u8]>>, n: usize) -> ReadResult<&[u8]> {
let Ok(pos) = usize::try_from(cursor.position()) else {
return Err(read_size_limit(usize::MAX));
};
let inner = cursor.get_ref().as_ref();
let next_pos = pos.saturating_add(n);
if next_pos > inner.len() {
return Err(read_size_limit(n));
}
cursor.set_position(next_pos as u64);
let inner = cursor.get_ref().as_ref();
Ok(&inner[pos..next_pos])
}
unsafe impl<'a, T> Reader<'a> for Cursor<T>
where
T: AsRef<[u8]>,
{
const BORROW_KINDS: u8 = BorrowKind::CallSite.mask();
#[inline]
fn copy_into_slice(&mut self, dst: &mut [u8]) -> ReadResult<()> {
let src = cursor_advance(self, dst.len())?;
unsafe { copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), dst.len()) };
Ok(())
}
#[inline]
fn copy_into_uninit_slice(&mut self, dst: &mut [MaybeUninit<u8>]) -> ReadResult<()> {
let src = cursor_advance(self, dst.len())?;
unsafe { copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr().cast::<u8>(), dst.len()) };
Ok(())
}
#[inline(always)]
fn take_array<const N: usize>(&mut self) -> ReadResult<[u8; N]> {
let src = cursor_advance(self, N)?;
Ok(unsafe { *(src.as_ptr().cast::<[u8; N]>()) })
}
#[inline]
fn take_scoped(&mut self, len: usize) -> ReadResult<&[u8]> {
cursor_advance(self, len)
}
#[inline]
unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> ReadResult<impl Reader<'a>> {
let buf = cursor_advance(self, n_bytes)?;
Ok(unsafe { SliceScopedUnchecked::new(buf) })
}
}
#[cfg(test)]
mod tests {
use super::*;
struct InspectingReader {
data: Vec<u8>,
pos: usize,
observed: Vec<u8>,
}
impl InspectingReader {
fn new(data: Vec<u8>) -> Self {
Self {
data,
pos: 0,
observed: Vec::new(),
}
}
}
impl Read for InspectingReader {
fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
self.observed.extend_from_slice(dst);
let remaining = &self.data[self.pos..];
let len = dst.len().min(remaining.len());
dst[..len].copy_from_slice(&remaining[..len]);
self.pos = self.pos.checked_add(len).unwrap();
Ok(len)
}
}
#[test]
fn read_adapter_initializes_destination_before_reading() {
let expected = 0x0123_4567_89ab_cdef_u64;
let data = crate::serialize(&expected).unwrap();
let mut reader = InspectingReader::new(data.clone());
let actual: u64 = crate::deserialize_from(ReadAdapter::new(&mut reader)).unwrap();
assert_eq!(actual, expected);
assert_eq!(reader.observed, vec![0; data.len()]);
}
#[test]
fn buf_reader_initializes_destination_before_reading() {
let expected = 0x0123_4567_89ab_cdef_u64;
let data = crate::serialize(&expected).unwrap();
let mut reader = InspectingReader::new(data.clone());
let actual: u64 =
crate::deserialize_from(BufReader::with_capacity(1, &mut reader)).unwrap();
assert_eq!(actual, expected);
assert_eq!(reader.observed, vec![0; data.len()]);
}
}