use serde::{Deserialize, Serialize}; use std::collections::HashMap; use uuid::Uuid; use crate::data::PageUuid; #[cfg(feature = "ssr")] use std::{ fs, path::{Path, PathBuf}, }; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Namespace { pub page: Option, pub children: HashMap, } pub struct Namespaces { pub root: Namespace, } impl Namespace { pub fn new() -> Self { Self { page: None, children: HashMap::new(), } } } #[cfg(feature = "ssr")] impl Namespaces { pub fn init(namespaces_dir: &Path) -> Result { // Read dir recursive let mut paths = Vec::new(); Self::scan_dir(namespaces_dir, &mut paths); let paths = paths .into_iter() .map(|path| PathBuf::from(path.strip_prefix(namespaces_dir).unwrap())) .collect::>(); // Build lookup let mut root = Namespace::new(); for path in paths { let mut current_node = &mut root; for segment in path.iter() { let segment = segment.to_string_lossy().to_string(); if segment == "_page" { let link_target = namespaces_dir.join(&path).read_link().unwrap(); let uuid_string = link_target.file_name().unwrap().to_str().unwrap(); let page_uuid = PageUuid(Uuid::try_parse(uuid_string).unwrap()); current_node.page = Some(page_uuid); } else { current_node .children .insert(segment.clone(), Namespace::new()); current_node = current_node.children.get_mut(&segment).unwrap(); } } } Ok(Self { root }) } pub fn get_page_uuid(&self, path: String) -> Option { todo!() } pub fn remove_page(&self, path: String) -> Result<(), String> { todo!() } pub fn add_page(&self, path: String, uuid: PageUuid) -> Result<(), String> { todo!() } fn scan_dir(current_dir: &Path, out_vec: &mut Vec) { if !current_dir.is_dir() { return; } for entry in fs::read_dir(current_dir).unwrap() { let entry_path = entry.unwrap().path(); if entry_path.is_dir() && !entry_path.is_symlink() { Self::scan_dir(&entry_path, out_vec); } else { out_vec.push(entry_path.into()); } } } }