use std::fs::*;
use std::io::{self, Read, Write};
use std::path::{Path, PathBuf};
use std::fs;
use std::env;
use log::error;
const ROOT_DIR: &str = "Alice-Database-Data";
const ADB_DATA_DIR: &str = "ADB_Data";
const LOG_ENGINE_DIR: &str = "log_engine";
#[derive(Debug, Clone)]
pub struct Document {
pub name: String,
pub path: PathBuf,
pub data: String,
}
#[derive(Debug, Clone)]
pub struct Collection {
pub name: String,
pub documents: Vec<Document>,
}
impl Collection {
pub fn get_document(&self, name: &str) -> Option<&Document> {
self.documents.iter().find(|doc| doc.name == name)
}
pub fn get_document_mut(&mut self, name: &str) -> Option<&mut Document> {
self.documents.iter_mut().find(|doc| doc.name == name)
}
pub fn add_document(&mut self, name: &str, content: &str) -> io::Result<()> {
let collection_path = Path::new(&self.path()).join(&self.name);
fs::create_dir_all(&collection_path)?;
let doc_path = collection_path.join(&name.clone());
let mut file = fs::File::create(&doc_path)?;
file.write_all(content.as_bytes())?;
let new_document = Document {
name: name.to_string(),
path: doc_path.clone(),
data: content.to_string(),
};
self.documents.push(new_document);
Ok(())
}
pub fn delete_document(&mut self, name: &str) -> io::Result<()> {
if let Some(doc) = self.documents.iter().find(|doc| doc.name == name) {
fs::remove_file(&doc.path)?;
self.documents.retain(|doc| doc.name != name);
Ok(())
} else {
Err(io::Error::new(io::ErrorKind::NotFound, "Document not found"))
}
}
fn path(&self) -> PathBuf {
let home_dir = env::home_dir().expect("Failed to get home directory");
home_dir.join(ROOT_DIR).join(ADB_DATA_DIR).join(LOG_ENGINE_DIR)
}
}
#[derive(Debug, Clone)]
pub struct LOGEngine {
pub collections: Vec<Collection>,
}
impl LOGEngine {
pub fn new(root: &Path, ) -> Self {
let collections = get_exists_collections(root);
LOGEngine { collections }
}
pub fn get_collection_mut(&mut self, name: &str) -> Option<&mut Collection> {
self.collections.iter_mut().find(|col| col.name == name)
}
pub fn add_collection(&mut self, name: &str) -> Option<&mut Collection> {
let collection_path = Path::new(&self.root_path()).join(name);
fs::create_dir_all(&collection_path).ok()?;
let new_collection = Collection {
name: name.to_string(),
documents: vec![],
};
self.collections.push(new_collection);
self.collections.last_mut() }
pub fn get_collection(&self, name: &str) -> Option<&Collection> {
self.collections.iter().find(|col| col.name == name)
}
pub fn get_document(&self, collection_name: &str, document_name: &str) -> Option<&Document> {
self.get_collection(collection_name)?.get_document(document_name)
}
fn root_path(&self) -> PathBuf {
let home_dir = env::home_dir().expect("Failed to get home directory");
home_dir.join(ROOT_DIR).join(ADB_DATA_DIR).join(LOG_ENGINE_DIR)
}
}
fn get_documents_in_collection(path: &Path) -> Vec<Document> {
let entries = fs::read_dir(path).unwrap();
let mut documents: Vec<Document> = vec![];
for entry in entries {
let entry = entry.unwrap();
let entry_path = entry.path();
if entry_path.is_file() {
let name = entry_path.file_name().unwrap().to_string_lossy().into_owned();
let data = read_file_data(&entry_path).unwrap_or_default();
let document = Document {
name,
path: entry_path.clone(),
data,
};
documents.push(document);
}
}
documents
}
fn read_file_data(path: &Path) -> io::Result<String> {
let mut file = fs::File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
fn get_exists_collections(path: &Path) -> Vec<Collection> {
let mut collections: Vec<Collection> = vec![];
if path.exists() && path.is_dir() {
let entries = fs::read_dir(path).unwrap();
for entry in entries {
let entry = entry.unwrap();
let entry_path = entry.path();
if entry_path.is_dir() {
let documents = get_documents_in_collection(&entry_path);
let collection_name = entry_path.file_name().unwrap().to_string_lossy().into_owned();
let collection = Collection {
name: collection_name,
documents,
};
collections.push(collection);
}
}
} else {
error!("The specified path does not exist or is not a directory: {:?}", path);
}
collections
}