From 7e699de239699903068f5d238fd91652e2398c98 Mon Sep 17 00:00:00 2001 From: trivernis Date: Fri, 13 Mar 2020 15:13:16 +0100 Subject: [PATCH] Add tests for reading --- Cargo.toml | 2 +- src/chunks.rs | 6 ++++++ src/lib.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ed8ed0f..e9b7128 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bdflib" -version = "0.1.0" +version = "0.1.1" authors = ["trivernis "] edition = "2018" license-file = "LICENSE" diff --git a/src/chunks.rs b/src/chunks.rs index 4bd9e87..d5adaea 100644 --- a/src/chunks.rs +++ b/src/chunks.rs @@ -80,6 +80,7 @@ impl GenericChunk { } let mut entries: Vec = Vec::new(); let mut position = 0; + while self.data.len() > (position + 8) { let entry_length_raw = &self.data[position..position + 4]; position += 4; @@ -90,6 +91,7 @@ impl GenericChunk { let pw_length = BigEndian::read_u32(pw_length_raw); let pw_plain_raw = &self.data[position..position + pw_length as usize]; position += pw_length as usize; + let pw_plain = String::from_utf8(pw_plain_raw.to_vec()) .map_err(|err| { format!( @@ -105,6 +107,7 @@ impl GenericChunk { let entry_id_raw = &self.data[position..position + 4]; position += 4; let entry_id = BigEndian::read_u32(entry_id_raw); + if let Some(hash_entry) = lookup_table.entries.get(&entry_id) { let hash = &self.data[position..position + hash_entry.output_length as usize]; position += hash_entry.output_length as usize; @@ -126,6 +129,7 @@ impl GenericChunk { lookup_table: &HashLookupTable, ) -> GenericChunk { let mut serialized_data: Vec = Vec::new(); + entries.iter().for_each(|entry| { serialized_data.append(&mut entry.serialize(&lookup_table)); }); @@ -158,6 +162,7 @@ impl GenericChunk { let mut decompressed: Vec = Vec::new(); decompressor.read_to_end(&mut decompressed)?; let crc = crc32::checksum_ieee(decompressed.as_slice()); + if crc != self.crc { return Err(Error::new( ErrorKind::InvalidData, @@ -230,6 +235,7 @@ impl MetaChunk { BigEndian::write_u64(&mut total_entries_raw, self.entry_count); serialized_data.append(&mut total_entries_raw.to_vec()); let mut compression_method = self.compression_method.clone(); + if let Some(method) = &mut compression_method { serialized_data.append(&mut method.clone().into_bytes()); } else { diff --git a/src/lib.rs b/src/lib.rs index 30fe66e..c12a4ba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,10 @@ #[cfg(test)] mod tests { use super::io::BDFWriter; - use std::io::{BufWriter, Error}; + use std::io::{BufWriter, Error, BufReader}; use std::fs::File; use crate::chunks::{HashEntry, DataEntry}; + use crate::io::BDFReader; const FOO: &str = "foo"; const BAR: &str = "bar"; @@ -13,16 +14,20 @@ mod tests { let file = File::create("tmp.bdf")?; let f = BufWriter::new(file); let mut writer = BDFWriter::new(f, 2, false); + writer.add_lookup_entry(HashEntry::new(BAR.to_string(), 5))?; writer.add_lookup_entry(HashEntry::new(FOO.to_string(), 4))?; + let mut entry_1 = DataEntry::new("lol".to_string()); entry_1.add_hash_value(FOO.to_string(), vec![0, 1, 0, 2]); entry_1.add_hash_value(BAR.to_string(), vec![0, 2, 3, 4, 5]); writer.add_data_entry(entry_1)?; + let mut entry_2 = DataEntry::new("lel".to_string()); entry_2.add_hash_value(BAR.to_string(), vec![0, 3, 2, 1, 5]); entry_2.add_hash_value(FOO.to_string(), vec![4, 5, 2, 3]); writer.add_data_entry(entry_2)?; + writer.flush()?; writer.flush_writer()?; @@ -34,16 +39,66 @@ mod tests { let file = File::create("tmp-compressed.bdf")?; let f = BufWriter::new(file); let mut writer = BDFWriter::new(f, 2, true); + writer.add_lookup_entry(HashEntry::new(FOO.to_string(), 4))?; writer.add_lookup_entry(HashEntry::new(BAR.to_string(), 5))?; + let mut entry_1 = DataEntry::new("lol".to_string()); entry_1.add_hash_value(FOO.to_string(), vec![2, 4, 0, 2]); entry_1.add_hash_value(BAR.to_string(), vec![5, 2, 1, 4, 5]); writer.add_data_entry(entry_1)?; + let mut entry_2 = DataEntry::new("lel".to_string()); entry_2.add_hash_value(BAR.to_string(), vec![0, 3, 2, 1, 5]); entry_2.add_hash_value(FOO.to_string(), vec![4, 5, 2, 3]); writer.add_data_entry(entry_2)?; + + writer.flush()?; + writer.flush_writer()?; + + Ok(()) + } + + #[test] + fn it_reads() -> Result<(), Error> { + create_simple_file(false)?; + let file = File::open("tmp2.bdf")?; + let f = BufReader::new(file); + let mut reader = BDFReader::new(f); + reader.read_metadata()?; + let lookup_table = &reader.read_lookup_table()?.clone(); + let mut next_chunk = reader.next_chunk()?; + let data_entries = next_chunk.data_entries(lookup_table)?; + assert_eq!(data_entries[0].plain, "lol".to_string()); + + Ok(()) + } + + #[test] + fn it_reads_compressed() -> Result<(), Error> { + create_simple_file(true)?; + let file = File::open("tmp2.bdf")?; + let f = BufReader::new(file); + let mut reader = BDFReader::new(f); + reader.read_metadata()?; + let lookup_table = &reader.read_lookup_table()?.clone(); + let mut next_chunk = reader.next_chunk()?; + let data_entries = next_chunk.data_entries(lookup_table)?; + assert_eq!(data_entries[0].plain, "lol".to_string()); + + Ok(()) + } + + fn create_simple_file(compressed: bool) -> Result<(), Error>{ + let file = File::create("tmp2.bdf")?; + let f = BufWriter::new(file); + let mut writer = BDFWriter::new(f, 1, compressed); + + writer.add_lookup_entry(HashEntry::new(FOO.to_string(), 4))?; + let mut entry_1 = DataEntry::new("lol".to_string()); + entry_1.add_hash_value(FOO.to_string(), vec![2, 4, 0, 2]); + writer.add_data_entry(entry_1)?; + writer.flush()?; writer.flush_writer()?;