From 53e0ec865fb9a0fc4bd4eda2569d7d5f100207ea Mon Sep 17 00:00:00 2001 From: Jacob VanDomelen Date: Tue, 12 Jan 2021 13:42:35 -0800 Subject: [PATCH] Using serde for serializing --- .gitignore | 2 + .vscode/launch.json | 16 ++++++ gemla/Cargo.toml | 2 + gemla/src/bracket/mod.rs | 2 +- gemla/src/file_linked/mod.rs | 3 +- gemla/src/main.rs | 2 +- gemla/src/tests/tree.rs | 5 +- gemla/src/tree/mod.rs | 107 ++++++----------------------------- 8 files changed, 43 insertions(+), 96 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.gitignore b/.gitignore index 4836da8..6f66af9 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk + +settings.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..3b9c326 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug", + "program": "${workspaceFolder}/gemla/target/debug/gemla.exe", + "args": ["./gemla/temp/"], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/gemla/Cargo.toml b/gemla/Cargo.toml index f27712f..c7ee63a 100644 --- a/gemla/Cargo.toml +++ b/gemla/Cargo.toml @@ -5,6 +5,8 @@ authors = ["Jacob VanDomelen "] edition = "2018" [dependencies] +serde = { version = "1.0", features = ["derive"] } uuid = { version = "0.7", features = ["serde", "v4"] } clap = { version = "~2.27.0", features = ["yaml"] } +toml = "0.5.8" regex = "1" \ No newline at end of file diff --git a/gemla/src/bracket/mod.rs b/gemla/src/bracket/mod.rs index 2fc15d3..be3bb4b 100644 --- a/gemla/src/bracket/mod.rs +++ b/gemla/src/bracket/mod.rs @@ -43,7 +43,7 @@ pub fn run_bracket() { let mut height = 1; let mut tree = FileLinked::new( *build_tree(height).expect("Error getting result from build_tree"), - "temp", + "for_tests", ).expect("Unable to create file linked object from tree"); diff --git a/gemla/src/file_linked/mod.rs b/gemla/src/file_linked/mod.rs index 74486bb..f2290d6 100644 --- a/gemla/src/file_linked/mod.rs +++ b/gemla/src/file_linked/mod.rs @@ -15,7 +15,8 @@ impl FileLinked where T: FromStr + ToString + Default, { - pub fn from_file(path: &str) -> Result, String> { + pub fn from_file(path: &str) -> Result, String> + { let meta = fs::metadata(path); match &meta { diff --git a/gemla/src/main.rs b/gemla/src/main.rs index 08bef82..38d1637 100644 --- a/gemla/src/main.rs +++ b/gemla/src/main.rs @@ -35,7 +35,7 @@ fn main() { println!("\n\nReading tree from temp file."); let tree: file_linked::FileLinked> = - file_linked::FileLinked::from_file("temp").expect( + file_linked::FileLinked::from_file("./for_tests").expect( "Unable to read tree from existing file", ); println!("Value read from file:\n{}", tree); diff --git a/gemla/src/tests/tree.rs b/gemla/src/tests/tree.rs index a6c5aba..7025f7f 100644 --- a/gemla/src/tests/tree.rs +++ b/gemla/src/tests/tree.rs @@ -18,12 +18,13 @@ fn test_new() { #[test] fn test_fmt() { + assert_eq!( format!( "{}", btree!("foo", btree!("bar"),), ), - "(foo: (bar: _|_)|_)" + "val = \"foo\"\n\n[left]\nval = \"bar\"\n" ); } @@ -36,7 +37,7 @@ fn test_fmt_node() { ); assert_eq!( Tree::fmt_node(&Some(Box::new(btree!(btree!("foo"))))), - "(foo: _|_)" + "val = \"foo\"\n" ); assert_eq!(Tree::::fmt_node(&None), "_"); } diff --git a/gemla/src/tree/mod.rs b/gemla/src/tree/mod.rs index 3a3c776..9138df1 100644 --- a/gemla/src/tree/mod.rs +++ b/gemla/src/tree/mod.rs @@ -24,8 +24,9 @@ //! ``` use std::fmt; +use serde::{Serialize, Deserialize}; +use serde::de::DeserializeOwned; use std::str::FromStr; -use regex::Regex; /// An unbalanced binary tree type where each node has an optional left and right child. /// @@ -48,7 +49,7 @@ use regex::Regex; /// let t1 = btree!(1,btree!(2),btree!(3)) /// assert_eq!(format!("{}", t1), "(1: (2: _|_)|(3: _|_)") /// ``` -#[derive(Default, Clone, PartialEq, Debug)] +#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Debug)] pub struct Tree { pub val: T, pub left: Option>>, @@ -95,6 +96,7 @@ impl Tree { where T: fmt::Display, { + match t { Some(n) => format!("{}", (*n).val), _ => String::from("_"), @@ -102,103 +104,26 @@ impl Tree { } } -impl fmt::Display for Tree { +impl fmt::Display for Tree { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let node_str = |t: &Option>>| -> String { - match t { - Some(n) => format!("{}", *n), - _ => String::from("_"), - } - }; - - write!( - f, - "({}: {}|{})", - self.val, - node_str(&self.left), - node_str(&self.right) - ) - } -} - -fn seperate_nodes(s: &str) -> Result<(&str, &str), ParseTreeError> { - let mut result = Err(ParseTreeError::new( - format!("Unable to seperate string: {}", s), - )); - let mut stack: Vec = Vec::new(); - - for (i, c) in s.char_indices() { - if c == '(' { - stack.push(c); - } else if c == ')' { - if stack.is_empty() { - result = Err(ParseTreeError::new( - format!("Unbalanced parenthesis found in string: {}", s), - )); - break; - } - - stack.pop(); - } else if c == '|' && stack.is_empty() { - result = Ok((&s[..i], &s[i + 1..])); - break; + let result = toml::to_string(self); + + match result + { + Ok(string) => write!(f, "{}", string), + Err(_) => Err(std::fmt::Error), } } - - result } -fn from_str_helper(s: &str) -> Result>>, ParseTreeError> { - let mut result = Err(ParseTreeError::new(String::from( - "Unable to parse tree, string format unrecognized.", - ))); - let emptyre = Regex::new(r"\s*_\s*").unwrap(); - let re = Regex::new(r"\(([0-9a-fA-F-]+)\s*:\s*(.*)\)$").unwrap(); - let caps = re.captures(s); - - if let Some(c) = caps { - let val = T::from_str(c.get(1).unwrap().as_str()).or_else(|_| { - Err(ParseTreeError::new(format!( - "Unable to parse node value: {}", - c.get(1).unwrap().as_str() - ))) - })?; - let (left, right) = seperate_nodes(c.get(2).unwrap().as_str())?; - let left = from_str_helper(left)?; - let right = from_str_helper(right)?; - - result = Ok(Some(Box::new(Tree::new(val, left, right)))); - } else if emptyre.is_match(s) { - result = Ok(None); - } - - result -} impl FromStr for Tree -where - T: FromStr, + where T: FromStr + DeserializeOwned { - type Err = ParseTreeError; + type Err = String; - fn from_str(s: &str) -> Result { - let result = from_str_helper(s)?; - - result - .ok_or_else(|| { - ParseTreeError::new(format!("Unable to parse string {}", s)) - }) - .and_then(|t| Ok(*t)) - } -} - -#[derive(Debug)] -pub struct ParseTreeError { - pub msg: String, -} - -impl ParseTreeError { - fn new(msg: String) -> ParseTreeError { - ParseTreeError { msg } + fn from_str(s: &str) -> Result + { + toml::from_str(s).or_else(|_| {Err(format!("Unable to parse string {}", s))}) } }