Skip to content

Commit

Permalink
Rename write_dir, add mkdir, add rm, support paths (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
paulyoung authored Apr 10, 2022
1 parent 1d3236f commit 897e5a9
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 28 deletions.
8 changes: 5 additions & 3 deletions examples/fatfs/fatfs.did
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
service : {
ls : () -> (vec text) query;
write_file : (filename : text, contents : text) -> ();
read_file : (filename : text) -> (text) query;
cat : (path : text) -> (text) query;
ls : (path : text) -> (vec text) query;
mkdir : (path : text) -> ();
rm : (path : text) -> ();
write_file : (path : text, contents : text) -> ();
}
105 changes: 91 additions & 14 deletions examples/fatfs/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ type FileSystem = fatfs::FileSystem<
fatfs::LossyOemCpConverter,
>;

type Dir<'a> = fatfs::Dir<
'a,
fatfs::StdIoWrapper<icfs::StableMemory>,
icfs_fatfs::TimeProvider,
fatfs::LossyOemCpConverter,
>;

thread_local! {
// static STABLE_MEMORY: std::cell::RefCell<fscommon::BufStream<icfs::StableMemory>>
// = std::cell::RefCell::new(fscommon::BufStream::new(icfs::StableMemory::default()));
Expand Down Expand Up @@ -56,45 +63,115 @@ thread_local! {
};
}

fn open_dir_path<'a>(fs: &'a FileSystem, path: &str) -> std::io::Result<Dir<'a>> {
let root_dir = fs.root_dir();
let (base_dir_name, sub_dir_path) = path_head_tail(&path)
.map_err(|error| std::io::Error::new(std::io::ErrorKind::Other, error))?;
match (base_dir_name.as_str(), sub_dir_path.as_str()) {
(".", "") => Ok(root_dir),
(".", sub_dir_path) => root_dir
.open_dir(&sub_dir_path)
.map_err(|error| std::io::Error::new(std::io::ErrorKind::Other, error)),
_ => Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("Invalid path: {}", path.to_string()),
)),
}
}

fn path_head_tail(path: &str) -> Result<(String, String), String> {
let path_segments = path.split("/").collect::<Vec<_>>();
let head = path_segments
.first()
.ok_or(format!("Invalid path: {}", path.to_string()))?;
let tail = path_segments[1..].join("/");
Ok((head.to_string(), tail))
}

fn path_init_last(path: &str) -> Result<(String, String), String> {
let mut path_segments = path.split("/").collect::<Vec<_>>();
let last = path_segments
.pop()
.ok_or(format!("Invalid path: {}", path.to_string()))?;
let init = path_segments.join("/");
Ok((init, last.to_string()))
}

#[query]
fn cat(path: String) -> String {
FS.with(|fs| {
let fs = fs.borrow();
let (dir_path, file_name) = path_init_last(&path)
.map_err(|error| std::io::Error::new(std::io::ErrorKind::Other, error))?;
let dir = open_dir_path(&fs, &dir_path)?;
let mut file = dir.open_file(&file_name)?;
let mut buf = vec![];
file.read_to_end(&mut buf)?;
let contents = String::from_utf8(buf)
.map_err(|error| std::io::Error::new(std::io::ErrorKind::Other, error))?;
std::io::Result::Ok(contents)
})
.unwrap()
}

#[query]
fn ls() -> Vec<String> {
fn ls(path: String) -> Vec<String> {
FS.with(|fs| {
let fs = fs.borrow();
let root_dir = fs.root_dir();
let entries: std::io::Result<Vec<String>> = root_dir
let dir = open_dir_path(&fs, &path)?;
let mut entries: std::io::Result<Vec<String>> = dir
.iter()
.map(|entry| {
entry
.map(|e| e.file_name())
.map_err(|error| std::io::Error::new(std::io::ErrorKind::Other, error))
})
.collect();

match entries.as_mut() {
Ok(ok) => ok.sort(),
Err(_err) => (),
}

entries
})
.unwrap()
}

#[query]
fn read_file(filename: String) -> String {
#[update]
fn mkdir(path: String) {
FS.with(|fs| {
let fs = fs.borrow();
let root_dir = fs.root_dir();
let mut file = root_dir.open_file(&filename)?;
let mut buf = vec![];
file.read_to_end(&mut buf)?;
let contents = String::from_utf8(buf)
let (dir_path, dir_name) = path_init_last(&path)
.map_err(|error| std::io::Error::new(std::io::ErrorKind::Other, error))?;
std::io::Result::Ok(contents)
let dir = open_dir_path(&fs, &dir_path)?;
dir.create_dir(&dir_name)?;
std::io::Result::Ok(())
})
.unwrap()
}

#[update]
fn rm(path: String) {
FS.with(|fs| {
let fs = fs.borrow();
let (dir_path, target) = path_init_last(&path)
.map_err(|error| std::io::Error::new(std::io::ErrorKind::Other, error))?;
let dir = open_dir_path(&fs, &dir_path)?;
dir.remove(&target)?;
std::io::Result::Ok(())
})
.unwrap()
}

#[update]
fn write_file(filename: String, contents: String) {
fn write_file(path: String, contents: String) {
FS.with(|fs| {
let fs = fs.borrow();
let root_dir = fs.root_dir();
let mut file = root_dir.create_file(&filename)?;
let (dir_path, file_name) = path_init_last(&path)
.map_err(|error| std::io::Error::new(std::io::ErrorKind::Other, error))?;
let dir = open_dir_path(&fs, &dir_path)?;
let mut file = dir.create_file(&file_name)?;
file.truncate()?;
file.write_all(&contents.into_bytes())?;
file.flush()?;
Expand Down
63 changes: 52 additions & 11 deletions examples/fatfs/test.ic-repl
Original file line number Diff line number Diff line change
@@ -1,29 +1,70 @@
import fatfs = "rrkah-fqaaa-aaaaa-aaaaq-cai" as "fatfs.did";
// import fatfs = "ai7t5-aibaq-aaaaa-aaaaa-c" as "fatfs.did";

let result = call fatfs.ls();
let result = call fatfs.ls(".");
assert result == vec {};

let result = call fatfs.write_file("hello.txt", "Hello, World!");
let result = call fatfs.write_file("./hello.txt", "Hello, World!");
assert result == null;

let result = call fatfs.ls();
let result = call fatfs.ls(".");
assert result == vec { "hello.txt"; };

let result = call fatfs.read_file("hello.txt");
let result = call fatfs.cat("./hello.txt");
assert result == "Hello, World!";

let result = call fatfs.write_file("hello.txt", "Hello!");
let result = call fatfs.write_file("./hello.txt", "Hello!");
assert result == null;

let result = call fatfs.read_file("hello.txt");
let result = call fatfs.cat("./hello.txt");
assert result == "Hello!";

let result = call fatfs.write_file("goodbye.txt", "Goodbye!");
let result = call fatfs.write_file("./goodbye.txt", "Goodbye!");
assert result == null;

let result = call fatfs.ls();
assert result == vec { "hello.txt"; "goodbye.txt"; };
let result = call fatfs.ls(".");
assert result == vec { "goodbye.txt"; "hello.txt" };

let result = call fatfs.read_file("goodbye.txt");
let result = call fatfs.cat("./goodbye.txt");
assert result == "Goodbye!";

let result = call fatfs.mkdir("./foo");
assert result == null;

let result = call fatfs.ls(".");
assert result == vec { "foo"; "goodbye.txt"; "hello.txt" };

let result = call fatfs.ls("./foo");
assert result == vec { "."; ".." };

let result = call fatfs.mkdir("./foo/baz");
assert result == null;

let result = call fatfs.ls("./foo");
assert result == vec { "."; ".."; "baz" };

let result = call fatfs.write_file("./foo/bar.txt", "bar");
assert result == null;

let result = call fatfs.cat("./foo/bar.txt");
assert result == "bar";

let result = call fatfs.ls("./foo");
assert result == vec { "."; ".."; "bar.txt"; "baz" };

let result = call fatfs.rm("./foo/baz");
assert result == null;

let result = call fatfs.ls("./foo");
assert result == vec { "."; ".."; "bar.txt" };

let result = call fatfs.rm("./foo/bar.txt");
assert result == null;

let result = call fatfs.ls("./foo");
assert result == vec { "."; ".." };

let result = call fatfs.rm("./foo");
assert result == null;

let result = call fatfs.ls(".");
assert result == vec { "goodbye.txt"; "hello.txt" };

0 comments on commit 897e5a9

Please sign in to comment.