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; fn restore(&mut self, mark: &Self::Mark) -> io::Result<()>; fn input_position(&mut self) -> io::Result>; fn skip(&mut self) -> io::Result<()>; fn peek(&mut self) -> io::Result>; fn discard(&mut self, count: u64) -> io::Result<()>; fn readbytes(&mut self, count: u64) -> io::Result>; fn readbytes_into(&mut self, bs: &mut [u8]) -> io::Result<()>; fn read_to_end(&mut self) -> io::Result>; //--------------------------------------------------------------------------- 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, 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 { pub read: R, pub buf: Option, } impl IOBinarySource { #[inline(always)] pub fn new(read: R) -> Self { IOBinarySource { read, buf: None } } } impl<'de, R: io::Read + io::Seek> BinarySource<'de> for IOBinarySource { type Mark = u64; #[inline(always)] fn mark(&mut self) -> io::Result { 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(()) } fn input_position(&mut self) -> io::Result> { 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> { 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> { 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> { 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 { Ok(self.index) } #[inline(always)] fn restore(&mut self, mark: &Self::Mark) -> io::Result<()> { self.index = *mark; Ok(()) } fn input_position(&mut self) -> io::Result> { 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> { 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> { 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> { self.readbytes(self.bytes.len() as u64 - self.index) } }