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