use std::fs::File;
use std::io::{Error, Result};
use std::os::unix::fs::FileExt;
use crate::Location;
pub struct FileArena {
files: Vec<File>,
}
impl FileArena {
pub fn new(files: Vec<File>) -> Result<Self> {
Ok(Self { files })
}
pub fn get(&self, loc: Location) -> Result<Vec<u8>> {
if loc.len == 0 {
return Ok(Vec::new());
}
let mut buf = vec![0u8; loc.len as usize];
let bytes_read =
self.files[loc.file_index as usize].read_at(&mut buf, loc.offset as u64)?;
if bytes_read != buf.len() {
return Err(Error::other(format!(
"short read: expected {} bytes, got {} at offset {}",
buf.len(),
bytes_read,
loc.offset
)));
}
Ok(buf)
}
pub fn get_into(&self, loc: Location, out: &mut Vec<u8>) -> Result<()> {
if loc.len == 0 {
return Ok(());
}
let len = loc.len as usize;
out.reserve(len);
let start = out.len();
unsafe {
out.set_len(start + len);
}
let bytes_read =
self.files[loc.file_index as usize].read_at(&mut out[start..], loc.offset as u64)?;
if bytes_read != len {
out.truncate(start);
return Err(Error::other(format!(
"short read: expected {} bytes, got {} at offset {}",
len, bytes_read, loc.offset
)));
}
Ok(())
}
pub fn file_count(&self) -> usize {
self.files.len()
}
}