diff --git a/src/lib.rs b/src/lib.rs index f47742b..5c0694e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,8 @@ use std::{boxed::Box, fs, io::Seek, path, vec}; -use walkdir::WalkDir; +use tree::{collect_physical_directory_children, create_kosmora_directory, create_kosmora_file}; +use walkdir::{DirEntry, WalkDir}; + +mod tree; #[derive(Debug)] pub struct KosmoraVfs { @@ -18,33 +21,33 @@ struct KosmoraPackage { inode_index: KosmoraDirectory, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum KosmoraINodeType { File(KosmoraFile), Directory(KosmoraDirectory), } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct KosmoraFileMetadata { name: String, extension: Option, size: usize, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct KosmoraFile { metadata: KosmoraFileMetadata, data: Vec, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct KosmoraDirectory { name: String, parent: Option>, children: Option>, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct KosmoraINode { inode: KosmoraINodeType, } @@ -65,56 +68,13 @@ impl KosmoraVfs { pub trait KosmoraINodeInteroperable { fn collect_directory_children(&self) -> Vec; fn to_kosmora_inode(&self) -> KosmoraINode; + fn to_kosmora_directory(&self) -> KosmoraDirectory; + fn to_kosmora_file(&self) -> KosmoraFile; } impl KosmoraINodeInteroperable for std::path::Path { fn collect_directory_children(&self) -> Vec { - if !self.is_dir() {} - dbg!(self); - - let mut inodes: Vec = vec![]; - - for entry in WalkDir::new(&self).into_iter().filter_map(|e| e.ok()) { - // println!("{}", entry.path().display()); - let inode: KosmoraINode = match entry.path().is_file() { - true => { - let file = KosmoraFile { - metadata: KosmoraFileMetadata { - name: entry.file_name().to_string_lossy().into(), - extension: None, - size: entry.path().metadata().unwrap().len() as usize, - }, - data: fs::read(entry.path()).unwrap(), - }; - KosmoraINode { - inode: KosmoraINodeType::File(file), - } - } - false => { - fn read_upwards(path: &path::Path) -> Option> { - - if let Some(parent) = path.parent() { - println!("{parent:#?}"); - return read_upwards(parent) - } else { - return None - } - } - let dir = KosmoraDirectory { - name: entry.file_name().to_string_lossy().into(), - parent: read_upwards(entry.path()), - children: None, - }; - KosmoraINode { - inode: KosmoraINodeType::Directory(dir), - } - } - }; - - inodes.push(inode); - } - - inodes + tree::collect_physical_directory_children(self) } fn to_kosmora_inode(&self) -> KosmoraINode { @@ -123,31 +83,36 @@ impl KosmoraINodeInteroperable for std::path::Path { } if self.is_dir() { - let dir = KosmoraDirectory { - name: self - .components() - .last() - .unwrap() - .as_os_str() - .to_string_lossy() - .into(), - parent: None, - children: Some(self.collect_directory_children()), - }; - return KosmoraINode { - inode: KosmoraINodeType::Directory(dir), - }; + return create_kosmora_directory(self, None, Some(collect_physical_directory_children(self))); } if self.is_file() { - let meta = self - .metadata() - .map_err(|_| panic!("Failed to get metadata")) - .ok() - .expect("Failed to get metadata"); + return create_kosmora_file(self, Some(Box::new(self.parent().unwrap().to_kosmora_directory()))); + } + + panic!("Unsupported path type"); + } - let file_metadata = KosmoraFileMetadata { - name: String::from(self.file_name().unwrap().to_str().unwrap().to_string()), + fn to_kosmora_directory(&self) -> KosmoraDirectory { + if !self.is_dir() { + panic!("Cannot convert file inode into Kosmora directory inode!"); + } + + KosmoraDirectory { + name: self.file_name().unwrap().to_string_lossy().into(), + parent: None, + children: None, + } + } + + fn to_kosmora_file(&self) -> KosmoraFile { + if !self.is_file() { + panic!("Cannot convert directory inode into Kosmora file inode!") + } + + KosmoraFile { + metadata: KosmoraFileMetadata { + name: self.file_name().unwrap().to_string_lossy().into(), extension: Some( self.file_name() .unwrap() @@ -156,20 +121,21 @@ impl KosmoraINodeInteroperable for std::path::Path { .split(".") .last() .unwrap() - .to_string(), + .into(), ), - size: meta.len() as usize, - }; - - let file = KosmoraFile { - metadata: file_metadata, - data: std::fs::read(self).unwrap(), - }; - - return KosmoraINode { - inode: KosmoraINodeType::File(file), - }; + size: self.metadata().unwrap().len() as usize, + }, + data: fs::read(self).unwrap(), + } + } +} + +impl KosmoraDirectory { + fn with_children(&self, children: Vec) -> KosmoraDirectory { + KosmoraDirectory { + name: self.name.clone(), + parent: self.parent.clone(), + children: Some(children), } - panic!("Unsupported path type"); } } diff --git a/src/tree.rs b/src/tree.rs new file mode 100644 index 0000000..68a7db8 --- /dev/null +++ b/src/tree.rs @@ -0,0 +1,77 @@ +use crate::{ + KosmoraDirectory, KosmoraFile, KosmoraFileMetadata, KosmoraINode, KosmoraINodeInteroperable, + KosmoraINodeType, +}; +use std::{boxed::Box, fs, path}; +use walkdir::{DirEntry, WalkDir}; + +fn read_upwards(path: &path::Path) -> Option> { + if let Some(parent) = path.parent() { + return read_upwards(parent); + } + + return None; +} + +pub(crate) fn collect_physical_directory_children(path: &path::Path) -> Vec { + if !path.is_dir() { + panic!("Cannot collect children of non-directory inode!"); + } + + let mut inodes: Vec = vec![]; + + for entry in WalkDir::new(path).into_iter().filter_map(|e| e.ok()) { + let inode: KosmoraINode = match entry.path().is_file() { + true => create_kosmora_file( + &entry.clone().into_path(), + Some(Box::new( + entry.path().parent().unwrap().to_kosmora_directory(), + )), + ), + false => create_kosmora_directory( + &entry.clone().into_path(), + Some(Box::new(entry.path().parent().unwrap().to_kosmora_directory())), + Some(collect_physical_directory_children(entry.path())) + ), + }; + + inodes.push(inode); + } + + inodes +} + +pub(crate) fn create_kosmora_file( + entry: &path::Path, + root: Option>, +) -> KosmoraINode { + let file = KosmoraFile { + metadata: KosmoraFileMetadata { + name: entry.file_name().unwrap().to_str().unwrap().to_string(), + extension: None, + size: entry.metadata().unwrap().len() as usize, + }, + data: fs::read(entry).unwrap(), + }; + + KosmoraINode { + inode: KosmoraINodeType::File(file), + } +} + +pub(crate) fn create_kosmora_directory( + entry: &path::Path, + root: Option>, + content: Option>, +) -> KosmoraINode { + let dir = KosmoraDirectory { + name: entry.file_name().unwrap().to_str().unwrap().to_string(), + // parent: read_upwards(entry.path()), + parent: root, + children: None, + }; + + KosmoraINode { + inode: KosmoraINodeType::Directory(dir), + } +}