use std::{fs, path::Path};
use super::*;
fn read_section(blocks: &[Block], section: &Section, key: &Key) -> Result<Vec<Block>, ErrorKind> {
let blocks = match blocks.get(section.range_usize()) {
Some(blocks) => blocks,
None => return Err(ErrorKind::InvalidInput),
};
let mut blocks = blocks.to_vec();
if !crypt::decrypt_section(&mut blocks, section, key) {
return Err(ErrorKind::InvalidData);
}
Ok(blocks)
}
fn from_blocks(mut blocks: Vec<Block>, key: &Key) -> Result<(Vec<Block>, Directory), Vec<Block>> {
if blocks.len() < Header::BLOCKS_LEN {
return Err(blocks);
}
let mut header: Header = dataview::DataView::from_mut(blocks.as_mut_slice()).read(0);
if !crypt::decrypt_header(&mut header, key) {
return Err(blocks);
}
let dir_start = header.info.directory.offset as usize;
let dir_end = dir_start + header.info.directory.size as usize * Descriptor::BLOCKS_LEN;
let dir_blocks = match blocks.get_mut(dir_start..dir_end) {
Some(dir_blocks) => dir_blocks,
None => return Err(blocks),
};
crypt::decrypt_section(dir_blocks, &header.info.directory, key);
let dir = unsafe {
slice::from_raw_parts(dir_blocks.as_ptr() as *const Descriptor, header.info.directory.size as usize)
};
let directory = Directory::from(dir.to_vec());
if blocks.len() == dir_end {
blocks.truncate(dir_start);
}
Ok((blocks, directory))
}
fn read_data(blocks: &[Block], desc: &Descriptor, key: &Key) -> Result<Vec<u8>, ErrorKind> {
if !desc.is_file() {
return Err(ErrorKind::InvalidInput);
}
let blocks = read_section(blocks, &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(blocks: &[Block], desc: &Descriptor, key: &Key, byte_offset: usize, dest: &mut [u8]) -> Result<(), ErrorKind> {
if !desc.is_file() {
return Err(ErrorKind::InvalidInput);
}
let blocks = read_section(blocks, &desc.section, key)?;
let data = match dataview::bytes(blocks.as_slice()).get(byte_offset..byte_offset + dest.len()) {
Some(data) => data,
None => return Err(ErrorKind::InvalidInput),
};
dest.copy_from_slice(data);
Ok(())
}
mod reader;
mod editor;
mod edit_file;
mod bundled;
pub use self::reader::*;
pub use self::editor::*;
pub use self::edit_file::*;
pub use self::bundled::*;
#[cfg(test)]
mod tests;