pub static HOBBIT_STORAGE: &str = "/var/tmp/hdb/";
macro_rules! unwrap_or_return {
( $e:expr ) => {
match $e {
Ok(x) => x,
Err(e) => return Err(e.to_string()),
}
};
}
macro_rules! some_or_return {
( $e:expr ) => {
match $e {
Some(x) => x.to_string(),
_ => return Err("None".to_string()),
}
};
}
fn trim_slash(s: &str) -> String {
let trim_len = match s.rfind('/') {
None => 0,
Some(i) => {
if i == s.len() - 1 {
i
} else {
i + 1
}
}
};
let trimmed = &s[..trim_len];
trimmed.to_string()
}
pub fn get(table: &str, key: &str) -> Result<String, String> {
let path = format!("{}{}", HOBBIT_STORAGE, table);
if let Ok(data) = std::fs::read_to_string(&path) {
let json: serde_json::Value = unwrap_or_return!(serde_json::from_str(&data));
return Ok(some_or_return!(json[key].as_str()));
}
let error = format!("Error reading table '{}'", table);
Err(error)
}
pub fn set(table: &str, key: &str, value: &str) -> Result<(), String> {
let _ = make(table);
let path = format!("{}{}", HOBBIT_STORAGE, table);
if let Ok(data) = std::fs::read_to_string(&path) {
let mut json: serde_json::Value = unwrap_or_return!(serde_json::from_str(&data));
json[key] = serde_json::Value::String(value.to_string());
return match std::fs::write(&path, json.to_string()) {
Ok(_) => Ok(()),
Err(e) => Err(e.to_string()),
};
}
let error = format!("Error reading table '{}'", table);
Err(error)
}
pub fn del(table: &str, key: &str) -> Result<(), String> {
let path = format!("{}{}", HOBBIT_STORAGE, table);
if let Ok(data) = std::fs::read_to_string(&path) {
let json: serde_json::Value = unwrap_or_return!(serde_json::from_str(&data));
match json {
serde_json::Value::Object(mut map) => {
map.remove(key);
if map.len() == 0 {
let _ = std::fs::remove_file(&path);
let _ = std::fs::remove_dir(trim_slash(&path));
return Ok(());
} else {
let v: serde_json::Value = map.into();
return match std::fs::write(&path, v.to_string()) {
Ok(_) => Ok(()),
Err(e) => Err(e.to_string()),
};
}
}
_ => return Err("Key not found".to_string()),
}
}
let error = format!("Error reading table '{}'", table);
Err(error)
}
fn make(table: &str) -> Result<(), String> {
let _ = std::fs::create_dir_all(HOBBIT_STORAGE);
let path = format!("{}{}", HOBBIT_STORAGE, table);
let _ = std::fs::create_dir_all(trim_slash(&path));
if !std::fs::metadata(path.to_string()).is_ok() {
let data = serde_json::json!({});
match std::fs::write(path.to_string(), data.to_string()) {
Ok(_) => return Ok(()),
Err(e) => return Err(e.to_string()),
}
}
Ok(())
}
pub fn map(table: &str) -> Result<serde_json::Map<String, serde_json::Value>, String> {
let path = format!("{}{}", HOBBIT_STORAGE, table);
if let Ok(data) = std::fs::read_to_string(&path) {
let json: serde_json::Value = unwrap_or_return!(serde_json::from_str(&data));
match json {
serde_json::Value::Object(map) => {
return Ok(map);
}
_ => return Err("Could not parse table as Map".to_string()),
}
}
let error = format!("Error reading table '{}'", table);
Err(error)
}