use std::{
fs::File,
io::{self, SeekFrom},
ops::Range,
};
mod cache;
pub use cache::LazyCache;
mod slice;
pub use slice::BufReader;
use crate::FILE_BYTES_MAX;
pub trait DataRead {
fn stream_position(&self) -> u64;
#[inline]
fn offset_from_start(&self, pos: SeekFrom) -> u64 {
match pos {
SeekFrom::Start(s) => s,
SeekFrom::Current(p) => {
(self.stream_position() as i128 + p as i128).clamp(0, u64::MAX as i128) as u64
}
SeekFrom::End(e) => {
(self.data_size() as i128 + e as i128).clamp(0, u64::MAX as i128) as u64
}
}
}
fn read_range(&mut self, range: Range<u64>) -> Result<&[u8], io::Error>;
#[inline]
fn read_count(&mut self, count: u64) -> Result<&[u8], io::Error> {
let pos = self.stream_position();
let range = pos..(pos.saturating_add(count));
self.read_range(range)
}
fn read_exact_range(&mut self, range: Range<u64>) -> Result<&[u8], io::Error> {
let range_len = range.end - range.start;
let b = self.read_range(range)?;
if b.len() as u64 != range_len {
Err(io::Error::from(io::ErrorKind::UnexpectedEof))
} else {
Ok(b)
}
}
fn read_exact_count(&mut self, count: u64) -> Result<&[u8], io::Error> {
let b = self.read_count(count)?;
debug_assert!(b.len() <= count as usize);
if b.len() as u64 != count {
Err(io::ErrorKind::UnexpectedEof.into())
} else {
Ok(b)
}
}
fn read_exact_into(&mut self, buf: &mut [u8]) -> Result<(), io::Error> {
let read = self.read_exact_count(buf.len() as u64)?;
buf.copy_from_slice(read);
Ok(())
}
fn read_until_any_delim_or_limit(
&mut self,
delims: &[u8],
limit: u64,
) -> Result<&[u8], io::Error>;
fn read_until_or_limit(&mut self, byte: u8, limit: u64) -> Result<&[u8], io::Error>;
fn read_while_or_limit<F>(&mut self, f: F, limit: u64) -> Result<&[u8], io::Error>
where
F: Fn(u8) -> bool;
fn read_until_utf16_or_limit(
&mut self,
utf16_char: &[u8; 2],
limit: u64,
) -> Result<&[u8], io::Error>;
fn data_size(&self) -> u64;
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64>;
}
pub enum DataReader<'b> {
Slice(BufReader<&'b [u8]>),
Vec(BufReader<Vec<u8>>),
File(LazyCache<File>),
}
impl DataReader<'_> {
pub fn from_file(r: File) -> Result<Self, io::Error> {
let x = LazyCache::<File>::from_read_seek(r)
.and_then(|lc| lc.with_hot_cache(2 * FILE_BYTES_MAX))
.map(|lc| lc.with_warm_cache(100 << 20))?;
Ok(Self::File(x))
}
}
impl<'b> DataReader<'b> {
pub fn from_slice(s: &'b [u8]) -> Self {
Self::Slice(BufReader::from_slice(s))
}
}
impl DataReader<'_> {
pub fn from_vec(v: Vec<u8>) -> Self {
Self::Vec(BufReader::from_slice(v))
}
}
impl DataRead for DataReader<'_> {
fn stream_position(&self) -> u64 {
match self {
DataReader::Slice(b) => b.stream_position(),
DataReader::Vec(v) => v.stream_position(),
DataReader::File(f) => f.stream_position(),
}
}
fn offset_from_start(&self, pos: SeekFrom) -> u64 {
match self {
DataReader::Slice(b) => b.offset_from_start(pos),
DataReader::Vec(v) => v.offset_from_start(pos),
DataReader::File(f) => f.offset_from_start(pos),
}
}
fn read_range(&mut self, range: Range<u64>) -> Result<&[u8], io::Error> {
match self {
DataReader::Slice(b) => b.read_range(range),
DataReader::Vec(v) => v.read_range(range),
DataReader::File(f) => f.read_range(range),
}
}
fn read_count(&mut self, count: u64) -> Result<&[u8], io::Error> {
match self {
DataReader::Slice(b) => b.read_count(count),
DataReader::Vec(v) => v.read_count(count),
DataReader::File(f) => f.read_count(count),
}
}
fn read_exact_range(&mut self, range: Range<u64>) -> Result<&[u8], io::Error> {
match self {
DataReader::Slice(b) => b.read_exact_range(range),
DataReader::Vec(v) => v.read_exact_range(range),
DataReader::File(f) => f.read_exact_range(range),
}
}
fn read_exact_count(&mut self, count: u64) -> Result<&[u8], io::Error> {
match self {
DataReader::Slice(b) => b.read_exact_count(count),
DataReader::Vec(v) => v.read_exact_count(count),
DataReader::File(f) => f.read_exact_count(count),
}
}
fn read_exact_into(&mut self, buf: &mut [u8]) -> Result<(), io::Error> {
match self {
DataReader::Slice(b) => b.read_exact_into(buf),
DataReader::Vec(v) => v.read_exact_into(buf),
DataReader::File(f) => f.read_exact_into(buf),
}
}
fn read_until_any_delim_or_limit(
&mut self,
delims: &[u8],
limit: u64,
) -> Result<&[u8], io::Error> {
match self {
DataReader::Slice(b) => b.read_until_any_delim_or_limit(delims, limit),
DataReader::Vec(v) => v.read_until_any_delim_or_limit(delims, limit),
DataReader::File(f) => f.read_until_any_delim_or_limit(delims, limit),
}
}
fn read_until_or_limit(&mut self, byte: u8, limit: u64) -> Result<&[u8], io::Error> {
match self {
DataReader::Slice(b) => b.read_until_or_limit(byte, limit),
DataReader::Vec(v) => v.read_until_or_limit(byte, limit),
DataReader::File(f) => f.read_until_or_limit(byte, limit),
}
}
fn read_while_or_limit<F>(&mut self, f: F, limit: u64) -> Result<&[u8], io::Error>
where
F: Fn(u8) -> bool,
{
match self {
DataReader::Slice(b) => b.read_while_or_limit(f, limit),
DataReader::Vec(v) => v.read_while_or_limit(f, limit),
DataReader::File(l) => l.read_while_or_limit(f, limit),
}
}
fn read_until_utf16_or_limit(
&mut self,
utf16_char: &[u8; 2],
limit: u64,
) -> Result<&[u8], io::Error> {
match self {
DataReader::Slice(b) => b.read_until_utf16_or_limit(utf16_char, limit),
DataReader::Vec(v) => v.read_until_utf16_or_limit(utf16_char, limit),
DataReader::File(f) => f.read_until_utf16_or_limit(utf16_char, limit),
}
}
fn data_size(&self) -> u64 {
match self {
DataReader::Slice(b) => b.data_size(),
DataReader::Vec(v) => v.data_size(),
DataReader::File(f) => f.data_size(),
}
}
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
match self {
DataReader::Slice(b) => b.seek(pos),
DataReader::Vec(v) => v.seek(pos),
DataReader::File(f) => f.seek(pos),
}
}
}