From 0076b3a37dcca0e11afd05dc98174f646cdb8fa9 Mon Sep 17 00:00:00 2001 From: Akshay Date: Tue, 19 Oct 2021 15:57:39 +0530 Subject: add vfs --- Cargo.toml | 3 +- vfs/Cargo.toml | 8 ++++++ vfs/src/lib.rs | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 vfs/Cargo.toml create mode 100644 vfs/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index adfe5d6..7303bc8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "bin", "lib", - "macros" + "macros", + "vfs" ] diff --git a/vfs/Cargo.toml b/vfs/Cargo.toml new file mode 100644 index 0000000..56a2c61 --- /dev/null +++ b/vfs/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "vfs" +version = "0.1.0" +edition = "2018" + +[dependencies] +indexmap = "1.6.2" + diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs new file mode 100644 index 0000000..f620ab9 --- /dev/null +++ b/vfs/src/lib.rs @@ -0,0 +1,89 @@ +use std::{ + collections::HashMap, + default::Default, + path::{Path, PathBuf}, +}; + +use indexmap::IndexSet; + +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)] +pub struct FileId(u32); + +#[derive(Debug, Default)] +pub struct Interner { + map: IndexSet, +} + +impl Interner { + pub fn get>(&self, path: P) -> Option { + self.map + .get_index_of(path.as_ref()) + .map(|i| FileId(i as u32)) + } + pub fn intern(&mut self, path: PathBuf) -> FileId { + let (id, _) = self.map.insert_full(path); + FileId(id as u32) + } + pub fn lookup(&self, file: FileId) -> Option<&Path> { + self.map.get_index(file.0 as usize).map(|p| p.as_path()) + } +} + +#[derive(Default)] +pub struct ReadOnlyVfs { + interner: Interner, + data: HashMap>, +} + +impl ReadOnlyVfs { + pub fn alloc_file_id>(&mut self, path: P) -> FileId { + self.interner.intern(path.as_ref().to_owned()) + } + pub fn len(&self) -> usize { + self.data.len() + } + pub fn file_path(&self, file_id: FileId) -> &Path { + self.interner.lookup(file_id).unwrap() + } + pub fn get(&self, file_id: FileId) -> &Vec { + self.data.get(&file_id).unwrap() + } + pub fn get_str(&self, file_id: FileId) -> &str { + std::str::from_utf8(self.get(file_id)).unwrap() + } + pub fn get_mut(&mut self, file_id: FileId) -> &mut Vec { + self.data.get_mut(&file_id).unwrap() + } + pub fn set_file_contents>(&mut self, path: P, contents: &[u8]) { + let file_id = self.alloc_file_id(path); + self.data.insert(file_id, contents.to_owned()); + } + pub fn iter<'ρ>(&'ρ self) -> impl Iterator> { + self.data.iter().map(move |(file_id, _)| VfsEntry { + file_id: *file_id, + file_path: self.file_path(*file_id), + contents: self.get_str(*file_id), + }) + } +} + +pub struct VfsEntry<'ρ> { + pub file_id: FileId, + pub file_path: &'ρ Path, + pub contents: &'ρ str, +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn trivial() { + let mut vfs = ReadOnlyVfs::default(); + let f1 = "a/b/c"; + let id1 = vfs.alloc_file_id(f1); + let data = "hello".as_bytes().to_vec(); + vfs.set_file_contents(f1, &data); + assert_eq!(vfs.get(id1), &data); + } +} -- cgit v1.2.3