use super::DBError; use std::{collections::HashMap, fmt, str}; #[derive(Clone)] pub enum CacheType { Raw(String), Record(Record), } #[derive(Clone)] pub struct Record { data: HashMap, } impl Record { fn new() -> Self { Self { data: HashMap::new(), } } fn add_field(&mut self, col: &str, data: &str) -> Result<(), DBError> { match self.data.get(col) { Some(_) => Err(DBError::new("duplicate field")), None => { self.data.insert(col.to_string(), data.to_string()); Ok(()) } } } fn get_field(&self, col: &str) -> Result { match self.data.get(col) { Some(item) => Ok(item.to_string()), None => Err(DBError::new("missing field")), } } } impl CacheType { fn entry_type(&self) -> String { match self { CacheType::Raw(_) => "Raw".to_string(), CacheType::Record(_) => "Record".to_string(), } } pub fn to_bytes(&self) -> Vec { let mut output = self.entry_type().into_bytes(); output.push(0); match self { CacheType::Raw(s) => output.append(&mut s.as_bytes().to_vec()), CacheType::Record(_) => todo!(), } return output; } pub fn from_bytes(data: Vec) -> CacheType { let mut data_iter = data.iter(); let mut holder: u8 = *data_iter.next().unwrap(); while holder != 0 { holder = *data_iter.next().unwrap(); } let mut output: Vec = Vec::new(); for letter in data_iter { output.push(letter.clone()); } CacheType::Raw(str::from_utf8(&output).unwrap().to_string()) } } impl fmt::Display for CacheType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { CacheType::Raw(s) => write!(f, "{}", s), CacheType::Record(_) => todo!(), } } } #[cfg(test)] mod raw { use super::*; #[test] fn get_bytes() { let data = "addams"; let holder = CacheType::Raw(data.to_string()); let mut expected = holder.entry_type().into_bytes(); expected.push(0); expected.append(&mut data.as_bytes().to_vec()); let output = holder.to_bytes(); assert_eq!(output, expected); } #[test] fn from_bytes() { let holder = CacheType::Raw("stored item".to_string()); let data = holder.to_bytes(); let output = CacheType::from_bytes(data); assert_eq!(output.to_string(), holder.to_string()); } } #[cfg(test)] mod enum_ctype { use super::*; #[test] fn get_raw_type() { let holder = CacheType::Raw("nothing important".to_string()); assert_eq!(holder.entry_type(), "Raw"); } #[test] fn get_record_type() { let rec = Record::new(); let holder = CacheType::Record(rec); assert_eq!(holder.entry_type(), "Record"); } } #[cfg(test)] mod record { use super::*; #[test] fn store() { let data = "data"; let mut rec = Record::new(); rec.add_field("column", data).unwrap(); let output = rec.get_field("column").unwrap(); assert_eq!(output, data); } #[test] fn no_duplicate_fields() { let mut rec = Record::new(); rec.add_field("dup", "datai1").unwrap(); match rec.add_field("dup", "datai2") { Ok(_) => assert!(false, "Should have raised an error."), Err(err) => { assert_eq!(err.to_string(), "duplicate field"); } } } #[test] fn missing_field() { let rec = Record::new(); match rec.get_field("nothing") { Ok(_) => assert!(false, "Should have errored."), Err(err) => assert_eq!(err.to_string(), "missing field"), } } }