From 4252851b810699331f3ad1602962dcae41f26084 Mon Sep 17 00:00:00 2001 From: Jacob VanDomelen Date: Fri, 31 May 2019 16:49:39 -0700 Subject: [PATCH] Finished implementing FileLinked struct. --- gemla/src/file_data/mod.rs | 3 -- gemla/src/file_linked/mod.rs | 71 ++++++++++++++++++++++++++++++++++++ gemla/src/main.rs | 2 + gemla/src/tree/mod.rs | 55 ++++++++++++++++------------ 4 files changed, 104 insertions(+), 27 deletions(-) delete mode 100644 gemla/src/file_data/mod.rs create mode 100644 gemla/src/file_linked/mod.rs diff --git a/gemla/src/file_data/mod.rs b/gemla/src/file_data/mod.rs deleted file mode 100644 index 7f347ca..0000000 --- a/gemla/src/file_data/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -trait FileData { - -} \ No newline at end of file diff --git a/gemla/src/file_linked/mod.rs b/gemla/src/file_linked/mod.rs new file mode 100644 index 0000000..378bbff --- /dev/null +++ b/gemla/src/file_linked/mod.rs @@ -0,0 +1,71 @@ +use std::fs; +use std::str::FromStr; +use std::fmt::Display; +use std::string::String; +use std::io::Read; +use std::io::Write; + +pub struct FileLinked { + val: T, + path: String +} + +impl FileLinked { + pub fn from_file(path: &str) -> Result, String> { + let meta = fs::metadata(path) + .or(Err(format!("Path {} does not exist.", path)))?; + + if meta.is_file() { + let mut file = fs::OpenOptions::new().read(true).open(path) + .or(Err(format!("Unable to open file {}", path)))?; + let mut s = String::new(); + file.read_to_string(&mut s) + .or(Err(String::from("Unable to read from file.")))?; + + let val = T::from_str(&s).or(Err(String::from("Unable to parse value from file.")))?; + + Ok(FileLinked { + val, + path: String::from(path) + }) + } else { + Err(format!("{} is not a file.", path)) + } + } + + pub fn new(val: T, path: &str) -> FileLinked { + let result = FileLinked { + val, + path: String::from(path) + }; + + result.write_data(); + + result + } + + pub fn write_data(&self) -> Result<(), String> { + let mut file = fs::OpenOptions::new() + .write(true) + .create_new(true) + .open(&self.path) + .or(Err(format!("Unable to open path {}", self.path)))?; + + write!(file, "{}", self.val) + .or(Err(String::from("Unable to write to file.")))?; + + Ok(()) + } + + pub fn readonly(&self) -> &T { + &self.val + } + + pub fn mutate U>(&mut self, op: F) -> U { + let result = op(&mut self.val); + + self.write_data(); + + result + } +} \ No newline at end of file diff --git a/gemla/src/main.rs b/gemla/src/main.rs index 9493271..9abefcf 100644 --- a/gemla/src/main.rs +++ b/gemla/src/main.rs @@ -5,6 +5,7 @@ extern crate regex; mod bracket; mod tree; mod constants; +mod file_linked; use clap::App; use std::fs::metadata; @@ -12,6 +13,7 @@ use std::fs::metadata; /// Runs a simluation of a genetic algorithm against a dataset. /// /// Use the -h, --h, or --help flag to see usage syntax. +/// TODO fn main() { // Command line arguments are parsed with the clap crate. And this program uses // the yaml method with clap. diff --git a/gemla/src/tree/mod.rs b/gemla/src/tree/mod.rs index f02286b..6f2b5d4 100644 --- a/gemla/src/tree/mod.rs +++ b/gemla/src/tree/mod.rs @@ -1,5 +1,4 @@ use std::fmt; - use std::str::FromStr; use regex::Regex; @@ -69,17 +68,13 @@ fn from_str_helper(s: &str) -> Result>>, ParseTre let caps = re.captures(s); if let Some(c) = caps { - result = T::from_str(c.get(1).unwrap().as_str()) - .or(Err(ParseTreeError::new(format!("Unable to parse node value: {}", c.get(1).unwrap().as_str())))) - .and_then(|v| { - seperate_nodes(c.get(2).unwrap().as_str()).and_then(|(left, right)| { - from_str_helper(left).and_then(|l| { - from_str_helper(right).and_then(|r| { - Ok(Some(Box::new(Tree::new(v, l, r)))) - }) - }) - }) - }) + let val = T::from_str(c.get(1).unwrap().as_str()) + .or(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); } @@ -96,22 +91,34 @@ impl FromStr for Tree where T: FromStr { let caps = re.captures(s); if let Some(c) = caps { - result = T::from_str(c.get(1).unwrap().as_str()) - .or(Err(ParseTreeError::new(format!("Unable to parse node value: {}", c.get(1).unwrap().as_str())))) - .and_then(|v| { - seperate_nodes(c.get(2).unwrap().as_str()).and_then(|(left, right)| { - from_str_helper(left).and_then(|l| { - from_str_helper(right).and_then(|r| { - Ok(Tree::new(v, l, r)) - }) - }) - }) - }) + let val = T::from_str(c.get(1).unwrap().as_str()) + .or(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(Tree::new(val, left, right)); } // if let Some(c) = caps { - // let val = T::from_str(c.get(1).unwrap().as_str()); + // result = T::from_str(c.get(1).unwrap().as_str()) + // .or(Err(ParseTreeError::new(format!("Unable to parse node value: {}", c.get(1).unwrap().as_str())))) + // .and_then(|v| { + // seperate_nodes(c.get(2).unwrap().as_str()) + // .and_then(|(left, right)| { + // from_str_helper(left) + // .and_then(|l| { + // from_str_helper(right) + // .and_then(|r| { + // Ok(Tree::new(v, l, r)) + // }) + // }) + // }) + // }) + // } + // if let Some(c) = caps { + // let val = T::from_str(c.get(1).unwrap().as_str()); // if let Ok(v) = val { // match seperate_nodes(c.get(2).unwrap().as_str()) { // Ok((l, r)) => {