diff --git a/Cargo.toml b/Cargo.toml index 0ff9dd4..0331372 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -hashbrown = "0.14" \ No newline at end of file +hashbrown = "0.14" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +zstd = "0.12.4" \ No newline at end of file diff --git a/src/encoding.rs b/src/encoding.rs new file mode 100644 index 0000000..08abbc8 --- /dev/null +++ b/src/encoding.rs @@ -0,0 +1,16 @@ +use std::io::{Read, Write}; + +use zstd::stream::{read::Decoder, write::Encoder}; + +pub fn encode(data: &str) -> Vec { + let mut encoder = Encoder::new(Vec::new(), 0).unwrap(); + encoder.write_all(data.as_bytes()).unwrap(); + encoder.finish().unwrap() +} + +pub fn decode(data: Vec) -> String { + let mut decoder = Decoder::new(data.as_slice()).unwrap(); + let mut decoded = String::new(); + decoder.read_to_string(&mut decoded).unwrap(); + decoded +} diff --git a/src/main.rs b/src/main.rs index 6ea1fac..7ae7592 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,7 @@ +use std::io::Read; + +mod encoding; + mod stores { pub mod container; pub mod db; @@ -8,11 +12,14 @@ pub mod values { } fn main() { - let mut db = stores::db::Database::new("test.db".to_string()); + let mut file = std::fs::File::open("test.bin").unwrap(); + let decoded = encoding::decode(file.bytes().map(|x| x.unwrap()).collect()); + println!("{}", decoded); + /*let mut db = stores::db::Database::new("test.db".to_string()); db.create_container("TestContainer".to_string()); let container = db.get_container("TestContainer"); if container.is_none() { panic!("Unable to get container"); - } + }*/ } diff --git a/src/stores/db.rs b/src/stores/db.rs index 8f6496e..a414ce5 100644 --- a/src/stores/db.rs +++ b/src/stores/db.rs @@ -1,10 +1,51 @@ +use std::{fs::File, io::Read, path::Path}; + use hashbrown::HashMap; -use std::{fs::File, path::Path}; -use crate::{stores::container, values::key::Key}; +use crate::encoding; use super::container::Container; +fn parse_database(data: String) -> Vec { + let mut lines = Vec::new(); + let mut block = String::new(); + let mut in_block = false; + + for line in data.lines() { + if line.starts_with("@CONTAINER") && !in_block { + in_block = true; + block = String::new(); + } else if line.starts_with("@CONTAINER") && in_block { + panic!("Invalid database file"); + } else if line.starts_with("@END") && in_block { + in_block = false; + lines.push(block.clone()); + } else if line.starts_with("@END") && !in_block { + panic!("Invalid database file"); + } else if in_block { + block.push_str(line); + block.push('\n'); + } + } + + lines +} + +fn load_containers(file: String) -> Vec> { + let parsed = { + let mut file = File::open(file).expect("Unable to open file"); + let data = encoding::decode(file.bytes().map(|x| x.unwrap()).collect()); + parse_database(data) + }; + let mut containers = Vec::new(); + + for parse in parsed { + containers.push(serde_json::from_str(&parse).unwrap()); + } + + containers +} + pub struct Database { pub filename: String, pub containers: Vec>, @@ -12,13 +53,18 @@ pub struct Database { impl Database { pub(crate) fn new(filename: String) -> Database { + let containers: Vec>; + if !Path::new(&filename).exists() { File::create(&filename).expect("Unable to Database create file"); + containers = Vec::new(); + } else { + containers = load_containers(filename.clone()); } Database { filename, - containers: Vec::new(), + containers, } }