use std::fs::File;
use std::io::Read;
use std::path::Path;
#[derive(Debug, Clone, Copy)]
pub(crate) struct ReadBounds {
pub(crate) source_bytes: u64,
pub(crate) total_bytes: u64,
pub(crate) consumed: u64,
}
pub(crate) enum ReadFault {
Unreadable(std::io::Error),
SourceBytes,
TotalBytes,
}
pub(crate) fn bounded(path: &Path, bounds: ReadBounds) -> Result<Vec<u8>, ReadFault> {
let mut bytes = Vec::new();
File::open(path)
.and_then(|file| {
file.take(bounds.source_bytes.saturating_add(1))
.read_to_end(&mut bytes)
})
.map_err(ReadFault::Unreadable)?;
let length = byte_count(&bytes);
match (
length > bounds.source_bytes,
bounds.consumed.saturating_add(length) > bounds.total_bytes,
) {
(true, _) => Err(ReadFault::SourceBytes),
(false, true) => Err(ReadFault::TotalBytes),
(false, false) => Ok(bytes),
}
}
pub(crate) fn byte_count(bytes: &[u8]) -> u64 {
u64::try_from(bytes.len()).unwrap_or(u64::MAX)
}