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;
|
mod state;
|
||||||
|
|
||||||
use super::tree;
|
|
||||||
use super::file_linked::FileLinked;
|
use super::file_linked::FileLinked;
|
||||||
|
use super::tree;
|
||||||
|
|
||||||
use uuid::Uuid;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
impl tree::Tree<Uuid> {
|
impl tree::Tree<Uuid> {
|
||||||
pub fn run_simulation(&self) {
|
pub fn run_simulation(&self) {
|
||||||
|
@ -44,8 +44,8 @@ pub fn run_bracket() {
|
||||||
let mut tree = FileLinked::new(
|
let mut tree = FileLinked::new(
|
||||||
*build_tree(height).expect("Error getting result from build_tree"),
|
*build_tree(height).expect("Error getting result from build_tree"),
|
||||||
"for_tests",
|
"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.
|
// Building tree one node at a time, appending to the top.
|
||||||
loop {
|
loop {
|
||||||
|
@ -56,7 +56,8 @@ pub fn run_bracket() {
|
||||||
Uuid::new_v4(),
|
Uuid::new_v4(),
|
||||||
Some(Box::new(tree.readonly().clone())),
|
Some(Box::new(tree.readonly().clone())),
|
||||||
build_tree(height),
|
build_tree(height),
|
||||||
)).expect("Error building up tree node");
|
))
|
||||||
|
.expect("Error building up tree node");
|
||||||
tree.readonly().run_simulation();
|
tree.readonly().run_simulation();
|
||||||
|
|
||||||
if height == 3 {
|
if height == 3 {
|
||||||
|
|
|
@ -1,37 +1,85 @@
|
||||||
use std::fs;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::string::String;
|
use std::fs;
|
||||||
use std::string::ToString;
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::string::String;
|
||||||
|
use std::string::ToString;
|
||||||
|
|
||||||
pub struct FileLinked<T> {
|
pub struct FileLinked<T> {
|
||||||
val: T,
|
val: T,
|
||||||
path: String,
|
path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> FileLinked<T> {
|
||||||
|
pub fn readonly(&self) -> &T {
|
||||||
|
&self.val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> FileLinked<T>
|
impl<T> FileLinked<T>
|
||||||
where
|
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);
|
let meta = fs::metadata(path);
|
||||||
|
|
||||||
match &meta {
|
match &meta {
|
||||||
Ok(m) if m.is_file() => {
|
Ok(m) if m.is_file() => {
|
||||||
let mut file = fs::OpenOptions::new().read(true).open(path).or_else(|_| {
|
let mut file = fs::OpenOptions::new()
|
||||||
Err(format!("Unable to open file {}", path))
|
.read(true)
|
||||||
})?;
|
.open(path)
|
||||||
|
.map_err(|_| format!("Unable to open file {}", path))?;
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
file.read_to_string(&mut s).or_else(|_| {
|
file.read_to_string(&mut s)
|
||||||
Err(String::from("Unable to read from file."))
|
.map_err(|_| String::from("Unable to read from file."))?;
|
||||||
})?;
|
|
||||||
|
|
||||||
let val = T::from_str(&s).or_else(|_| {
|
let val = T::from_str(&s)
|
||||||
Err(String::from("Unable to parse value from file."))
|
.map_err(|_| String::from("Unable to parse value from file."))?;
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(FileLinked {
|
Ok(FileLinked {
|
||||||
val,
|
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> {
|
impl<T: fmt::Display> fmt::Display for FileLinked<T> {
|
||||||
|
|
|
@ -35,9 +35,8 @@ fn main() {
|
||||||
|
|
||||||
println!("\n\nReading tree from temp file.");
|
println!("\n\nReading tree from temp file.");
|
||||||
let tree: file_linked::FileLinked<tree::Tree<uuid::Uuid>> =
|
let tree: file_linked::FileLinked<tree::Tree<uuid::Uuid>> =
|
||||||
file_linked::FileLinked::from_file("./for_tests").expect(
|
file_linked::FileLinked::from_file("./for_tests")
|
||||||
"Unable to read tree from existing file",
|
.expect("Unable to read tree from existing file");
|
||||||
);
|
|
||||||
println!("Value read from file:\n{}", tree);
|
println!("Value read from file:\n{}", tree);
|
||||||
}
|
}
|
||||||
Ok(_) => println!("{} is not a valid directory!", directory),
|
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 bracket;
|
||||||
mod file_linked;
|
mod file_linked;
|
||||||
|
mod tree;
|
||||||
|
|
|
@ -18,12 +18,8 @@ fn test_new() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fmt() {
|
fn test_fmt() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!(
|
format!("{}", btree!("foo", btree!("bar"),),),
|
||||||
"{}",
|
|
||||||
btree!("foo", btree!("bar"),),
|
|
||||||
),
|
|
||||||
"val = \"foo\"\n\n[left]\nval = \"bar\"\n"
|
"val = \"foo\"\n\n[left]\nval = \"bar\"\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -31,10 +27,7 @@ fn test_fmt() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fmt_node() {
|
fn test_fmt_node() {
|
||||||
let t = btree!(17, btree!(16), btree!(12));
|
let t = btree!(17, btree!(16), btree!(12));
|
||||||
assert_eq!(
|
assert_eq!(Tree::fmt_node(&t.left), "16");
|
||||||
Tree::fmt_node(&t.left),
|
|
||||||
"16"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Tree::fmt_node(&Some(Box::new(btree!(btree!("foo"))))),
|
Tree::fmt_node(&Some(Box::new(btree!(btree!("foo"))))),
|
||||||
"val = \"foo\"\n"
|
"val = \"foo\"\n"
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
/// An unbalanced binary tree type where each node has an optional left and right child.
|
/// 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_export]
|
||||||
macro_rules! btree {
|
macro_rules! btree {
|
||||||
($val:expr, $l:expr, $r:expr) => {
|
($val:expr, $l:expr, $r:expr) => {
|
||||||
$crate::tree::Tree::new(
|
$crate::tree::Tree::new($val, Some(Box::new($l)), Some(Box::new($r)))
|
||||||
$val,
|
};
|
||||||
Some(Box::new($l)),
|
($val:expr, , $r:expr) => {
|
||||||
Some(Box::new($r))
|
$crate::tree::Tree::new($val, None, Some(Box::new($r)))
|
||||||
) };
|
};
|
||||||
($val:expr, , $r:expr) => { $crate::tree::Tree::new($val, None, Some(Box::new($r))) };
|
($val:expr, $l:expr,) => {
|
||||||
($val:expr, $l:expr,) => { $crate::tree::Tree::new($val, Some(Box::new($l)), None) };
|
$crate::tree::Tree::new($val, Some(Box::new($l)), None)
|
||||||
($val:expr) => { Tree::new($val, None, None) };
|
};
|
||||||
|
($val:expr) => {
|
||||||
|
Tree::new($val, None, None)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Tree<T> {
|
impl<T> Tree<T> {
|
||||||
|
@ -96,7 +99,6 @@ impl<T> Tree<T> {
|
||||||
where
|
where
|
||||||
T: fmt::Display,
|
T: fmt::Display,
|
||||||
{
|
{
|
||||||
|
|
||||||
match t {
|
match t {
|
||||||
Some(n) => format!("{}", (*n).val),
|
Some(n) => format!("{}", (*n).val),
|
||||||
_ => String::from("_"),
|
_ => 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 {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let result = toml::to_string(self);
|
let result = toml::to_string(self);
|
||||||
|
|
||||||
match result
|
match result {
|
||||||
{
|
|
||||||
Ok(string) => write!(f, "{}", string),
|
Ok(string) => write!(f, "{}", string),
|
||||||
Err(_) => Err(std::fmt::Error),
|
Err(_) => Err(std::fmt::Error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<T> FromStr for Tree<T>
|
impl<T> FromStr for Tree<T>
|
||||||
where T: FromStr + DeserializeOwned
|
where
|
||||||
|
T: FromStr + DeserializeOwned,
|
||||||
{
|
{
|
||||||
type Err = String;
|
type Err = String;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err>
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
{
|
toml::from_str(s).map_err(|_| format!("Unable to parse string {}", s))
|
||||||
toml::from_str(s).or_else(|_| {Err(format!("Unable to parse string {}", s))})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue