use std::{fs, path::Path, io, io::prelude::*};
use super::*;
pub fn read<F: Read>(mut file: F, key: &Key) -> io::Result<Vec<Block>> {
let mut header: Header = dataview::zeroed();
file.read_exact(dataview::bytes_mut(&mut header))?;
let header2 = header;
if !crypt::decrypt_header(&mut header, key) {
return Err(io::Error::from(io::ErrorKind::InvalidData));
}
let blocks_len = usize::max(Header::BLOCKS_LEN, header.info.directory.offset as usize + header.info.directory.size as usize * Descriptor::BLOCKS_LEN);
let mut blocks = vec![Block::default(); blocks_len];
blocks[..Header::BLOCKS_LEN].copy_from_slice(header2.as_ref());
file.read_exact(dataview::bytes_mut(&mut blocks[Header::BLOCKS_LEN..]))?;
Ok(blocks)
}
#[inline(always)]
fn read_header(file: &mut fs::File, key: &Key) -> io::Result<(InfoHeader, Directory)> {
let mut header: Header = dataview::zeroed();
file.read_exact(dataview::bytes_mut(&mut header))?;
if !crypt::decrypt_header(&mut header, key) {
Err(io::ErrorKind::InvalidData)?;
}
file.seek(io::SeekFrom::Start(header.info.directory.offset as u64 * BLOCK_SIZE as u64))?;
let mut directory = Directory::from(vec![Descriptor::default(); header.info.directory.size as usize]);
file.read_exact(dataview::bytes_mut(directory.as_mut()))?;
if !crypt::decrypt_section(directory.as_blocks_mut(), &header.info.directory, key) {
Err(io::ErrorKind::InvalidData)?;
}
Ok((header.info, directory))
}
fn read_section(mut file: &fs::File, section: &Section, key: &Key) -> io::Result<Vec<Block>> {
let file_offset = section.offset as u64 * BLOCK_SIZE as u64;
file.seek(io::SeekFrom::Start(file_offset))?;
let mut blocks = vec![Block::default(); section.size as usize];
file.read_exact(dataview::bytes_mut(blocks.as_mut_slice()))?;
if !crypt::decrypt_section(&mut blocks, section, key) {
Err(io::ErrorKind::InvalidData)?;
}
Ok(blocks)
}
fn read_data(file: &fs::File, desc: &Descriptor, key: &Key) -> io::Result<Vec<u8>> {
if !desc.is_file() {
Err(io::ErrorKind::InvalidInput)?;
}
let blocks = read_section(file, &desc.section, key)?;
let data = dataview::bytes(blocks.as_slice());
let len = usize::min(data.len(), desc.content_size as usize);
Ok(data[..len].to_vec())
}
fn read_data_into(file: &fs::File, desc: &Descriptor, key: &Key, byte_offset: usize, dest: &mut [u8]) -> io::Result<()> {
if !desc.is_file() {
Err(io::ErrorKind::InvalidInput)?;
}
let blocks = read_section(file, &desc.section, key)?;
let data = match dataview::bytes(blocks.as_slice()).get(byte_offset..byte_offset + dest.len()) {
Some(data) => data,
None => Err(io::ErrorKind::InvalidInput)?,
};
dest.copy_from_slice(data);
Ok(())
}
mod reader;
mod editor;
mod edit_file;
pub use self::reader::FileReader;
pub use self::editor::FileEditor;
pub use self::edit_file::FileEditFile;
#[cfg(test)]
mod tests;