Skip to content

Commit

Permalink
state (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
sergey-shandar authored Oct 18, 2023
1 parent 389cf2e commit bd8a0d6
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 30 deletions.
12 changes: 9 additions & 3 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,19 @@ fn add<'a, T: Io, S: 'a + Storage>(

fn calculate_total(io: &impl Io, d: &str, extra: u64) -> io::Result<u64> {
let stdout = &mut io.stdout();
let a = io.read_dir(&("cdt0/".to_owned() + d))?;
let a = io.read_dir_type(&("cdt0/".to_owned() + d), true);
let a = match a {
Ok(a) => a,
Err(_) => return Ok(extra),
};
let an = a.len() as u64;
let mut total = 0;
let state = &mut State::new(stdout);
for (ai, ia) in a.iter().enumerate() {
let b = io.read_dir(&ia.path())?;
let b = io.read_dir_type(&ia.path(), true)?;
let bn = b.len() as u64;
for (bi, ib) in b.iter().enumerate() {
let c = io.read_dir(&ib.path())?;
let c = io.read_dir_type(&ib.path(), false)?;
for ic in c.iter() {
let d = ic.metadata()?.len();
total += d;
Expand Down Expand Up @@ -269,6 +273,8 @@ mod test {
" Hello, world!".as_bytes(),
)
.unwrap();
io.write_recursively("cdt0/roots/ab", " Hello, world!".as_bytes())
.unwrap();
run(&mut io).unwrap();
}

Expand Down
10 changes: 10 additions & 0 deletions src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{
#[allow(clippy::len_without_is_empty)]
pub trait Metadata {
fn len(&self) -> u64;
fn is_dir(&self) -> bool;
}

pub trait DirEntry {
Expand Down Expand Up @@ -66,6 +67,15 @@ pub trait Io {
}
Ok(())
}
fn read_dir_type(&self, path: &str, is_dir: bool) -> io::Result<Vec<Self::DirEntry>> {
let mut result = Vec::default();
for i in self.read_dir(path)? {
if i.metadata()?.is_dir() == is_dir {
result.push(i);
}
}
Ok(result)
}
}

#[cfg(test)]
Expand Down
3 changes: 3 additions & 0 deletions src/real_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ impl Metadata for fs::Metadata {
fn len(&self) -> u64 {
self.len()
}
fn is_dir(&self) -> bool {
self.is_dir()
}
}

impl DirEntry for fs::DirEntry {
Expand Down
85 changes: 58 additions & 27 deletions src/virtual_io.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{
cell::RefCell,
collections::{HashMap, HashSet},
collections::HashMap,
io::{self, Read, Write},
iter::once,
rc::Rc,
Expand All @@ -12,12 +12,16 @@ use crate::io::Io;
#[derive(Debug, Clone)]
pub struct Metadata {
len: u64,
is_dir: bool,
}

impl crate::io::Metadata for Metadata {
fn len(&self) -> u64 {
self.len
}
fn is_dir(&self) -> bool {
self.is_dir
}
}

#[derive(Debug, Default, Clone)]
Expand Down Expand Up @@ -47,20 +51,47 @@ impl Write for VecRef {
}
}

#[derive(Debug, Default)]
enum Entity {
#[default]
Dir,
File(VecRef),
}

impl Entity {
fn metadata(&self) -> Metadata {
match self {
Entity::Dir => Metadata {
len: 0,
is_dir: true,
},
Entity::File(x) => Metadata {
len: x.0.borrow().len() as u64,
is_dir: false,
},
}
}
}

#[derive(Debug, Default)]
pub struct FileSystem {
directory_set: HashSet<String>,
file_map: HashMap<String, VecRef>,
entity_map: HashMap<String, Entity>,
}

impl FileSystem {
pub fn check_dir(&self, path: &str) -> io::Result<()> {
if let Some(Entity::Dir) = self.entity_map.get(path) {
Ok(())
} else {
Err(not_found())
}
}
pub fn check_parent(&self, path: &str) -> io::Result<()> {
if let Some(d) = path.rfind('/').map(|i| &path[..i]) {
if !self.directory_set.contains(d) {
return Err(not_found());
}
self.check_dir(d)
} else {
Ok(())
}
Ok(())
}
}

Expand Down Expand Up @@ -156,33 +187,39 @@ impl Io for VirtualIo {
}
fn metadata(&self, path: &str) -> io::Result<Metadata> {
let fs = self.fs.borrow();
fs.file_map
fs.entity_map
.get(path)
.map(|v| Metadata {
len: v.0.borrow().len() as u64,
})
.map(Entity::metadata)
.ok_or_else(not_found)
}
fn create(&self, path: &str) -> io::Result<Self::File> {
let mut fs = self.fs.borrow_mut();
fs.check_dir(path)?;
fs.check_parent(path)?;
let vec_ref = VecRef::default();
check_path(path)?;
fs.file_map.insert(path.to_string(), vec_ref.clone());
fs.entity_map
.insert(path.to_string(), Entity::File(vec_ref.clone()));
Ok(MemFile::new(vec_ref))
}
fn create_dir(&self, path: &str) -> io::Result<()> {
let mut fs = self.fs.borrow_mut();
fs.directory_set.insert(path.to_string());
fs.entity_map.insert(path.to_string(), Entity::Dir);
Ok(())
}
fn open(&self, path: &str) -> io::Result<Self::File> {
let fs = self.fs.borrow();
fs.check_dir(path)?;
fs.check_parent(path)?;
check_path(path)?;
fs.file_map
fs.entity_map
.get(path)
.map(|v| MemFile::new(v.clone()))
.map(|v| {
if let Entity::File(x) = v {
Some(MemFile::new(x.to_owned()))
} else {
None
}
})
.flatten()
.ok_or_else(not_found)
}
fn stdout(&self) -> VecRef {
Expand All @@ -191,17 +228,11 @@ impl Io for VirtualIo {

fn read_dir(&self, path: &str) -> io::Result<Vec<DirEntry>> {
let fs = self.fs.borrow();
let d = fs.directory_set.iter().map(|d| DirEntry {
path: d.to_string(),
metadata: Metadata { len: 0 },
});
let f = fs.file_map.iter().map(|(k, v)| DirEntry {
path: k.to_owned(),
metadata: Metadata {
len: v.0.borrow().len() as u64,
},
fs.check_dir(path)?;
let i = fs.entity_map.iter().map(|(p, e)| DirEntry {
path: p.to_owned(),
metadata: e.metadata(),
});
let i = d.chain(f);
let x = i
.filter(|p| {
if let Some((a, _)) = p.path.rsplit_once('/') {
Expand Down

0 comments on commit bd8a0d6

Please sign in to comment.