use crate::DaemonError;
use file_lock::{FileLock, FileOptions};
use serde_json::{from_reader, json, Value};
use std::{fs::File, io::Seek};
#[derive(Debug)]
pub struct JsonLockedState {
lock: FileLock,
json: Value,
path: String,
}
impl JsonLockedState {
pub fn new(path: &str) -> Self {
let options = FileOptions::new()
.create(true)
.read(true)
.write(true)
.truncate(false);
let lock: FileLock = FileLock::lock(path, false, options)
.unwrap_or_else(|_| panic!("Was not able to receive {path} state lock"));
let json: Value = if lock.file.metadata().unwrap().len().eq(&0) {
json!({})
} else {
from_reader(&lock.file).unwrap()
};
let filename = path.to_owned();
JsonLockedState {
lock,
json,
path: filename,
}
}
pub fn prepare(&mut self, chain_id: &str, network_id: &str, deploy_id: &str) {
let json = &mut self.json;
if json.get(network_id).is_none() {
json[network_id] = json!({});
}
if json[network_id].get(chain_id).is_none() {
json[network_id][chain_id] = json!({
deploy_id: {},
"code_ids": {}
});
}
}
pub fn state(&self) -> Value {
self.json.clone()
}
pub fn get(&self, network_id: &str, chain_id: &str) -> &Value {
&self.json[network_id][chain_id]
}
pub fn get_mut(&mut self, network_id: &str, chain_id: &str) -> &mut Value {
self.json[network_id].get_mut(chain_id).unwrap()
}
pub fn force_write(&mut self) {
self.lock.file.set_len(0).unwrap();
self.lock.file.rewind().unwrap();
serde_json::to_writer_pretty(&self.lock.file, &self.json).unwrap();
}
pub fn path(&self) -> &str {
&self.path
}
}
impl Drop for JsonLockedState {
fn drop(&mut self) {
self.force_write()
}
}
pub fn read(filename: &String) -> Result<Value, DaemonError> {
let file = File::open(filename)
.map_err(|err| DaemonError::OpenFile(filename.to_string(), err.to_string()))?;
let json: serde_json::Value = from_reader(file)?;
Ok(json)
}