Modified FileLinked struct
This commit is contained in:
parent
53e0ec865f
commit
f3720847ed
7 changed files with 143 additions and 114 deletions
|
@ -1,10 +1,10 @@
|
|||
mod state;
|
||||
|
||||
use super::tree;
|
||||
use super::file_linked::FileLinked;
|
||||
use super::tree;
|
||||
|
||||
use uuid::Uuid;
|
||||
use std::str::FromStr;
|
||||
use uuid::Uuid;
|
||||
|
||||
impl tree::Tree<Uuid> {
|
||||
pub fn run_simulation(&self) {
|
||||
|
@ -44,8 +44,8 @@ pub fn run_bracket() {
|
|||
let mut tree = FileLinked::new(
|
||||
*build_tree(height).expect("Error getting result from build_tree"),
|
||||
"for_tests",
|
||||
).expect("Unable to create file linked object from tree");
|
||||
|
||||
)
|
||||
.expect("Unable to create file linked object from tree");
|
||||
|
||||
// Building tree one node at a time, appending to the top.
|
||||
loop {
|
||||
|
@ -56,7 +56,8 @@ pub fn run_bracket() {
|
|||
Uuid::new_v4(),
|
||||
Some(Box::new(tree.readonly().clone())),
|
||||
build_tree(height),
|
||||
)).expect("Error building up tree node");
|
||||
))
|
||||
.expect("Error building up tree node");
|
||||
tree.readonly().run_simulation();
|
||||
|
||||
if height == 3 {
|
||||
|
|
|
@ -1,37 +1,85 @@
|
|||
use std::fs;
|
||||
use std::str::FromStr;
|
||||
use std::fmt;
|
||||
use std::string::String;
|
||||
use std::string::ToString;
|
||||
use std::fs;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
use std::string::String;
|
||||
use std::string::ToString;
|
||||
|
||||
pub struct FileLinked<T> {
|
||||
val: T,
|
||||
path: String,
|
||||
}
|
||||
|
||||
impl<T> FileLinked<T> {
|
||||
pub fn readonly(&self) -> &T {
|
||||
&self.val
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> FileLinked<T>
|
||||
where
|
||||
T: FromStr + ToString + Default,
|
||||
T: ToString,
|
||||
{
|
||||
pub fn from_file(path: &str) -> Result<FileLinked<T>, String>
|
||||
pub fn new(val: T, path: &str) -> Result<FileLinked<T>, String> {
|
||||
let result = FileLinked {
|
||||
val,
|
||||
path: String::from(path),
|
||||
};
|
||||
|
||||
result.write_data()?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn write_data(&self) -> Result<(), String> {
|
||||
let mut file = fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(&self.path)
|
||||
.map_err(|_| format!("Unable to open path {}", self.path))?;
|
||||
|
||||
write!(file, "{}", self.val.to_string())
|
||||
.or_else(|_| Err(String::from("Unable to write to file.")))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn mutate<U, F: FnOnce(&mut T) -> U>(&mut self, op: F) -> Result<U, String> {
|
||||
let result = op(&mut self.val);
|
||||
|
||||
self.write_data()?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn replace(&mut self, val: T) -> Result<(), String> {
|
||||
self.val = val;
|
||||
|
||||
self.write_data()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> FileLinked<T>
|
||||
where
|
||||
T: ToString + FromStr + Default,
|
||||
{
|
||||
pub fn from_file(path: &str) -> Result<FileLinked<T>, String> {
|
||||
let meta = fs::metadata(path);
|
||||
|
||||
match &meta {
|
||||
Ok(m) if m.is_file() => {
|
||||
let mut file = fs::OpenOptions::new().read(true).open(path).or_else(|_| {
|
||||
Err(format!("Unable to open file {}", path))
|
||||
})?;
|
||||
let mut file = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.open(path)
|
||||
.map_err(|_| format!("Unable to open file {}", path))?;
|
||||
let mut s = String::new();
|
||||
file.read_to_string(&mut s).or_else(|_| {
|
||||
Err(String::from("Unable to read from file."))
|
||||
})?;
|
||||
file.read_to_string(&mut s)
|
||||
.map_err(|_| String::from("Unable to read from file."))?;
|
||||
|
||||
let val = T::from_str(&s).or_else(|_| {
|
||||
Err(String::from("Unable to parse value from file."))
|
||||
})?;
|
||||
let val = T::from_str(&s)
|
||||
.map_err(|_| String::from("Unable to parse value from file."))?;
|
||||
|
||||
Ok(FileLinked {
|
||||
val,
|
||||
|
@ -51,50 +99,6 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(val: T, path: &str) -> Result<FileLinked<T>, String> {
|
||||
let result = FileLinked {
|
||||
val,
|
||||
path: String::from(path),
|
||||
};
|
||||
|
||||
result.write_data()?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn write_data(&self) -> Result<(), String> {
|
||||
let mut file = fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(&self.path)
|
||||
.or_else(|_| Err(format!("Unable to open path {}", self.path)))?;
|
||||
|
||||
write!(file, "{}", self.val.to_string()).or_else(|_| {
|
||||
Err(String::from("Unable to write to file."))
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn readonly(&self) -> &T {
|
||||
&self.val
|
||||
}
|
||||
|
||||
pub fn mutate<U, F: FnOnce(&mut T) -> U>(&mut self, op: F) -> Result<U, String> {
|
||||
let result = op(&mut self.val);
|
||||
|
||||
self.write_data()?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn replace(&mut self, val: T) -> Result<(), String> {
|
||||
self.val = val;
|
||||
|
||||
self.write_data()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display> fmt::Display for FileLinked<T> {
|
||||
|
|
|
@ -35,9 +35,8 @@ fn main() {
|
|||
|
||||
println!("\n\nReading tree from temp file.");
|
||||
let tree: file_linked::FileLinked<tree::Tree<uuid::Uuid>> =
|
||||
file_linked::FileLinked::from_file("./for_tests").expect(
|
||||
"Unable to read tree from existing file",
|
||||
);
|
||||
file_linked::FileLinked::from_file("./for_tests")
|
||||
.expect("Unable to read tree from existing file");
|
||||
println!("Value read from file:\n{}", tree);
|
||||
}
|
||||
Ok(_) => println!("{} is not a valid directory!", directory),
|
||||
|
|
|
@ -1 +1,33 @@
|
|||
use super::super::file_linked::FileLinked;
|
||||
use super::super::tree::Tree;
|
||||
|
||||
#[test]
|
||||
fn test_mutate() -> Result<(), String> {
|
||||
let tree = btree!(1, btree!(2), btree!(3, btree!(4),));
|
||||
let mut linked_tree = FileLinked::new(tree, "blah.txt")?;
|
||||
|
||||
assert_eq!(
|
||||
format!("{}", linked_tree.readonly()),
|
||||
"val = 1\n\n[left]\nval = 2\n\n[right]\nval = 3\n\n[right.left]\nval = 4\n"
|
||||
);
|
||||
|
||||
linked_tree.mutate(|v1| v1.val = 10)?;
|
||||
|
||||
assert_eq!(
|
||||
format!("{}", linked_tree.readonly()),
|
||||
"val = 10\n\n[left]\nval = 2\n\n[right]\nval = 3\n\n[right.left]\nval = 4\n"
|
||||
);
|
||||
|
||||
linked_tree.mutate(|v1| {
|
||||
let mut left = v1.left.clone().unwrap();
|
||||
left.val = 13;
|
||||
v1.left = Some(left);
|
||||
})?;
|
||||
|
||||
assert_eq!(
|
||||
format!("{}", linked_tree.readonly()),
|
||||
"val = 10\n\n[left]\nval = 13\n\n[right]\nval = 3\n\n[right.left]\nval = 4\n"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
mod tree;
|
||||
mod bracket;
|
||||
mod file_linked;
|
||||
mod tree;
|
||||
|
|
|
@ -18,12 +18,8 @@ fn test_new() {
|
|||
|
||||
#[test]
|
||||
fn test_fmt() {
|
||||
|
||||
assert_eq!(
|
||||
format!(
|
||||
"{}",
|
||||
btree!("foo", btree!("bar"),),
|
||||
),
|
||||
format!("{}", btree!("foo", btree!("bar"),),),
|
||||
"val = \"foo\"\n\n[left]\nval = \"bar\"\n"
|
||||
);
|
||||
}
|
||||
|
@ -31,10 +27,7 @@ fn test_fmt() {
|
|||
#[test]
|
||||
fn test_fmt_node() {
|
||||
let t = btree!(17, btree!(16), btree!(12));
|
||||
assert_eq!(
|
||||
Tree::fmt_node(&t.left),
|
||||
"16"
|
||||
);
|
||||
assert_eq!(Tree::fmt_node(&t.left), "16");
|
||||
assert_eq!(
|
||||
Tree::fmt_node(&Some(Box::new(btree!(btree!("foo"))))),
|
||||
"val = \"foo\"\n"
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
//! # }
|
||||
//! ```
|
||||
|
||||
use std::fmt;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
/// An unbalanced binary tree type where each node has an optional left and right child.
|
||||
|
@ -76,14 +76,17 @@ pub struct Tree<T> {
|
|||
#[macro_export]
|
||||
macro_rules! btree {
|
||||
($val:expr, $l:expr, $r:expr) => {
|
||||
$crate::tree::Tree::new(
|
||||
$val,
|
||||
Some(Box::new($l)),
|
||||
Some(Box::new($r))
|
||||
) };
|
||||
($val:expr, , $r:expr) => { $crate::tree::Tree::new($val, None, Some(Box::new($r))) };
|
||||
($val:expr, $l:expr,) => { $crate::tree::Tree::new($val, Some(Box::new($l)), None) };
|
||||
($val:expr) => { Tree::new($val, None, None) };
|
||||
$crate::tree::Tree::new($val, Some(Box::new($l)), Some(Box::new($r)))
|
||||
};
|
||||
($val:expr, , $r:expr) => {
|
||||
$crate::tree::Tree::new($val, None, Some(Box::new($r)))
|
||||
};
|
||||
($val:expr, $l:expr,) => {
|
||||
$crate::tree::Tree::new($val, Some(Box::new($l)), None)
|
||||
};
|
||||
($val:expr) => {
|
||||
Tree::new($val, None, None)
|
||||
};
|
||||
}
|
||||
|
||||
impl<T> Tree<T> {
|
||||
|
@ -96,7 +99,6 @@ impl<T> Tree<T> {
|
|||
where
|
||||
T: fmt::Display,
|
||||
{
|
||||
|
||||
match t {
|
||||
Some(n) => format!("{}", (*n).val),
|
||||
_ => String::from("_"),
|
||||
|
@ -108,22 +110,20 @@ impl<T: fmt::Display + Serialize> fmt::Display for Tree<T> {
|
|||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let result = toml::to_string(self);
|
||||
|
||||
match result
|
||||
{
|
||||
match result {
|
||||
Ok(string) => write!(f, "{}", string),
|
||||
Err(_) => Err(std::fmt::Error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T> FromStr for Tree<T>
|
||||
where T: FromStr + DeserializeOwned
|
||||
where
|
||||
T: FromStr + DeserializeOwned,
|
||||
{
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err>
|
||||
{
|
||||
toml::from_str(s).or_else(|_| {Err(format!("Unable to parse string {}", s))})
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
toml::from_str(s).map_err(|_| format!("Unable to parse string {}", s))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue