use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
use std::fs;
use std::io;
#[allow(dead_code)]
pub struct Connection {
uri: String,
}
impl Connection {
pub fn new(uri: &str) -> Result<Self, io::Error> {
let _ = fs::create_dir_all(&uri)?;
Ok(Self {
uri: uri.to_string(),
})
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Model<T> {
name: String,
data: Vec<T>,
ty: PhantomData<T>,
uri: String,
}
impl<T: Serialize + for<'a> Deserialize<'a>> Model<T> {
pub fn new(name: &str, connection: &Connection) -> Self {
Self {
name: name.to_string(),
data: Vec::new(),
ty: PhantomData::<T>,
uri: connection.uri.to_string(),
}
}
fn get_path(&self) -> String {
format!("{}/{}.jsnbase", &self.uri, &self.name)
}
pub fn load(&mut self) {
if let Ok(contents) = std::fs::read_to_string(&self.get_path()) {
if let Ok(prased_contents) = serde_json::from_str::<Model<T>>(&contents) {
self.data = prased_contents.data;
};
}
}
pub fn save(&self) {
let contents = serde_json::to_string(&self).unwrap();
let _ = std::fs::write(&self.get_path(), &contents);
}
pub fn create(&mut self, payload: T) -> Option<&T> {
self.data.push(payload);
self.data.get(self.data.len() - 1)
}
pub fn creates(&mut self, payloads: Vec<T>) -> () {
payloads.into_iter().for_each(|item| {
self.create(item);
});
}
pub fn get(&self, condition: impl Fn(&T) -> bool) -> Option<&T> {
self.data.iter().find(|item| condition(*item))
}
pub fn gets(&self, condition: impl Fn(&T) -> bool) -> Vec<&T> {
self.data.iter().filter(|item| condition(*item)).collect()
}
pub fn remove(&mut self, condition: impl Fn(&T) -> bool) -> Option<T> {
match self.data.iter().position(|item| condition(item)) {
Some(index) => Some(self.data.remove(index)),
_ => None,
}
}
pub fn removes(&mut self, condition: impl Fn(&T) -> bool) {
while let Some(_) = self.remove(&condition) {
}
}
}