#![forbid(unsafe_code, future_incompatible, rust_2018_idioms)]
#![deny(missing_debug_implementations, nonstandard_style)]
#![warn(missing_docs, missing_doc_code_examples, unreachable_pub)]
use serde_json::Value;
use std::collections::HashMap;
use std::fs;
use std::io::Error;
use std::path::PathBuf;
use tempfile::NamedTempFile;
#[derive(Debug)]
pub struct Toiletdb {
path: PathBuf,
state: HashMap<String, Value>,
}
impl Toiletdb {
pub fn new<P: Into<PathBuf>>(path: P) -> Result<Self, Error> {
let path = path.into();
Ok(Self {
path,
state: HashMap::new(),
})
}
pub fn write<K, V>(&mut self, key: K, value: V) -> Result<(), Error>
where
K: Into<String>,
V: serde::Serialize,
{
self.state.insert(key.into(), serde_json::to_value(value)?);
write_file(&self.path, &self.state)?;
Ok(())
}
pub fn read(&mut self) -> Result<String, Error> {
let json = fs::read_to_string(&self.path)?;
Ok(json)
}
pub fn read_key<K: Into<String>>(&mut self, key: K) -> Option<&Value> {
let value = self.state.get(&key.into());
value
}
pub fn delete<K: Into<String>>(&mut self, key: K) -> Result<String, Error> {
self.state.remove(&key.into());
write_file(&self.path, &self.state)?;
let json = fs::read_to_string(&self.path)?;
Ok(json)
}
pub fn flush(&mut self) -> Result<(), Error> {
self.state = HashMap::new();
fs::remove_file(&self.path)?;
Ok(())
}
}
fn write_file<V: serde::Serialize>(path: &PathBuf, state: V) -> Result<(), Error> {
let tmpfile = NamedTempFile::new()?;
serde_json::to_writer_pretty(&tmpfile, &state)?;
tmpfile.persist(&path)?;
Ok(())
}