diff options
author | Katharina Fey <kookie@spacekookie.de> | 2017-12-15 12:08:43 +0100 |
---|---|---|
committer | Katharina Fey <kookie@spacekookie.de> | 2017-12-15 12:08:43 +0100 |
commit | 6f09a3e75b8f498d6ef1132c8a5943d3735ef99d (patch) | |
tree | 2453184ceaf1756a9daa14929ef1d144c5cc1381 | |
parent | 382cc1f9ae806271eb45cbc134f227878c7da0b1 (diff) |
Expanding record tests. Adding new traits to payload
Diffstat (limited to '')
-rw-r--r-- | src/record/mod.rs | 3 | ||||
-rw-r--r-- | src/record/version.rs | 128 | ||||
-rw-r--r-- | src/test/mod.rs | 23 |
3 files changed, 147 insertions, 7 deletions
diff --git a/src/record/mod.rs b/src/record/mod.rs index a46a9ae..a7029ac 100644 --- a/src/record/mod.rs +++ b/src/record/mod.rs @@ -3,13 +3,14 @@ //! A record is a set of key-value store values with a header //! +pub mod version; use std::collections::BTreeMap; use chrono::{Local, DateTime}; /// A generic payload for a record -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)] pub enum Payload { Text(String), Boolean(bool), diff --git a/src/record/version.rs b/src/record/version.rs index 7b563d6..5c3c77a 100644 --- a/src/record/version.rs +++ b/src/record/version.rs @@ -1,10 +1,130 @@ //! A version of a record -//! +//! //! A set of version can be flattened to represent the latest set //! of changes of a record +use super::Payload; +use std::collections::BTreeMap; +use std::ops; -#[derive(Debug, Serialise, Deserialse)] +/// An operation that was applied to a version +/// +/// An operation is either an insert or a delete. +/// It also carries a string key and a payload value inside +/// a tuple. These are then summed together as a vector. +/// +/// This means that if data contradicts itself in the same +/// version the later edit (call) will override the previous +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +pub enum Operation { + Insert(String, Payload), + Delete(String), +} + +use self::Operation::{Insert, Delete}; + +/// Represents a series of operations done in sequence +/// that are applied to a record to preserve history of state +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct Version { - -}
\ No newline at end of file + version: u64, + ops: Vec<Operation>, +} + +impl Version { + /// Create a simple new version + pub fn new(ver: u64) -> Version { + return Version { + version: ver, + ops: Vec::new(), + }; + } + + /// A simple utility to add an INSERT operation + /// + /// Checks if the same operation already exists + pub fn insert(&mut self, key: &str, val: Payload) { + let i = Insert(String::from(key), val); + if self.ops.contains(&i) { + return; + } + + self.ops.push(i); + } + + /// A simple utility to add a DELETE operation + /// + /// Checks if the same operation already exists. Also checks + /// if an insert operation for the same key already exists, + /// removing it from the vector if it does. + pub fn delete(&mut self, key: &str) { + let d = Delete(String::from(key)); + + /* Search for the insert key */ + let mut inserted = false; + let mut ctr = 0; + for op in &self.ops { + match op { + &Insert(ref k, _) => { + if key == k { + inserted = true; + break; + } + } + _ => {} + } + + ctr += 1; + } + + /* Remove the insert then */ + if inserted { + self.ops.remove(ctr); + return; + } + + /* Search for existing deletion */ + if self.ops.contains(&d) { + return; + } + + /* It's safe to insert! */ + self.ops.push(d); + } + + /// Take a version full of operations and flatten it to a single + /// binary search tree that can be included into an embedded record + /// + /// Non-mutable on the version itself + pub fn flatten(&self) -> BTreeMap<String, Payload> { + let mut map = BTreeMap::new(); + + /* For all operations, process them in order */ + for op in &self.ops { + + /* Match the operation */ + match op { + &Insert(ref key, ref payload) => { + map.insert(key.clone(), payload.clone()); + } + &Delete(ref key) => { + map.remove(key); + } + } + } + + /* Return the map */ + return map; + } + + /// A utility function which merges two versions onto &self + /// + /// - If a key is present in `other`, `self.key` is overwritten + /// - If a key is missing in `other`, `self.key` is deleted + /// + pub fn merge(&mut self, other: &Version) { + for op in &other.ops { + self.ops.push(op.clone()); + } + } +} diff --git a/src/test/mod.rs b/src/test/mod.rs index 2f6b986..30a7eae 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -5,14 +5,33 @@ //! #![allow(unused)] -use record::Record; +use record::{Record, Payload}; use serde_json; #[test] -fn serialise_deserialise() { +fn serialise_record_simple() { let r = Record::new("name", "category"); let serial = serde_json::to_string(&r).unwrap(); let deserial: Record = serde_json::from_str(&serial).unwrap(); assert_eq!(r, deserial); +} + + +#[test] +fn serialise_record_data() { + let mut r = Record::new("name", "category"); + r.add_tag("tag"); + r.set_data("username", Payload::Text("jane".to_owned())); + r.set_data("password", Payload::Text("car battery horse staple".to_owned())); + + let serial = serde_json::to_string(&r).unwrap(); + let deserial: Record = serde_json::from_str(&serial).unwrap(); + + assert_eq!(r, deserial); +} + +#[test] +fn serialise_version() { + // let v = Version::new(); }
\ No newline at end of file |