Skip to content

Commit 648f4a7

Browse files
committed
feat: storage trait
- storage trait - json storage implementation
1 parent 044fe98 commit 648f4a7

File tree

6 files changed

+220
-95
lines changed

6 files changed

+220
-95
lines changed

src/actions.rs

Lines changed: 38 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,40 @@
1-
use std::fs::File;
2-
use std::io::Write;
31
use std::path::Path;
42

5-
use json::JsonValue;
63
use seahorse::{ActionError, ActionResult, Context};
74

85
use crate::config::get_config_path;
96
use crate::error::invalid;
10-
use crate::json_object::{get_json_object_or_create, set_json_object};
7+
use crate::storage::json::CfsJSONStore;
8+
use crate::storage::{CfsStorage, CfsValue};
119

12-
pub fn init_action(c: &Context) -> ActionResult {
10+
pub fn init_action(_c: &Context) -> ActionResult {
1311
let config_path = get_config_path();
1412
let path = Path::new(&config_path);
1513

1614
if path.exists() {
1715
println!("config file already exists");
18-
} else {
19-
clear_action(c)?;
2016
}
2117

18+
CfsJSONStore::with_force_create(true);
19+
2220
Ok(())
2321
}
2422

2523
pub fn list_action(c: &Context) -> ActionResult {
26-
let conf = get_json_object_or_create(c.bool_flag("force-create"));
24+
let store = CfsJSONStore::with_force_create(c.bool_flag("force-create"));
2725

28-
for (key, value) in conf.entries() {
26+
for (key, value) in store.all().iter() {
2927
println!("{}\t{}", key, value);
3028
}
3129

3230
Ok(())
3331
}
3432

3533
pub fn clear_action(_c: &Context) -> ActionResult {
36-
let mut file = File::create(get_config_path()).unwrap();
34+
let mut store = CfsJSONStore::new();
35+
36+
store.clear();
3737

38-
write!(file, "{}", "{}").expect("couldn't overwrite config file");
3938
println!("cleared config file at '{:?}'", get_config_path());
4039

4140
Ok(())
@@ -46,24 +45,29 @@ pub fn get_action(c: &Context) -> ActionResult {
4645
return Err(invalid("command"));
4746
}
4847

49-
let conf = get_json_object_or_create(c.bool_flag("force-create"));
50-
let key = c.args.get(0);
48+
let key = c.args.get(0).to_owned();
5149

5250
let Some(key) = key else {
5351
return Err(invalid("key"));
5452
};
5553

56-
if conf.has_key(&key) {
57-
println!("{}", conf[key]);
58-
return Ok(());
59-
}
60-
61-
if c.bool_flag("ignore-null") {
62-
println!();
63-
} else {
64-
return Err(ActionError {
65-
message: format!("could not find key '{}'", key),
66-
});
54+
let store = CfsJSONStore::new();
55+
56+
let value = store.get(key);
57+
58+
match value {
59+
Some(v) => {
60+
println!("{}", v)
61+
}
62+
None => {
63+
if c.bool_flag("ignore_null") {
64+
println!();
65+
} else {
66+
return Err(ActionError {
67+
message: format!("could not find key '{}'", key),
68+
});
69+
}
70+
}
6771
}
6872

6973
Ok(())
@@ -74,8 +78,6 @@ pub fn set_action(c: &Context) -> ActionResult {
7478
return Err(invalid("command"));
7579
}
7680

77-
let mut conf = get_json_object_or_create(c.bool_flag("force-create"));
78-
7981
let Some(key) = c.args.get(0) else {
8082
return Err(invalid("key"));
8183
};
@@ -84,39 +86,28 @@ pub fn set_action(c: &Context) -> ActionResult {
8486
return Err(invalid("value"));
8587
};
8688

87-
let json_value = JsonValue::from(value_str.as_str());
88-
let value = json_value.as_str().unwrap();
89+
let mut store = CfsJSONStore::new();
8990

90-
if conf.has_key(key) {
91-
conf.remove(key);
92-
}
93-
94-
conf.insert(key, value).unwrap();
91+
let value = CfsValue::Value(value_str.to_owned());
92+
store.set(key, value.clone());
9593

96-
match set_json_object(conf) {
97-
Ok(_) => println!("'{}' -> '{}'", key, value),
98-
Err(err) => eprintln!("{}", err),
99-
}
94+
println!("{}\t{}", key, value);
10095

10196
Ok(())
10297
}
10398

10499
pub fn remove_action(c: &Context) -> ActionResult {
105-
let mut conf = get_json_object_or_create(c.bool_flag("force-create"));
106100
let Some(key) = c.args.get(0) else {
107101
return Err(invalid("key"));
108102
};
109103

110-
if !conf.has_key(&key) {
111-
println!("key '{}' was not found", key);
112-
return Ok(());
113-
}
114-
115-
conf.remove(&key);
104+
let mut store = CfsJSONStore::new();
116105

117-
match set_json_object(conf) {
118-
Ok(_) => println!("updated config file"),
119-
Err(err) => eprintln!("{}", err),
106+
match store.remove(key) {
107+
Some(value) => println!("{}\t{}", key, value),
108+
None => {
109+
println!("key '{}' was not found", key);
110+
}
120111
}
121112

122113
Ok(())

src/json_object.rs

Lines changed: 0 additions & 45 deletions
This file was deleted.

src/main.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mod commands;
99
mod config;
1010
mod error;
1111
mod flags;
12-
mod json_object;
12+
mod storage;
1313

1414
fn main() -> ActionResult {
1515
let args: Vec<String> = env::args().collect();
@@ -26,10 +26,12 @@ fn main() -> ActionResult {
2626
.command(clear());
2727

2828
match app.run_with_result(args) {
29-
Ok(_) => Ok(()),
29+
Ok(_) => (),
3030
Err(action_error) => {
3131
eprintln!("{}", action_error.message);
3232
exit(1)
3333
}
34-
}
34+
};
35+
36+
Ok(())
3537
}

src/storage/json.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
use std::fs::{read_to_string, File};
2+
use std::io;
3+
use std::io::Write;
4+
use std::process::exit;
5+
6+
use json::JsonValue;
7+
8+
use crate::config::get_config_path;
9+
use crate::storage::{CfsStorage, CfsValue};
10+
11+
pub fn init_store(force_create: bool) -> JsonValue {
12+
let path = get_config_path();
13+
14+
if !path.exists() && force_create {
15+
let mut file = File::create(get_config_path()).unwrap();
16+
write!(file, "{}", "{}").unwrap();
17+
} else if !path.exists() {
18+
eprintln!("config file does not exist at '{:?}'", &path);
19+
exit(1);
20+
}
21+
22+
let json = json::parse(&read_to_string(&path).unwrap()).unwrap();
23+
24+
if !json.is_object() {
25+
eprintln!("config file is not a JSON file ('{:?}')", &path);
26+
exit(1);
27+
}
28+
29+
json
30+
}
31+
32+
#[derive(Clone, Debug)]
33+
pub struct CfsJSONStore {
34+
store: JsonValue,
35+
}
36+
37+
impl CfsJSONStore {
38+
pub fn new() -> Self {
39+
return Self {
40+
store: init_store(false),
41+
};
42+
}
43+
44+
pub fn with_force_create(force_create: bool) -> Self {
45+
return Self {
46+
store: init_store(force_create),
47+
};
48+
}
49+
50+
fn save_store(&mut self) -> Result<(), io::Error> {
51+
let mut file = File::create(get_config_path())?;
52+
53+
let json_string = json::stringify_pretty(self.store.clone(), 2);
54+
55+
write!(file, "{}", json_string)?;
56+
57+
Ok(())
58+
}
59+
}
60+
61+
impl CfsStorage for CfsJSONStore {
62+
fn all(&self) -> Vec<(String, CfsValue)> {
63+
self
64+
.store
65+
.entries()
66+
.map(|(key, value)| (key.to_owned(), value.into()))
67+
.collect()
68+
}
69+
70+
fn get(&self, key: &str) -> Option<CfsValue> {
71+
if !self.store.has_key(key) {
72+
return None;
73+
}
74+
75+
Some(self.store[key].clone().into())
76+
}
77+
78+
fn set(&mut self, key: &str, value: CfsValue) -> CfsValue {
79+
self.store.insert(key, value.clone()).unwrap();
80+
81+
self.save_store().unwrap();
82+
83+
value
84+
}
85+
86+
fn remove(&mut self, key: &str) -> Option<CfsValue> {
87+
if !self.store.has_key(key) {
88+
return None;
89+
}
90+
91+
let value = self.store.remove(key);
92+
93+
self.save_store().unwrap();
94+
95+
return Some(value.into());
96+
}
97+
98+
fn clear(&mut self) {
99+
self.store.clear();
100+
101+
self.save_store().unwrap();
102+
}
103+
}

src/storage/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
pub mod json;
2+
mod value;
3+
4+
pub use value::CfsValue;
5+
6+
pub trait CfsStorage {
7+
fn all(&self) -> Vec<(String, CfsValue)>;
8+
9+
fn get(&self, key: &str) -> Option<CfsValue>;
10+
fn set(&mut self, key: &str, value: CfsValue) -> CfsValue;
11+
fn remove(&mut self, key: &str) -> Option<CfsValue>;
12+
13+
fn clear(&mut self);
14+
}

0 commit comments

Comments
 (0)