diff --git a/src/data/record.rs b/src/data/record.rs index 62da269..6c51a8f 100644 --- a/src/data/record.rs +++ b/src/data/record.rs @@ -25,8 +25,18 @@ pub struct Record { } impl Record { - pub fn new(data: HashMap) -> Self { - Self { data: data } + pub fn new() -> Self { + Self { + data: HashMap::new(), + } + } + + pub fn add(&mut self, name: S, data: D) -> Option + where + String: From, + Field: From, + { + self.data.insert(name.into(), data.into()) } } @@ -56,21 +66,49 @@ mod records { #[test] fn new_record() { - let data: HashMap = HashMap::new(); - let rec = Record::new(data); + let rec = Record::new(); assert_eq!(rec.len(), 0); } + #[test] + fn add_field() { + let mut rec = Record::new(); + let name = "field_name"; + let data = ID::random(); + rec.add(name.to_string(), data); + match rec.get(name) { + Some(data) => match data { + Field::ID(result) => assert_eq!(result.to_string(), data.to_string()), + }, + None => unreachable!("Should get data back"), + } + } + + #[test] + fn add_alternate_field() { + let mut rec = Record::new(); + let name = "alternate"; + let data = ID::random(); + rec.add(name, data.clone()); + match rec.get(name) { + Some(data) => match data { + Field::ID(result) => assert_eq!(result.to_string(), data.to_string()), + }, + None => unreachable!("Should get data back"), + } + } + #[test] fn record_iter() { - let a = Field::from(ID::random()); - let b = Field::from(ID::random()); - let c = Field::from(ID::random()); - let mut data: HashMap = HashMap::new(); - data.insert("a".to_string(), a.clone()); - data.insert("b".to_string(), b.clone()); - data.insert("c".to_string(), c.clone()); - let rec = Record::new(data.clone()); + let mut data: HashMap = HashMap::new(); + data.insert("a".to_string(), ID::random()); + data.insert("b".to_string(), ID::random()); + data.insert("c".to_string(), ID::random()); + let mut rec = Record::new(); + for (key, value) in data.iter() { + rec.add(key, value.clone()); + } + assert_eq!(rec.len(), data.len()); for (key, value) in rec.iter() { assert_eq!(value.to_string(), data.get(key).unwrap().to_string()); } diff --git a/src/data/table.rs b/src/data/table.rs index df318ef..d899693 100644 --- a/src/data/table.rs +++ b/src/data/table.rs @@ -11,6 +11,7 @@ use std::{collections::HashMap, fmt}; pub enum TBLError { DuplicateField(String), InvalidField(String), + MissingField(String), } impl fmt::Display for TBLError { @@ -18,6 +19,7 @@ impl fmt::Display for TBLError { match self { TBLError::DuplicateField(data) => write!(f, "'{}' already exists", data), TBLError::InvalidField(data) => write!(f, "'{}' invalid field name", data), + TBLError::MissingField(data) => write!(f, "'{}' field is missing", data), } } } @@ -39,6 +41,13 @@ mod errors { let err = TBLError::InvalidField(data.to_string()); assert_eq!(err.to_string(), format!("'{}' invalid field name", data)); } + + #[test] + fn missing_field() { + let data = "something"; + let err = TBLError::MissingField(data.to_string()); + assert_eq!(err.to_string(), format!("'{}' field is missing", data)); + } } enum FieldType { @@ -86,15 +95,22 @@ impl Table { } fn add_record(&mut self, rec: Record) -> Result { - for (key, _) in rec.iter() { - match self.fields.get(key) { + let mut holder = rec.clone(); + for (key, _) in self.fields.iter() { + match holder.remove(key.into()) { Some(_) => {} None => { - let err = TBLError::InvalidField(key.to_string()); + let err = TBLError::MissingField(key.to_string()); return Err(err.into()); } } } + if holder.len() > 0 { + for (key, _) in holder.iter() { + let err = TBLError::InvalidField(key.to_string()); + return Err(err.into()); + } + } Ok(rec) } } @@ -134,10 +150,10 @@ mod table { match tbl.add_field(name, FieldType::ID) { Ok(_) => unreachable!(" Should not duplicates."), Err(err) => match err.get_code() { - ErrorType::TBLErr(data) => {match data { + ErrorType::TBLErr(data) => match data { TBLError::DuplicateField(fname) => assert_eq!(fname, name), _ => unreachable!("Should have been a dupluicate field error"), - }} + }, _ => unreachable!("should produce a duplicate name error"), }, } @@ -149,9 +165,8 @@ mod table { let name = "id"; let field_data = ID::random(); tbl.add_field(name, FieldType::ID).unwrap(); - let mut data: HashMap = HashMap::new(); - data.insert(name.to_string(), field_data.clone().into()); - let rec = Record::new(data); + let mut rec = Record::new(); + rec.add(name, field_data.clone()); let result = tbl.add_record(rec).unwrap(); assert_eq!( result.get(name).unwrap().to_string(), @@ -164,9 +179,8 @@ mod table { let mut tbl = Table::new(); let name = "id"; let field_data = ID::random(); - let mut data: HashMap = HashMap::new(); - data.insert(name.to_string(), field_data.clone().into()); - let rec = Record::new(data); + let mut rec = Record::new(); + rec.add(name, field_data.clone()); match tbl.add_record(rec) { Ok(_) => unreachable!("should have produced an error"), Err(err) => match err.get_code() { @@ -175,7 +189,28 @@ mod table { _ => unreachable!("should have been invalid field name"), }, _ => unreachable!("should have been a table error"), - } + }, + } + } + + #[test] + fn add_record_missing_field() { + let mut tbl = Table::new(); + let present = "here"; + let missing = "not"; + tbl.add_field(present, FieldType::ID); + tbl.add_field(missing, FieldType::ID); + let mut rec = Record::new(); + rec.add(present, ID::random()); + match tbl.add_record(rec) { + Ok(_) => unreachable!("should have produced an error"), + Err(err) => match err.get_code() { + ErrorType::TBLErr(error) => match error { + TBLError::MissingField(result) => assert_eq!(result, missing), + _ => unreachable!("should have been missing field"), + }, + _ => unreachable!("should have been a table error"), + }, } } } diff --git a/src/error.rs b/src/error.rs index b1642e2..1d6fdfe 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,4 @@ -use crate::data::{id::IDError, DBError, table::TBLError}; +use crate::data::{id::IDError, table::TBLError, DBError}; use std::{error::Error, fmt}; #[derive(Debug)] @@ -109,7 +109,6 @@ impl From for MTTError { } } - #[cfg(test)] mod errors { use super::*;