Compare commits
2 Commits
ad889622d5
...
982dac721f
Author | SHA1 | Date | |
---|---|---|---|
982dac721f | |||
df71a1f787 |
194
src/esh/mod.rs
194
src/esh/mod.rs
@ -1,194 +0,0 @@
|
||||
use std::borrow::BorrowMut;
|
||||
use std::cell::RefCell;
|
||||
use std::num::ParseIntError;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
use itertools::Itertools;
|
||||
use lazy_static::lazy_static;
|
||||
use regex::{Captures, Match, Regex};
|
||||
use crate::esh::ExecutionError::DirectoryNotFoundError;
|
||||
|
||||
pub enum ExecutionError {
|
||||
ParseError(CommandError),
|
||||
DirectoryNotFoundError(String),
|
||||
InvalidFileSize(ParseIntError)
|
||||
}
|
||||
|
||||
impl From<CommandError> for ExecutionError {
|
||||
fn from(e: CommandError) -> Self {
|
||||
Self::ParseError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for ExecutionError {
|
||||
fn from(e: ParseIntError) -> Self {
|
||||
Self::InvalidFileSize(e)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum CommandError {
|
||||
UnknownCommand,
|
||||
ArgumentError,
|
||||
}
|
||||
|
||||
pub enum Command {
|
||||
Ls,
|
||||
CdParent,
|
||||
CdRoot,
|
||||
Cd(String),
|
||||
}
|
||||
|
||||
impl TryFrom<Captures<'_>> for Command {
|
||||
type Error = CommandError;
|
||||
|
||||
fn try_from(s: Captures) -> Result<Self, Self::Error> {
|
||||
match s.name("cmd") {
|
||||
Some(c) if c.as_str() == "ls" => Ok(Command::Ls),
|
||||
Some(c) if c.as_str() == "cd" => match s.name("arg") {
|
||||
None => Err(CommandError::ArgumentError),
|
||||
Some(c) if c.as_str() == "/" => Ok(Command::CdRoot),
|
||||
Some(c) if c.as_str() == ".." => Ok(Command::CdParent),
|
||||
Some(c) => Ok(Command::Cd(c.as_str().into())),
|
||||
},
|
||||
_ => Err(CommandError::UnknownCommand)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Esh<'a> {
|
||||
pub working_directory2: &'a Directory,
|
||||
pub working_directory: RefCell<Directory>,
|
||||
pub total_disk_space: usize
|
||||
}
|
||||
|
||||
impl<'a> Esh<'a> {
|
||||
pub fn execute(&mut self, line: &str) -> Result<(), ExecutionError> {
|
||||
lazy_static! {
|
||||
static ref COMMAND_REGEX: Regex = Regex::new(r"\$ (?P<cmd>\w+)( (?P<arg>[\w\.]+))?")
|
||||
.unwrap();
|
||||
static ref FILE_REGEX: Regex = Regex::new(r"(?P<size>\d+) (?P<name>[\w\.]+)")
|
||||
.unwrap();
|
||||
}
|
||||
if let Some(captures) = COMMAND_REGEX.captures(line) {
|
||||
let command = captures.try_into()?;
|
||||
self.execute_command(command)?;
|
||||
} else if let Some(captures) = FILE_REGEX.captures(line) {
|
||||
let size = captures.name("size").unwrap().as_str().parse()?;
|
||||
let file = DirectoryEntry::File {
|
||||
size,
|
||||
name: captures.name("name").unwrap().as_str().into()
|
||||
};
|
||||
//self.working_directory.entries.push(file);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_command(&mut self, command: Command) -> Result<(), ExecutionError> {
|
||||
match command {
|
||||
Command::Ls => Ok(()),
|
||||
Command::CdRoot => {
|
||||
|
||||
while let Some(wd) = &self.working_directory.borrow().parent {
|
||||
self.working_directory.replace(wd.into_inner());
|
||||
}/*
|
||||
while let Some(wd) = &self.working_directory.into_inner().parent {
|
||||
self.working_directory = wd;
|
||||
}*/
|
||||
Ok(())
|
||||
},
|
||||
Command::CdParent => {
|
||||
/*
|
||||
if let Some(wd) = &self.working_directory.parent {
|
||||
self.working_directory = wd;
|
||||
Ok(())
|
||||
}*/
|
||||
if let Some(wd) = &self.working_directory.borrow().parent {
|
||||
self.working_directory.replace(wd.into_inner());
|
||||
Ok(())
|
||||
} else {
|
||||
Err(DirectoryNotFoundError(
|
||||
format!("{}/../", self.working_directory.borrow().name)
|
||||
))
|
||||
}
|
||||
},
|
||||
Command::Cd(dir) => {
|
||||
if let Some(child) = self.working_directory.into_inner().subfolder(&dir) {
|
||||
//self.working_directory = RefCell::from()
|
||||
todo!();
|
||||
Ok(())
|
||||
} else {
|
||||
Err(DirectoryNotFoundError(
|
||||
format!("{}/{}/", self.working_directory.name, dir)
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
impl<'a> Default for Esh<'a> {
|
||||
fn default() -> Self {
|
||||
let d: &'static Directory = &Directory::root();
|
||||
Esh {
|
||||
working_directory: d,
|
||||
total_disk_space: 70000000
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
pub enum DirectoryEntry {
|
||||
File { size: usize, name: String },
|
||||
Directory(Directory)
|
||||
}
|
||||
|
||||
pub struct Directory {
|
||||
name: String,
|
||||
entries: Vec<DirectoryEntry>,
|
||||
parent: Option<Rc<RefCell<Directory>>>
|
||||
}
|
||||
|
||||
impl Directory {
|
||||
pub fn size(&self) -> usize {
|
||||
self.entries.iter().map(|e|e.size()).sum()
|
||||
}
|
||||
|
||||
pub fn root() -> Self {
|
||||
Self {
|
||||
name: "/".into(),
|
||||
entries: vec![],
|
||||
parent: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn subfolder(&self, dir: &str) -> Option<&Directory> {
|
||||
self.entries
|
||||
.iter()
|
||||
.flat_map(|e| {
|
||||
match e {
|
||||
DirectoryEntry::Directory(d) if d.name == dir => Some(d),
|
||||
_ => None
|
||||
}
|
||||
})
|
||||
.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Directory {
|
||||
fn default() -> Self { Directory::root() }
|
||||
}
|
||||
|
||||
impl DirectoryEntry {
|
||||
pub fn size(&self) -> usize {
|
||||
match self {
|
||||
DirectoryEntry::File { size, name } => *size,
|
||||
DirectoryEntry::Directory(d) => d.size()
|
||||
}
|
||||
}
|
||||
pub fn name(&self) -> String {
|
||||
match &self {
|
||||
DirectoryEntry::File { size, name } => name.into(),
|
||||
DirectoryEntry::Directory(d) => (*d.name).into()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user