194 lines
5.2 KiB
Rust
194 lines
5.2 KiB
Rust
use crate::error::io_eof;
|
|
|
|
use std::borrow::Cow;
|
|
use std::io;
|
|
|
|
pub trait BinarySource<'de>: Sized {
|
|
type Mark;
|
|
fn mark(&mut self) -> io::Result<Self::Mark>;
|
|
fn restore(&mut self, mark: &Self::Mark) -> io::Result<()>;
|
|
|
|
fn skip(&mut self) -> io::Result<()>;
|
|
fn peek(&mut self) -> io::Result<Option<u8>>;
|
|
fn discard(&mut self, count: u64) -> io::Result<()>;
|
|
fn readbytes(&mut self, count: u64) -> io::Result<Cow<'de, [u8]>>;
|
|
fn readbytes_into(&mut self, bs: &mut [u8]) -> io::Result<()>;
|
|
fn read_to_end(&mut self) -> io::Result<Cow<'de, [u8]>>;
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
fn packed(&mut self) -> super::PackedReader<'de, '_, Self> {
|
|
super::PackedReader::new(self)
|
|
}
|
|
|
|
fn text(&mut self) -> super::TextReader<'de, '_, Self> {
|
|
super::TextReader::new(self)
|
|
}
|
|
}
|
|
|
|
pub struct IOBinarySource<R: io::Read + io::Seek> {
|
|
pub read: R,
|
|
pub buf: Option<u8>,
|
|
}
|
|
|
|
impl<R: io::Read + io::Seek> IOBinarySource<R> {
|
|
#[inline(always)]
|
|
pub fn new(read: R) -> Self {
|
|
IOBinarySource { read, buf: None }
|
|
}
|
|
}
|
|
|
|
impl<'de, R: io::Read + io::Seek> BinarySource<'de> for IOBinarySource<R> {
|
|
type Mark = u64;
|
|
|
|
#[inline(always)]
|
|
fn mark(&mut self) -> io::Result<Self::Mark> {
|
|
Ok(self.read.stream_position()? - (if self.buf.is_some() { 1 } else { 0 }))
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn restore(&mut self, mark: &Self::Mark) -> io::Result<()> {
|
|
self.read.seek(io::SeekFrom::Start(*mark))?;
|
|
self.buf = None;
|
|
Ok(())
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn skip(&mut self) -> io::Result<()> {
|
|
if self.buf.is_none() { unreachable!(); }
|
|
self.buf = None;
|
|
Ok(())
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn peek(&mut self) -> io::Result<Option<u8>> {
|
|
match self.buf {
|
|
Some(b) => Ok(Some(b)),
|
|
None => {
|
|
let b = &mut [0];
|
|
match self.read.read(b)? {
|
|
0 => Ok(None),
|
|
1 => {
|
|
self.buf = Some(b[0]);
|
|
Ok(Some(b[0]))
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn discard(&mut self, mut count: u64) -> io::Result<()> {
|
|
if self.buf.is_some() { unreachable!(); }
|
|
while count > i64::MAX as u64 {
|
|
self.read.seek(io::SeekFrom::Current(i64::MAX))?;
|
|
count -= i64::MAX as u64;
|
|
}
|
|
self.read.seek(io::SeekFrom::Current(count as i64))?;
|
|
Ok(())
|
|
}
|
|
|
|
fn readbytes(&mut self, count: u64) -> io::Result<Cow<'de, [u8]>> {
|
|
let mut bs = vec![0; count as usize];
|
|
self.readbytes_into(&mut bs)?;
|
|
Ok(Cow::Owned(bs))
|
|
}
|
|
|
|
fn readbytes_into(&mut self, bs: &mut [u8]) -> io::Result<()> {
|
|
if self.buf.is_some() { unreachable!(); }
|
|
self.read.read_exact(bs)
|
|
}
|
|
|
|
fn read_to_end(&mut self) -> io::Result<Cow<'de, [u8]>> {
|
|
if self.buf.is_some() { unreachable!(); }
|
|
let mut bs = Vec::new();
|
|
self.read.read_to_end(&mut bs)?;
|
|
Ok(Cow::Owned(bs))
|
|
}
|
|
}
|
|
|
|
pub struct BytesBinarySource<'de> {
|
|
pub bytes: &'de [u8],
|
|
pub index: u64,
|
|
}
|
|
|
|
impl<'de> BytesBinarySource<'de> {
|
|
#[inline(always)]
|
|
pub fn new(bytes: &'de [u8]) -> Self {
|
|
BytesBinarySource { bytes, index: 0 }
|
|
}
|
|
}
|
|
|
|
impl<'de> BinarySource<'de> for BytesBinarySource<'de> {
|
|
type Mark = u64;
|
|
|
|
#[inline(always)]
|
|
fn mark(&mut self) -> io::Result<Self::Mark> {
|
|
Ok(self.index)
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn restore(&mut self, mark: &Self::Mark) -> io::Result<()> {
|
|
self.index = *mark;
|
|
Ok(())
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn skip(&mut self) -> io::Result<()> {
|
|
if self.index as usize >= self.bytes.len() { unreachable!(); }
|
|
self.index += 1;
|
|
Ok(())
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn peek(&mut self) -> io::Result<Option<u8>> {
|
|
if self.index as usize >= self.bytes.len() {
|
|
Ok(None)
|
|
} else {
|
|
Ok(Some(self.bytes[self.index as usize]))
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn discard(&mut self, count: u64) -> io::Result<()> {
|
|
if (self.index + count) as usize > self.bytes.len() {
|
|
Err(io_eof())
|
|
} else {
|
|
self.index += count;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn readbytes(&mut self, count: u64) -> io::Result<Cow<'de, [u8]>> {
|
|
let base = self.index as usize;
|
|
let limit = base + count as usize;
|
|
if limit > self.bytes.len() {
|
|
Err(io_eof())
|
|
} else {
|
|
let bs = &self.bytes[base..limit];
|
|
self.index += count;
|
|
Ok(Cow::Borrowed(bs))
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn readbytes_into(&mut self, bs: &mut [u8]) -> io::Result<()> {
|
|
let base = self.index as usize;
|
|
let count = bs.len();
|
|
let limit = base + count;
|
|
if limit > self.bytes.len() {
|
|
Err(io_eof())
|
|
} else {
|
|
bs.copy_from_slice(&self.bytes[base..limit]);
|
|
self.index += count as u64;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn read_to_end(&mut self) -> io::Result<Cow<'de, [u8]>> {
|
|
self.readbytes(self.bytes.len() as u64 - self.index)
|
|
}
|
|
}
|