preserves/implementations/rust/oo/src/source.rs

240 lines
6.5 KiB
Rust

use crate::error::io_eof;
use std::borrow::Cow;
use std::io;
pub trait BinarySource<'de>: Sized {
fn mark(&mut self) -> io::Result<usize>;
fn restore(&mut self, mark: usize) -> io::Result<()>;
fn input_position(&mut self) -> io::Result<Option<usize>>;
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]>>;
//---------------------------------------------------------------------------
#[inline(always)]
fn peek_noeof(&mut self) -> io::Result<u8> {
self.peek()?.ok_or_else(io_eof)
}
#[inline(always)]
fn read(&mut self) -> io::Result<u8> {
let v = self.peek_noeof()?;
self.skip()?;
Ok(v)
}
fn syntax_error(&mut self, message: &str) -> io::Error {
io::Error::new(io::ErrorKind::InvalidData, SyntaxError {
position: match self.input_position() {
Ok(p) => p,
Err(_) => None,
},
message: message.to_owned(),
})
}
fn packed(&mut self) -> super::PackedReader<'de, '_, Self> {
super::PackedReader::new(self)
}
fn text(&mut self) -> super::TextReader<'de, '_, Self> {
super::TextReader::new(self)
}
}
#[derive(Debug)]
pub struct SyntaxError {
position: Option<usize>,
message: String,
}
impl std::fmt::Display for SyntaxError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "position {}: {}",
match self.position {
Some(p) => p.to_string(),
None => "??".to_string(),
},
self.message)
}
}
impl std::error::Error for SyntaxError {}
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> {
#[inline(always)]
fn mark(&mut self) -> io::Result<usize> {
let pos = self.read.stream_position()? - (if self.buf.is_some() { 1 } else { 0 });
Ok(pos as usize)
}
#[inline(always)]
fn restore(&mut self, mark: usize) -> io::Result<()> {
self.read.seek(io::SeekFrom::Start(mark as u64))?;
self.buf = None;
Ok(())
}
fn input_position(&mut self) -> io::Result<Option<usize>> {
Ok(Some(self.mark()? as usize))
}
#[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> {
#[inline(always)]
fn mark(&mut self) -> io::Result<usize> {
Ok(self.index as usize)
}
#[inline(always)]
fn restore(&mut self, mark: usize) -> io::Result<()> {
self.index = mark as u64;
Ok(())
}
fn input_position(&mut self) -> io::Result<Option<usize>> {
Ok(Some(self.index as usize))
}
#[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)
}
}