aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2017-12-15 12:08:43 +0100
committerKatharina Fey <kookie@spacekookie.de>2017-12-15 12:08:43 +0100
commit6f09a3e75b8f498d6ef1132c8a5943d3735ef99d (patch)
tree2453184ceaf1756a9daa14929ef1d144c5cc1381
parent382cc1f9ae806271eb45cbc134f227878c7da0b1 (diff)
Expanding record tests. Adding new traits to payload
Diffstat (limited to '')
-rw-r--r--src/record/mod.rs3
-rw-r--r--src/record/version.rs128
-rw-r--r--src/test/mod.rs23
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