Using serde for serializing

This commit is contained in:
Jacob VanDomelen 2021-01-12 13:42:35 -08:00
parent 978baef596
commit 53e0ec865f
8 changed files with 43 additions and 96 deletions

2
.gitignore vendored
View file

@ -8,3 +8,5 @@ Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
settings.json

16
.vscode/launch.json vendored Normal file
View file

@ -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}"
}
]
}

View file

@ -5,6 +5,8 @@ authors = ["Jacob VanDomelen <Jacob.Vandome15@gmail.com>"]
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"

View file

@ -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");

View file

@ -15,7 +15,8 @@ impl<T> FileLinked<T>
where
T: FromStr + ToString + Default,
{
pub fn from_file(path: &str) -> Result<FileLinked<T>, String> {
pub fn from_file(path: &str) -> Result<FileLinked<T>, String>
{
let meta = fs::metadata(path);
match &meta {

View file

@ -35,7 +35,7 @@ fn main() {
println!("\n\nReading tree from temp file.");
let tree: file_linked::FileLinked<tree::Tree<uuid::Uuid>> =
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);

View file

@ -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::<i32>::fmt_node(&None), "_");
}

View file

@ -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<T> {
pub val: T,
pub left: Option<Box<Tree<T>>>,
@ -95,6 +96,7 @@ impl<T> Tree<T> {
where
T: fmt::Display,
{
match t {
Some(n) => format!("{}", (*n).val),
_ => String::from("_"),
@ -102,103 +104,26 @@ impl<T> Tree<T> {
}
}
impl<T: fmt::Display> fmt::Display for Tree<T> {
impl<T: fmt::Display + Serialize> fmt::Display for Tree<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let node_str = |t: &Option<Box<Tree<T>>>| -> 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<char> = 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<T: FromStr>(s: &str) -> Result<Option<Box<Tree<T>>>, 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<T> FromStr for Tree<T>
where
T: FromStr,
where T: FromStr + DeserializeOwned
{
type Err = ParseTreeError;
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
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<Self, Self::Err>
{
toml::from_str(s).or_else(|_| {Err(format!("Unable to parse string {}", s))})
}
}