Update file/dir structure to be more robust
parent
d363bbfc1a
commit
6acc77e52e
@ -0,0 +1,177 @@
|
||||
pub struct Permissions {
|
||||
pub can_read: bool,
|
||||
pub can_write: bool,
|
||||
pub can_exec: bool
|
||||
}
|
||||
|
||||
pub struct DirEntry {
|
||||
pub name: &'static str,
|
||||
pub permissions: Permissions,
|
||||
pub item: DirEntryContents
|
||||
}
|
||||
|
||||
pub enum DirEntryContents {
|
||||
Directory(Directory),
|
||||
File(File)
|
||||
}
|
||||
|
||||
pub struct Directory {
|
||||
entries : Vec<DirEntry>
|
||||
}
|
||||
|
||||
pub struct File {
|
||||
pub contents: &'static str
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirError {
|
||||
pub filename: String
|
||||
}
|
||||
|
||||
impl Directory {
|
||||
pub fn get_entry_by_name(&self, name : &str) -> Result<&DirEntry, DirError> {
|
||||
for entry in self.entries.iter() {
|
||||
if entry.name == name {
|
||||
return Ok(entry)
|
||||
}
|
||||
}
|
||||
|
||||
return Err(DirError {
|
||||
filename: name.to_string()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_entry_by_path(&self, path : &str) -> Result<&DirEntry, DirError> {
|
||||
let mut segments = path.split("/").filter(|s| !s.is_empty());
|
||||
let first_seg = segments.next().expect("Path has no segments!");
|
||||
let remaining_path = segments.fold(String::new(), |mut a, b| {
|
||||
a.reserve(b.len() + 1);
|
||||
a.push_str("/");
|
||||
a.push_str(b);
|
||||
a
|
||||
});
|
||||
|
||||
console_log!("In dir, getting {}. first_seg: {}. remaining: {}", path, first_seg, remaining_path);
|
||||
|
||||
let entry = self.get_entry_by_name(first_seg)?;
|
||||
|
||||
if remaining_path.is_empty() {
|
||||
console_log!("Found entry! {}", entry.name);
|
||||
return Ok(entry);
|
||||
} else if entry.is_dir() {
|
||||
console_log!("Found dir: {}", entry.name);
|
||||
return entry.as_dir().unwrap().get_entry_by_path(remaining_path.as_str())
|
||||
} else {
|
||||
console_log!("Error accessing: {}", first_seg);
|
||||
return Err(DirError {
|
||||
filename: first_seg.to_string()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_entries(&self) -> impl Iterator<Item = &DirEntry> {
|
||||
self.entries.iter()
|
||||
}
|
||||
|
||||
pub fn get_dirs(&self) -> impl Iterator<Item = &DirEntry> {
|
||||
self.entries.iter().filter(|item| item.is_dir())
|
||||
}
|
||||
|
||||
pub fn get_files(&self) -> impl Iterator<Item = &DirEntry> {
|
||||
self.entries.iter().filter(|item| item.is_file())
|
||||
}
|
||||
}
|
||||
|
||||
impl DirEntry {
|
||||
pub fn create_dir(name: &'static str, perms: bool) -> DirEntry {
|
||||
DirEntry {
|
||||
name,
|
||||
permissions: Permissions {
|
||||
can_read: perms,
|
||||
can_write: perms,
|
||||
can_exec: perms
|
||||
},
|
||||
item: DirEntryContents::Directory(Directory {
|
||||
entries: Vec::new()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_file(name: &'static str, perms: bool, contents: &'static str) -> DirEntry {
|
||||
DirEntry {
|
||||
name,
|
||||
permissions: Permissions {
|
||||
can_read: perms,
|
||||
can_write: perms,
|
||||
can_exec: perms
|
||||
},
|
||||
item: DirEntryContents::File(File {
|
||||
contents
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_file(&self) -> bool {
|
||||
if let DirEntryContents::File(file) = &self.item {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
pub fn is_dir(&self) -> bool {
|
||||
!self.is_file()
|
||||
}
|
||||
|
||||
pub fn as_dir(&self) -> Option<&Directory> {
|
||||
if let DirEntryContents::Directory(dir) = &self.item {
|
||||
return Some(dir)
|
||||
}
|
||||
return None
|
||||
}
|
||||
|
||||
pub fn as_file(&self) -> Option<&File> {
|
||||
if let DirEntryContents::File(file) = &self.item {
|
||||
return Some(file)
|
||||
}
|
||||
return None
|
||||
}
|
||||
|
||||
pub fn get_entry_by_path(&self, path : &str) -> Result<&DirEntry, DirError> {
|
||||
console_log!("In entry, getting {}", path);
|
||||
|
||||
if path == "/" || path.is_empty() {
|
||||
return Ok(self)
|
||||
}
|
||||
|
||||
self.as_dir().expect("Cannot get entries of file").get_entry_by_path(path)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_fs() -> DirEntry {
|
||||
let mut root = DirEntry::create_dir("root", false);
|
||||
let mut home = DirEntry::create_dir("home", false);
|
||||
let mut ashe = DirEntry::create_dir("ashe", true);
|
||||
let mut projects = DirEntry::create_dir("projects", true);
|
||||
|
||||
if let DirEntryContents::Directory(ref mut dir) = projects.item {
|
||||
dir.entries.push(DirEntry::create_file("~ashe", true, include_str!("../res/~ashe.md")));
|
||||
dir.entries.push(DirEntry::create_file("ashe.gay", true, include_str!("../res/ashe.gay.md")));
|
||||
dir.entries.push(DirEntry::create_file("tempest.dev", true, include_str!("../res/tempest.dev.md")));
|
||||
}
|
||||
|
||||
if let DirEntryContents::Directory(ref mut dir) = ashe.item {
|
||||
dir.entries.push(DirEntry::create_file("about.md", true, include_str!("../res/about.md")));
|
||||
dir.entries.push(DirEntry::create_file("contact.md", true, include_str!("../res/contact.md")));
|
||||
dir.entries.push(projects)
|
||||
}
|
||||
|
||||
if let DirEntryContents::Directory(ref mut dir) = home.item {
|
||||
dir.entries.push(ashe)
|
||||
}
|
||||
|
||||
if let DirEntryContents::Directory(ref mut dir) = root.item {
|
||||
dir.entries.push(home);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
pub fn join(root : &str, path : &str) -> String {
|
||||
if path.starts_with("/") {
|
||||
return String::from_str(path).unwrap()
|
||||
}
|
||||
|
||||
let mut result_segments : Vec<&str> = root.split("/").filter(|s| !s.is_empty()).collect();
|
||||
let path_segments = path.split("/").filter(|s| !s.is_empty());
|
||||
|
||||
for segment in path_segments {
|
||||
if segment == "." {
|
||||
continue
|
||||
}
|
||||
|
||||
if segment == ".." {
|
||||
if result_segments.len() > 0 {
|
||||
result_segments.pop();
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
result_segments.push(segment)
|
||||
}
|
||||
|
||||
let result_path = result_segments.iter().fold(String::new(), |mut a, b| {
|
||||
a.reserve(b.len() + 1);
|
||||
a.push_str("/");
|
||||
a.push_str(b);
|
||||
a
|
||||
});
|
||||
|
||||
return result_path
|
||||
}
|
Loading…
Reference in New Issue