diff --git a/file_linked/src/lib.rs b/file_linked/src/lib.rs index 14271e0..7c2d0e5 100644 --- a/file_linked/src/lib.rs +++ b/file_linked/src/lib.rs @@ -5,6 +5,7 @@ extern crate serde; use std::fmt; use std::fs; use std::io::prelude::*; +use std::path; use serde::de::DeserializeOwned; use serde::Serialize; @@ -15,7 +16,7 @@ where T: Serialize, { val: T, - path: String, + path: path::PathBuf, } impl FileLinked @@ -30,6 +31,7 @@ where /// # use serde::{Deserialize, Serialize}; /// # use std::fmt; /// # use std::string::ToString; + /// # use std::path; /// # /// # #[derive(Deserialize, Serialize)] /// # struct Test { @@ -45,7 +47,7 @@ where /// c: 3.0 /// }; /// - /// let linked_test = FileLinked::new(test, String::from("./temp")) + /// let linked_test = FileLinked::new(test, path::PathBuf::from("./temp")) /// .expect("Unable to create file linked object"); /// /// assert_eq!(linked_test.readonly().a, 1); @@ -60,13 +62,14 @@ where } /// Creates a new [`FileLinked`] object of type `T` stored to the file given by `path`. - /// + /// /// # Examples /// ``` /// # use file_linked::*; /// # use serde::{Deserialize, Serialize}; /// # use std::fmt; /// # use std::string::ToString; + /// # use std::path; /// # /// #[derive(Deserialize, Serialize)] /// struct Test { @@ -82,7 +85,7 @@ where /// c: 3.0 /// }; /// - /// let linked_test = FileLinked::new(test, String::from("./temp")) + /// let linked_test = FileLinked::new(test, path::PathBuf::from("./temp")) /// .expect("Unable to create file linked object"); /// /// assert_eq!(linked_test.readonly().a, 1); @@ -92,7 +95,11 @@ where /// # std::fs::remove_file("./temp").expect("Unable to remove file"); /// # } /// ``` - pub fn new(val: T, path: String) -> Result, String> { + pub fn new(val: T, path: path::PathBuf) -> Result, String> { + if path.is_file() { + return Err(format!("{} is not a valid file path", path.display())); + } + let result = FileLinked { val, path }; result.write_data()?; @@ -106,23 +113,28 @@ where .create(true) .truncate(true) .open(&self.path) - .map_err(|_| format!("Unable to open path {}", self.path))?; + .map_err(|_| format!("Unable to open path {}", self.path.display()))?; - write!(file, "{}", serde_json::to_string(&self.val).map_err(|e| e.to_string())?) - .or_else(|_| Err(String::from("Unable to write to file.")))?; + write!( + file, + "{}", + serde_json::to_string(&self.val).map_err(|e| e.to_string())? + ) + .or_else(|_| Err(String::from("Unable to write to file.")))?; Ok(()) } - /// Modifies the data contained in a `FileLinked` object using a callback `op` that has a mutable reference to the + /// Modifies the data contained in a `FileLinked` object using a callback `op` that has a mutable reference to the /// underlying data. After the mutable operation is performed the data is written to a file to synchronize the state. - /// + /// /// # Examples /// ``` /// # use file_linked::*; /// # use serde::{Deserialize, Serialize}; /// # use std::fmt; /// # use std::string::ToString; + /// # use std::path; /// # /// # #[derive(Deserialize, Serialize)] /// # struct Test { @@ -138,13 +150,13 @@ where /// c: 0.0 /// }; /// - /// let mut linked_test = FileLinked::new(test, String::from("./temp")) + /// let mut linked_test = FileLinked::new(test, path::PathBuf::from("./temp")) /// .expect("Unable to create file linked object"); /// /// assert_eq!(linked_test.readonly().a, 1); - /// + /// /// linked_test.mutate(|t| t.a = 2)?; - /// + /// /// assert_eq!(linked_test.readonly().a, 2); /// # /// # std::fs::remove_file("./temp").expect("Unable to remove file"); @@ -161,13 +173,14 @@ where } /// Replaces the value held by the `FileLinked` object with `val`. After replacing the object will be written to a file. - /// + /// /// # Examples /// ``` /// # use file_linked::*; /// # use serde::{Deserialize, Serialize}; /// # use std::fmt; /// # use std::string::ToString; + /// # use std::path; /// # /// # #[derive(Deserialize, Serialize)] /// # struct Test { @@ -183,17 +196,17 @@ where /// c: 0.0 /// }; /// - /// let mut linked_test = FileLinked::new(test, String::from("./temp")) + /// let mut linked_test = FileLinked::new(test, path::PathBuf::from("./temp")) /// .expect("Unable to create file linked object"); /// /// assert_eq!(linked_test.readonly().a, 1); - /// + /// /// linked_test.replace(Test { /// a: 2, /// b: String::from(""), /// c: 0.0 /// })?; - /// + /// /// assert_eq!(linked_test.readonly().a, 2); /// # /// # std::fs::remove_file("./temp").expect("Unable to remove file"); @@ -210,10 +223,10 @@ where impl FileLinked where - T: Serialize + DeserializeOwned + Default, + T: Serialize + DeserializeOwned, { /// Deserializes an object `T` from the file given by `path` - /// + /// /// # Examples /// ``` /// # use file_linked::*; @@ -223,8 +236,9 @@ where /// # use std::fs; /// # use std::fs::OpenOptions; /// # use std::io::Write; + /// # use std::path; /// # - /// # #[derive(Deserialize, Serialize, Default)] + /// # #[derive(Deserialize, Serialize)] /// # struct Test { /// # pub a: u32, /// # pub b: String, @@ -237,22 +251,22 @@ where /// b: String::from("2"), /// c: 3.0 /// }; - /// - /// let path = String::from("./temp"); - /// + /// + /// let path = path::PathBuf::from("./temp"); + /// /// let mut file = OpenOptions::new() /// .write(true) /// .create(true) /// .open(path.clone()) /// .expect("Unable to create file"); - /// + /// /// write!(file, "{}", serde_json::to_string(&test) /// .expect("Unable to serialize object")) /// .expect("Unable to write file"); - /// + /// /// drop(file); /// - /// let mut linked_test = FileLinked::::from_file(&path) + /// let mut linked_test = FileLinked::::from_file(path) /// .expect("Unable to create file linked object"); /// /// assert_eq!(linked_test.readonly().a, test.a); @@ -264,43 +278,30 @@ where /// # Ok(()) /// # } /// ``` - pub fn from_file(path: &str) -> Result, String> { - let meta = fs::metadata(path); + pub fn from_file(path: path::PathBuf) -> Result, String> { + let meta = fs::metadata(&path); match &meta { - Ok(m) if m.is_file() => { + Ok(m) if m.is_file() && path.is_file()=> { let file = fs::OpenOptions::new() .read(true) - .open(path) - .map_err(|_| format!("Unable to open file {}", path))?; + .open(&path) + .map_err(|_| format!("Unable to open file {}", path.display()))?; let val = serde_json::from_reader(file) .map_err(|_| String::from("Unable to parse value from file."))?; - Ok(FileLinked { - val, - path: String::from(path), - }) - } - Ok(_) => Err(format!("{} is not a file.", path)), - _ => { - let result = FileLinked { - val: T::default(), - path: String::from(path), - }; - - result.write_data()?; - - Ok(result) + Ok(FileLinked { val, path }) } + Ok(_) => Err(format!("{} is not a file.", path.display())), + _ => Err(format!("Error parsing file path {}", path.display())), } } } impl fmt::Debug for FileLinked where - T: fmt::Debug - + Serialize, + T: fmt::Debug + Serialize, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", self.val) @@ -315,12 +316,9 @@ mod tests { #[test] fn test_mutate() -> Result<(), String> { let list = vec![1, 2, 3, 4]; - let mut file_linked_list = FileLinked::new(list, String::from("test.txt"))?; + let mut file_linked_list = FileLinked::new(list, path::PathBuf::from("test.txt"))?; - assert_eq!( - format!("{:?}", file_linked_list.readonly()), - "[1, 2, 3, 4]" - ); + assert_eq!(format!("{:?}", file_linked_list.readonly()), "[1, 2, 3, 4]"); file_linked_list.mutate(|v1| v1.push(5))?; @@ -329,9 +327,7 @@ mod tests { "[1, 2, 3, 4, 5]" ); - file_linked_list.mutate(|v1| { - v1[1] = 1 - })?; + file_linked_list.mutate(|v1| v1[1] = 1)?; assert_eq!( format!("{:?}", file_linked_list.readonly()), diff --git a/gemla/src/bracket/mod.rs b/gemla/src/bracket/mod.rs index bac8e3e..e87db18 100644 --- a/gemla/src/bracket/mod.rs +++ b/gemla/src/bracket/mod.rs @@ -9,6 +9,7 @@ use file_linked::FileLinked; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use std::fmt; +use std::path; use std::str::FromStr; /// As the bracket tree increases in height, `IterationScaling` can be used to configure the number of iterations that @@ -22,6 +23,7 @@ use std::str::FromStr; /// # use std::fmt; /// # use std::str::FromStr; /// # use std::string::ToString; +/// # use std::path; /// # /// # #[derive(Default, Deserialize, Serialize, Clone)] /// # struct TestState { @@ -66,7 +68,7 @@ use std::str::FromStr; /// # } /// # /// # fn main() { -/// let mut bracket = Bracket::::initialize("./temp".to_string()) +/// let mut bracket = Bracket::::initialize(path::PathBuf::from("./temp")) /// .expect("Bracket failed to initialize"); /// /// // Constant iteration scaling ensures that every node is simulated 5 times. @@ -120,8 +122,7 @@ where impl fmt::Debug for Bracket where - T: genetic_node::GeneticNode - + Serialize + T: genetic_node::GeneticNode + Serialize, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( @@ -134,12 +135,7 @@ where impl Bracket where - T: genetic_node::GeneticNode - + FromStr - + Default - + DeserializeOwned - + Serialize - + Clone, + T: genetic_node::GeneticNode + FromStr + Default + DeserializeOwned + Serialize + Clone, { /// Initializes a bracket of type `T` storing the contents to `file_path` /// @@ -151,6 +147,7 @@ where /// # use std::fmt; /// # use std::str::FromStr; /// # use std::string::ToString; + /// # use std::path; /// # /// #[derive(Default, Deserialize, Serialize, Debug, Clone)] /// struct TestState { @@ -203,7 +200,7 @@ where /// } /// /// # fn main() { - /// let mut bracket = Bracket::::initialize("./temp".to_string()) + /// let mut bracket = Bracket::::initialize(path::PathBuf::from("./temp")) /// .expect("Bracket failed to initialize"); /// /// assert_eq!( @@ -215,7 +212,7 @@ where /// std::fs::remove_file("./temp").expect("Unable to remove file"); /// # } /// ``` - pub fn initialize(file_path: String) -> Result, String> { + pub fn initialize(file_path: path::PathBuf) -> Result, String> { FileLinked::new( Bracket { tree: btree!(*T::initialize()?), @@ -234,6 +231,7 @@ where /// # use std::fmt; /// # use std::str::FromStr; /// # use std::string::ToString; + /// # use std::path; /// # /// # #[derive(Default, Deserialize, Serialize, Clone)] /// # struct TestState { @@ -284,7 +282,7 @@ where /// # } /// # /// # fn main() { - /// let mut bracket = Bracket::::initialize("./temp".to_string()) + /// let mut bracket = Bracket::::initialize(path::PathBuf::from("./temp")) /// .expect("Bracket failed to initialize"); /// /// // Constant iteration scaling ensures that every node is simulated 5 times. @@ -343,6 +341,7 @@ where /// # use std::fmt; /// # use std::str::FromStr; /// # use std::string::ToString; + /// # use std::path; /// # /// # #[derive(Default, Deserialize, Serialize, Clone)] /// # struct TestState { @@ -393,7 +392,7 @@ where /// # } /// # /// # fn main() { - /// let mut bracket = Bracket::::initialize("./temp".to_string()) + /// let mut bracket = Bracket::::initialize(path::PathBuf::from("./temp")) /// .expect("Bracket failed to initialize"); /// /// // Running simulations 3 times @@ -434,7 +433,6 @@ mod tests { use serde::{Deserialize, Serialize}; use std::str::FromStr; - use std::string::ToString; #[derive(Default, Deserialize, Serialize, Clone, Debug)] struct TestState { @@ -474,7 +472,7 @@ mod tests { #[test] fn test_new() { - let bracket = Bracket::::initialize("./temp".to_string()) + let bracket = Bracket::::initialize(path::PathBuf::from("./temp")) .expect("Bracket failed to initialize"); assert_eq!( @@ -488,7 +486,7 @@ mod tests { #[test] fn test_run() { - let mut bracket = Bracket::::initialize("./temp2".to_string()) + let mut bracket = Bracket::::initialize(path::PathBuf::from("./temp2")) .expect("Bracket failed to initialize"); bracket diff --git a/gemla/src/lib.rs b/gemla/src/lib.rs index 96c5982..310ab4b 100644 --- a/gemla/src/lib.rs +++ b/gemla/src/lib.rs @@ -1,5 +1,5 @@ -extern crate regex; extern crate file_linked; +extern crate regex; #[macro_use] pub mod tree; diff --git a/gemla/src/tree/mod.rs b/gemla/src/tree/mod.rs index 271f785..357f25a 100644 --- a/gemla/src/tree/mod.rs +++ b/gemla/src/tree/mod.rs @@ -4,14 +4,14 @@ //! //! ``` //! use gemla::btree; -//! +//! //! // Tree with 2 nodes, one root node and one on the left side //! let mut t = btree!(1, btree!(2),); -//! +//! //! assert_eq!(t.height(), 2); //! assert_eq!(t.left.unwrap().val, 2); //! assert_eq!(t.right, None); -//! +//! //! t.right = Some(Box::new(btree!(3))); //! assert_eq!(t.right.unwrap().val, 3); //! ``` @@ -28,14 +28,14 @@ use std::str::FromStr; /// /// ``` /// use gemla::btree; -/// +/// /// // Tree with 2 nodes, one root node and one on the left side /// let mut t = btree!(1, btree!(2),); -/// +/// /// assert_eq!(t.height(), 2); /// assert_eq!(t.left.unwrap().val, 2); /// assert_eq!(t.right, None); -/// +/// /// t.right = Some(Box::new(btree!(3))); /// assert_eq!(t.right.unwrap().val, 3); /// ``` @@ -53,34 +53,34 @@ pub struct Tree { /// ``` /// use gemla::tree::*; /// use gemla::btree; -/// +/// /// # fn main() { /// // A tree with two child nodes. /// let t = btree!(1, btree!(2), btree!(3)); -/// assert_eq!(t, -/// Tree::new(1, -/// Some(Box::new(Tree::new(2, None, None))), +/// assert_eq!(t, +/// Tree::new(1, +/// Some(Box::new(Tree::new(2, None, None))), /// Some(Box::new(Tree::new(3, None, None))))); -/// +/// /// // A tree with only a left node. /// let t_left = btree!(1, btree!(2),); -/// assert_eq!(t_left, -/// Tree::new(1, -/// Some(Box::new(Tree::new(2, None, None))), +/// assert_eq!(t_left, +/// Tree::new(1, +/// Some(Box::new(Tree::new(2, None, None))), /// None)); -/// +/// /// // A tree with only a right node. /// let t_right = btree!(1, , btree!(3)); -/// assert_eq!(t_right, -/// Tree::new(1, -/// None, +/// assert_eq!(t_right, +/// Tree::new(1, +/// None, /// Some(Box::new(Tree::new(3, None, None))))); -/// +/// /// // A tree with no child nodes. /// let t_single = btree!(1); -/// assert_eq!(t_single, -/// Tree::new(1, -/// None, +/// assert_eq!(t_single, +/// Tree::new(1, +/// None, /// None)); /// # } /// ``` @@ -102,12 +102,12 @@ macro_rules! btree { impl Tree { /// Constructs a new [`Tree`] object - /// + /// /// # Examples - /// + /// /// ``` /// use gemla::tree::*; - /// + /// /// let t = Tree::new(1, None, None); /// assert_eq!(t, Tree { /// val: 1, @@ -120,16 +120,16 @@ impl Tree { } /// Obtains the height of the longest branch in a [`Tree`] - /// + /// /// # Examples - /// + /// /// ``` /// use gemla::tree::*; /// use gemla::btree; - /// - /// let t = - /// btree!("a", - /// btree!("aa", + /// + /// let t = + /// btree!("a", + /// btree!("aa", /// btree!("aaa"),), /// btree!("ab")); /// assert_eq!(t.height(), 3);