|
|
@ -1,8 +1,8 @@
|
|
|
|
use byteorder::{BigEndian, ByteOrder};
|
|
|
|
use byteorder::{BigEndian, ByteOrder};
|
|
|
|
use crc::crc32;
|
|
|
|
use crc::crc32;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::convert::{TryFrom};
|
|
|
|
use std::convert::TryFrom;
|
|
|
|
use std::io::{Read};
|
|
|
|
use std::io::Read;
|
|
|
|
use std::io::{Error, ErrorKind};
|
|
|
|
use std::io::{Error, ErrorKind};
|
|
|
|
use xz2::read::{XzDecoder, XzEncoder};
|
|
|
|
use xz2::read::{XzDecoder, XzEncoder};
|
|
|
|
|
|
|
|
|
|
|
@ -14,7 +14,7 @@ pub const META_CHUNK_NAME: &str = "META";
|
|
|
|
pub const HTBL_CHUNK_NAME: &str = "HTBL";
|
|
|
|
pub const HTBL_CHUNK_NAME: &str = "HTBL";
|
|
|
|
pub const DTBL_CHUNK_NAME: &str = "DTBL";
|
|
|
|
pub const DTBL_CHUNK_NAME: &str = "DTBL";
|
|
|
|
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct GenericChunk {
|
|
|
|
pub struct GenericChunk {
|
|
|
|
pub length: u32,
|
|
|
|
pub length: u32,
|
|
|
@ -23,7 +23,7 @@ pub struct GenericChunk {
|
|
|
|
pub crc: u32,
|
|
|
|
pub crc: u32,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct MetaChunk {
|
|
|
|
pub struct MetaChunk {
|
|
|
|
pub chunk_count: u32,
|
|
|
|
pub chunk_count: u32,
|
|
|
@ -32,13 +32,13 @@ pub struct MetaChunk {
|
|
|
|
pub compression_method: Option<String>,
|
|
|
|
pub compression_method: Option<String>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct HashLookupTable {
|
|
|
|
pub struct HashLookupTable {
|
|
|
|
pub entries: HashMap<u32, HashEntry>,
|
|
|
|
pub entries: HashMap<u32, HashEntry>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct HashEntry {
|
|
|
|
pub struct HashEntry {
|
|
|
|
pub(crate) id: u32,
|
|
|
|
pub(crate) id: u32,
|
|
|
@ -46,7 +46,7 @@ pub struct HashEntry {
|
|
|
|
name: String,
|
|
|
|
name: String,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct DataEntry {
|
|
|
|
pub struct DataEntry {
|
|
|
|
pub plain: String,
|
|
|
|
pub plain: String,
|
|
|
@ -55,8 +55,7 @@ pub struct DataEntry {
|
|
|
|
|
|
|
|
|
|
|
|
impl GenericChunk {
|
|
|
|
impl GenericChunk {
|
|
|
|
/// Serializes the chunk to a vector of bytes
|
|
|
|
/// Serializes the chunk to a vector of bytes
|
|
|
|
#[no_mangle]
|
|
|
|
pub fn serialize(&mut self) -> Vec<u8> {
|
|
|
|
pub extern fn serialize(&mut self) -> Vec<u8> {
|
|
|
|
|
|
|
|
let mut serialized: Vec<u8> = Vec::new();
|
|
|
|
let mut serialized: Vec<u8> = Vec::new();
|
|
|
|
let mut length_raw = [0u8; 4];
|
|
|
|
let mut length_raw = [0u8; 4];
|
|
|
|
BigEndian::write_u32(&mut length_raw, self.length);
|
|
|
|
BigEndian::write_u32(&mut length_raw, self.length);
|
|
|
@ -72,8 +71,7 @@ impl GenericChunk {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Returns the data entries of the chunk
|
|
|
|
/// Returns the data entries of the chunk
|
|
|
|
#[no_mangle]
|
|
|
|
pub fn data_entries(
|
|
|
|
pub extern fn data_entries(
|
|
|
|
|
|
|
|
&mut self,
|
|
|
|
&mut self,
|
|
|
|
lookup_table: &HashLookupTable,
|
|
|
|
lookup_table: &HashLookupTable,
|
|
|
|
) -> Result<Vec<DataEntry>, Error> {
|
|
|
|
) -> Result<Vec<DataEntry>, Error> {
|
|
|
@ -123,8 +121,7 @@ impl GenericChunk {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Constructs the chunk from a Vec of Data entries and a hash lookup table
|
|
|
|
/// Constructs the chunk from a Vec of Data entries and a hash lookup table
|
|
|
|
#[no_mangle]
|
|
|
|
pub fn from_data_entries(
|
|
|
|
pub extern fn from_data_entries(
|
|
|
|
|
|
|
|
entries: &Vec<DataEntry>,
|
|
|
|
entries: &Vec<DataEntry>,
|
|
|
|
lookup_table: &HashLookupTable,
|
|
|
|
lookup_table: &HashLookupTable,
|
|
|
|
) -> GenericChunk {
|
|
|
|
) -> GenericChunk {
|
|
|
@ -142,8 +139,8 @@ impl GenericChunk {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
/// Compresses the data of the chunk using lzma with a level of 6
|
|
|
|
pub extern fn compress(&mut self) -> Result<(), Error> {
|
|
|
|
pub fn compress(&mut self) -> Result<(), Error> {
|
|
|
|
let data = self.data.as_slice();
|
|
|
|
let data = self.data.as_slice();
|
|
|
|
let mut compressor = XzEncoder::new(data, 6);
|
|
|
|
let mut compressor = XzEncoder::new(data, 6);
|
|
|
|
let mut compressed: Vec<u8> = Vec::new();
|
|
|
|
let mut compressed: Vec<u8> = Vec::new();
|
|
|
@ -154,8 +151,8 @@ impl GenericChunk {
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
/// Decompresses the data of the chunk with lzma
|
|
|
|
pub extern fn decompress(&mut self) -> Result<(), Error> {
|
|
|
|
pub fn decompress(&mut self) -> Result<(), Error> {
|
|
|
|
let data = self.data.as_slice();
|
|
|
|
let data = self.data.as_slice();
|
|
|
|
let mut decompressor = XzDecoder::new(data);
|
|
|
|
let mut decompressor = XzDecoder::new(data);
|
|
|
|
let mut decompressed: Vec<u8> = Vec::new();
|
|
|
|
let mut decompressed: Vec<u8> = Vec::new();
|
|
|
@ -204,8 +201,7 @@ impl From<&HashLookupTable> for GenericChunk {
|
|
|
|
|
|
|
|
|
|
|
|
impl MetaChunk {
|
|
|
|
impl MetaChunk {
|
|
|
|
/// Creates a new meta chunk
|
|
|
|
/// Creates a new meta chunk
|
|
|
|
#[no_mangle]
|
|
|
|
pub fn new(entry_count: u64, entries_per_chunk: u32, compress: bool) -> Self {
|
|
|
|
pub extern fn new(entry_count: u64, entries_per_chunk: u32, compress: bool) -> Self {
|
|
|
|
|
|
|
|
let compression_method = if compress {
|
|
|
|
let compression_method = if compress {
|
|
|
|
Some(LZMA.to_string())
|
|
|
|
Some(LZMA.to_string())
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -222,8 +218,7 @@ impl MetaChunk {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Serializes the chunk into bytes
|
|
|
|
/// Serializes the chunk into bytes
|
|
|
|
#[no_mangle]
|
|
|
|
pub fn serialize(&self) -> Vec<u8> {
|
|
|
|
pub extern fn serialize(&self) -> Vec<u8> {
|
|
|
|
|
|
|
|
let mut serialized_data: Vec<u8> = Vec::new();
|
|
|
|
let mut serialized_data: Vec<u8> = Vec::new();
|
|
|
|
let mut chunk_count_raw = [0u8; 4];
|
|
|
|
let mut chunk_count_raw = [0u8; 4];
|
|
|
|
BigEndian::write_u32(&mut chunk_count_raw, self.chunk_count);
|
|
|
|
BigEndian::write_u32(&mut chunk_count_raw, self.chunk_count);
|
|
|
@ -248,7 +243,6 @@ impl MetaChunk {
|
|
|
|
impl TryFrom<GenericChunk> for MetaChunk {
|
|
|
|
impl TryFrom<GenericChunk> for MetaChunk {
|
|
|
|
type Error = Error;
|
|
|
|
type Error = Error;
|
|
|
|
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
|
|
|
fn try_from(chunk: GenericChunk) -> Result<MetaChunk, Error> {
|
|
|
|
fn try_from(chunk: GenericChunk) -> Result<MetaChunk, Error> {
|
|
|
|
if &chunk.name != META_CHUNK_NAME {
|
|
|
|
if &chunk.name != META_CHUNK_NAME {
|
|
|
|
return Err(Error::new(
|
|
|
|
return Err(Error::new(
|
|
|
@ -285,20 +279,19 @@ impl TryFrom<GenericChunk> for MetaChunk {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl HashLookupTable {
|
|
|
|
impl HashLookupTable {
|
|
|
|
#[no_mangle]
|
|
|
|
|
|
|
|
pub extern fn new(entries: HashMap<u32, HashEntry>) -> Self {
|
|
|
|
/// Creates a new hash lookup table
|
|
|
|
|
|
|
|
pub fn new(entries: HashMap<u32, HashEntry>) -> Self {
|
|
|
|
Self { entries }
|
|
|
|
Self { entries }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Returns an entry by the name of the hash function
|
|
|
|
/// Returns an entry by the name of the hash function
|
|
|
|
#[no_mangle]
|
|
|
|
pub fn get_entry(&self, name: &String) -> Option<(&u32, &HashEntry)> {
|
|
|
|
pub extern fn get_entry(&self, name: &String) -> Option<(&u32, &HashEntry)> {
|
|
|
|
|
|
|
|
self.entries.iter().find(|(_, entry)| entry.name == *name)
|
|
|
|
self.entries.iter().find(|(_, entry)| entry.name == *name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Serializes the lookup table into a vector of bytes
|
|
|
|
/// Serializes the lookup table into a vector of bytes
|
|
|
|
#[no_mangle]
|
|
|
|
pub fn serialize(&self) -> Vec<u8> {
|
|
|
|
pub extern fn serialize(&self) -> Vec<u8> {
|
|
|
|
|
|
|
|
let mut serialized_full: Vec<u8> = Vec::new();
|
|
|
|
let mut serialized_full: Vec<u8> = Vec::new();
|
|
|
|
for (_, entry) in &self.entries {
|
|
|
|
for (_, entry) in &self.entries {
|
|
|
|
serialized_full.append(entry.serialize().as_mut())
|
|
|
|
serialized_full.append(entry.serialize().as_mut())
|
|
|
@ -311,7 +304,6 @@ impl HashLookupTable {
|
|
|
|
impl TryFrom<GenericChunk> for HashLookupTable {
|
|
|
|
impl TryFrom<GenericChunk> for HashLookupTable {
|
|
|
|
type Error = Error;
|
|
|
|
type Error = Error;
|
|
|
|
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
|
|
|
fn try_from(chunk: GenericChunk) -> Result<HashLookupTable, Error> {
|
|
|
|
fn try_from(chunk: GenericChunk) -> Result<HashLookupTable, Error> {
|
|
|
|
if &chunk.name != HTBL_CHUNK_NAME {
|
|
|
|
if &chunk.name != HTBL_CHUNK_NAME {
|
|
|
|
return Err(Error::new(
|
|
|
|
return Err(Error::new(
|
|
|
@ -350,8 +342,9 @@ impl TryFrom<GenericChunk> for HashLookupTable {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl HashEntry {
|
|
|
|
impl HashEntry {
|
|
|
|
#[no_mangle]
|
|
|
|
|
|
|
|
pub extern fn new(name: String, output_length: u32) -> Self {
|
|
|
|
/// Creates a new hash entry
|
|
|
|
|
|
|
|
pub fn new(name: String, output_length: u32) -> Self {
|
|
|
|
Self {
|
|
|
|
Self {
|
|
|
|
id: 0,
|
|
|
|
id: 0,
|
|
|
|
name,
|
|
|
|
name,
|
|
|
@ -360,8 +353,7 @@ impl HashEntry {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Serializes the entry to a vector of bytes
|
|
|
|
/// Serializes the entry to a vector of bytes
|
|
|
|
#[no_mangle]
|
|
|
|
pub fn serialize(&self) -> Vec<u8> {
|
|
|
|
pub extern fn serialize(&self) -> Vec<u8> {
|
|
|
|
|
|
|
|
let mut serialized: Vec<u8> = Vec::new();
|
|
|
|
let mut serialized: Vec<u8> = Vec::new();
|
|
|
|
let mut id_raw = [0u8; 4];
|
|
|
|
let mut id_raw = [0u8; 4];
|
|
|
|
BigEndian::write_u32(&mut id_raw, self.id);
|
|
|
|
BigEndian::write_u32(&mut id_raw, self.id);
|
|
|
@ -380,8 +372,7 @@ impl HashEntry {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl DataEntry {
|
|
|
|
impl DataEntry {
|
|
|
|
#[no_mangle]
|
|
|
|
pub fn new(plain: String) -> Self {
|
|
|
|
pub extern fn new(plain: String) -> Self {
|
|
|
|
|
|
|
|
Self {
|
|
|
|
Self {
|
|
|
|
hashes: HashMap::new(),
|
|
|
|
hashes: HashMap::new(),
|
|
|
|
plain,
|
|
|
|
plain,
|
|
|
@ -389,20 +380,17 @@ impl DataEntry {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Adds a hash to the hash values
|
|
|
|
/// Adds a hash to the hash values
|
|
|
|
#[no_mangle]
|
|
|
|
pub fn add_hash_value(&mut self, name: String, value: Vec<u8>) {
|
|
|
|
pub extern fn add_hash_value(&mut self, name: String, value: Vec<u8>) {
|
|
|
|
|
|
|
|
self.hashes.insert(name, value);
|
|
|
|
self.hashes.insert(name, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Returns the hash value for a given name of a hash function
|
|
|
|
/// Returns the hash value for a given name of a hash function
|
|
|
|
#[no_mangle]
|
|
|
|
pub fn get_hash_value(&self, name: String) -> Option<&Vec<u8>> {
|
|
|
|
pub extern fn get_hash_value(&self, name: String) -> Option<&Vec<u8>> {
|
|
|
|
|
|
|
|
self.hashes.get(&name)
|
|
|
|
self.hashes.get(&name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Serializes the entry to a vector of bytes
|
|
|
|
/// Serializes the entry to a vector of bytes
|
|
|
|
#[no_mangle]
|
|
|
|
pub fn serialize(&self, lookup_table: &HashLookupTable) -> Vec<u8> {
|
|
|
|
pub extern fn serialize(&self, lookup_table: &HashLookupTable) -> Vec<u8> {
|
|
|
|
|
|
|
|
let mut pw_plain_raw = self.plain.clone().into_bytes();
|
|
|
|
let mut pw_plain_raw = self.plain.clone().into_bytes();
|
|
|
|
let mut pw_length_raw = [0u8; 4];
|
|
|
|
let mut pw_length_raw = [0u8; 4];
|
|
|
|
BigEndian::write_u32(&mut pw_length_raw, pw_plain_raw.len() as u32);
|
|
|
|
BigEndian::write_u32(&mut pw_length_raw, pw_plain_raw.len() as u32);
|
|
|
|