diff --git a/src/morethantext/databases.rs b/src/morethantext/databases.rs index 6089d18..7c93e56 100644 --- a/src/morethantext/databases.rs +++ b/src/morethantext/databases.rs @@ -1,4 +1,5 @@ -use std::collections::HashMap; +use super::{DBError, FileData}; +use std::{collections::HashMap, slice, str}; #[derive(Clone)] pub struct Databases { @@ -32,6 +33,54 @@ impl Databases { } } +impl FileData for Databases { + fn to_bytes(&self) -> Vec { + let mut output = Vec::new(); + for (name, id) in self.db_map.iter() { + output.append(&mut name.as_bytes().to_vec()); + output.push(0); + output.append(&mut id.as_bytes().to_vec()); + output.push(0); + } + output + } + + fn from_bytes(data: &mut slice::Iter) -> Result { + let mut output = Databases::new(); + let mut name: Vec = Vec::new(); + let mut id: Vec = Vec::new(); + let mut get_id = false; + let mut letter: u8; + loop { + match data.next() { + Some(a) => letter = a.clone(), + None => { + if !name.is_empty() { + return Err(DBError::new("file corruption")); + } + break; + } + } + if letter == 0 { + if get_id { + output + .add_database(str::from_utf8(&name).unwrap(), str::from_utf8(&id).unwrap()); + name.clear(); + id.clear(); + } + get_id = !get_id; + } else { + if get_id { + id.push(letter); + } else { + name.push(letter); + } + } + } + Ok(output) + } +} + #[cfg(test)] mod functions { use super::*; @@ -79,3 +128,65 @@ mod functions { assert_eq!(output, expected); } } + +#[cfg(test)] +mod filedata { + use super::*; + + #[test] + fn to_bytes_new() { + let dbs = Databases::new(); + let expected: Vec = Vec::new(); + let output = dbs.to_bytes(); + assert_eq!(output, expected); + } + + #[test] + fn to_bytes_with_database() { + let mut dbs = Databases::new(); + let name = "something"; + let id = "id"; + dbs.add_database(name, id); + let mut expected: Vec = Vec::new(); + expected.append(&mut name.as_bytes().to_vec()); + expected.push(0); + expected.append(&mut id.as_bytes().to_vec()); + expected.push(0); + let output = dbs.to_bytes(); + assert_eq!(output, expected); + } + + #[test] + fn from_bytes() { + let mut dbs = Databases::new(); + dbs.add_database("one", "1"); + dbs.add_database("two", "2"); + dbs.add_database("three", "3"); + let data = dbs.to_bytes(); + let mut feed = data.iter(); + let output = Databases::from_bytes(&mut feed).unwrap(); + assert_eq!(output.db_map, dbs.db_map); + } + + #[test] + fn from_bytes_incomplete_name() { + let data = "notName".as_bytes(); + let mut feed = data.iter(); + match Databases::from_bytes(&mut feed) { + Ok(_) => assert!(false, "This should have failed."), + Err(err) => assert_eq!(err.to_string(), "file corruption"), + } + } + + #[test] + fn from_bytes_incomplete_id() { + let mut data = "proper".as_bytes().to_vec(); + data.push(0); + data.append(&mut "nope".as_bytes().to_vec()); + let mut feed = data.iter(); + match Databases::from_bytes(&mut feed) { + Ok(_) => assert!(false, "This should have failed."), + Err(err) => assert_eq!(err.to_string(), "file corruption"), + } + } +} diff --git a/src/morethantext/mod.rs b/src/morethantext/mod.rs index 44660f0..f90fb50 100644 --- a/src/morethantext/mod.rs +++ b/src/morethantext/mod.rs @@ -12,13 +12,18 @@ use error::DBError; use rand::{distributions::Alphanumeric, thread_rng, Rng}; use std::{ collections::HashMap, - fmt, str, + fmt, slice, str, time::{Duration, Instant}, }; const DATA: &str = "data"; const ENTRY: &str = "databases"; +trait FileData { + fn to_bytes(&self) -> Vec; + fn from_bytes(data: &mut slice::Iter) -> Result; +} + #[derive(Clone)] pub enum CacheType { Raw(String),