use std::collections::HashMap;
use std::error::Error;
use std::fs::{create_dir_all, DirBuilder, File};
use std::io::{prelude::*, Result};
use std::path::PathBuf;
use crate::DbId;
use rayon::prelude::*;
use serde::Serialize;
pub mod history;
#[allow(dead_code)]
pub enum SaveScope {
All,
One((&'static str, DbId)),
Some(Vec<DbId>),
Tag(&'static str),
}
pub trait Persistable {
fn get_id_str(&self) -> &str;
fn save(&self, path: &std::path::PathBuf) -> std::io::Result<()>;
}
pub(crate) fn prep_tag_directory(dir: &PathBuf) -> Result<()> {
if dir.exists() {
Ok(())
} else {
create_tag_directory(dir)
}
}
fn create_tag_directory(dir: &PathBuf) -> Result<()> {
DirBuilder::new().recursive(true).create(dir)?;
Ok(())
}
pub(crate) fn load_from_vec(
page_col: Vec<PathBuf>,
) -> std::result::Result<HashMap<[u8; 16], crate::ephemeral::Page>, Box<dyn std::error::Error>> {
Ok(page_col
.par_iter()
.filter_map(|path_buf| match File::open(&path_buf) {
Ok(file) => Some(file),
Err(e) => {
error!("Error: {:?}", e);
None
}
})
.map(|file| {
let mut buffer = Vec::new();
let mut file = file;
match file.read_to_end(&mut buffer) {
Ok(g) => g,
Err(e) => {
panic!("Failed reading file: {:?}", e);
}
};
let mut page: crate::ephemeral::Page = match bincode::deserialize(&buffer) {
Ok(page) => page,
Err(e) => panic!(format!("{:?}", e)),
};
buffer.clear();
let id: [u8; 16] = page.get_id();
page.build_index();
(id, page)
})
.collect())
}
pub fn persist<T: Serialize + Persistable + Clone>(
item: &T,
path: &std::path::PathBuf,
) -> std::io::Result<()> {
let page_vec = match bincode::serialize(&item) {
Ok(p) => p,
Err(e) => panic!(
"Failed to serialize: {}, error: {}",
item.get_id_str(),
e.description()
),
};
crate::persistence::write(page_vec, item.get_id_str(), path)
}
pub(crate) fn write(item: Vec<u8>, id: &str, path: &std::path::PathBuf) -> Result<()> {
let mut file_path = path.to_path_buf();
if !file_path.exists() {
create_dir_all(path)?;
}
file_path.push(id);
let mut file = match File::create(file_path) {
Ok(f) => f,
Err(e) => {
error!("Error: {:?}", e);
unimplemented!()
}
};
match file.write_all(&item) {
Ok(_) => (),
Err(e) => {
error!("Failed to write file to disk: {}", e);
unimplemented!()
}
}
match file.sync_all() {
Ok(_) => Ok(()),
Err(e) => {
warn!(" ** Failed to write to disk: {:?}", e);
unimplemented!()
}
}
}