use super::constants::DATA_DIRECTORY;
use serde::{Deserialize, Serialize};
use serde_json;
use std::fs::{metadata, read_dir, read_to_string, File};
use std::io::{BufReader, BufWriter, Write};
pub trait WriterStrategy<T: Serialize + for<'de> Deserialize<'de>> {
fn write_file(&self, path: &str, object: &T);
fn read_file(&self, path: &str) -> T;
}
pub struct BinaryFileWriter {}
impl<T: Serialize + for<'de> Deserialize<'de>> WriterStrategy<T> for BinaryFileWriter {
#[inline(always)]
fn write_file(&self, path: &str, object: &T) {
let obj_bytes: Vec<u8> = bincode::serialize(&object).expect("Should serialize.");
let mut file = BufWriter::new(File::create(path).expect("Should open file."));
file.write_all(&obj_bytes).expect("Should write.");
}
#[inline(always)]
fn read_file(&self, path: &str) -> T {
let file = BufReader::new(File::open(path).expect("Should open file."));
let object: T = bincode::deserialize_from(file).expect("Should deserialize.");
return object;
}
}
impl BinaryFileWriter {
#[inline(always)]
pub fn new() -> Self {
BinaryFileWriter {}
}
}
pub struct JSONFileWriter {}
impl<T: Serialize + for<'de> Deserialize<'de>> WriterStrategy<T> for JSONFileWriter {
#[inline(always)]
fn write_file(&self, path: &str, object: &T) {
let json = serde_json::to_string_pretty(&object).expect("Should serialize.");
let mut file = File::create(path).expect("Should open file.");
file.write_all(json.as_bytes()).expect("Should write.");
}
#[inline(always)]
fn read_file(&self, path: &str) -> T {
let json = read_to_string(path).expect("Should open file.");
let object: T = serde_json::from_str(&json).expect("Should deserialize.");
return object;
}
}
impl JSONFileWriter {
#[inline(always)]
pub fn new() -> Self {
JSONFileWriter {}
}
}
pub struct Writer<T> {
strategy: Box<dyn WriterStrategy<T>>,
}
impl<T: Serialize + for<'de> Deserialize<'de>> Writer<T> {
pub fn new(strategy: Box<dyn WriterStrategy<T>>) -> Self {
Writer { strategy }
}
pub fn set_strategy(&mut self, strategy: Box<dyn WriterStrategy<T>>) {
self.strategy = strategy;
}
pub fn write_file(&self, path: &str, object: &T) {
self.strategy.write_file(path, object);
}
pub fn read_file(&self, path: &str) -> T {
self.strategy.read_file(path)
}
}
pub fn build_binary_writer<T: Serialize + for<'de> Deserialize<'de>>() -> Writer<T> {
let bin_writer = BinaryFileWriter::new();
let writer = Writer::new(Box::new(bin_writer));
return writer;
}
pub fn build_json_writer<T: Serialize + for<'de> Deserialize<'de>>() -> Writer<T> {
let json_writer = JSONFileWriter::new();
let writer = Writer::new(Box::new(json_writer));
return writer;
}
fn dir_filesize(folder: &str) -> u64 {
let mut size = 0;
for entry in read_dir(folder).unwrap() {
let path = entry.unwrap().path();
if path.is_dir() {
size += dir_filesize(path.to_str().unwrap());
} else {
size += metadata(path).unwrap().len();
}
}
size
}
pub fn database_filesize() -> u64 {
dir_filesize(DATA_DIRECTORY)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn database_filesize_test() {
let size = database_filesize();
assert!(size > 1);
}
}