very elegant extension API and parts of it used in std as POC

This commit is contained in:
2024-07-01 20:11:22 +02:00
parent 93867e40c6
commit fc8441f080
63 changed files with 2040 additions and 925 deletions

View File

@@ -13,13 +13,13 @@ pub enum Loaded {
Code(Arc<String>),
/// Conceptually equivalent to the list of *.orc files in a folder, without
/// the extension
Collection(Arc<Vec<Token<String>>>),
Collection(Arc<Vec<Tok<String>>>),
}
impl Loaded {
/// Is the loaded item source code (not a collection)?
pub fn is_code(&self) -> bool { matches!(self, Loaded::Code(_)) }
/// Collect the elements in a collection rreport
pub fn collection(items: impl IntoIterator<Item = Token<String>>) -> Self {
pub fn collection(items: impl IntoIterator<Item = Tok<String>>) -> Self {
Self::Collection(Arc::new(items.into_iter().collect()))
}
}
@@ -55,7 +55,7 @@ impl ErrorSansOrigin for CodeNotFound {
/// formats and other sources for libraries and dependencies.
pub trait VirtFS {
/// Implementation of [VirtFS::read]
fn get(&self, path: &[Token<String>], full_path: &PathSlice) -> FSResult;
fn get(&self, path: &[Tok<String>], full_path: &PathSlice) -> FSResult;
/// Discover information about a path without reading it.
///
/// Implement this if your vfs backend can do expensive operations
@@ -68,7 +68,7 @@ pub trait VirtFS {
}
/// Convert a path into a human-readable string that is meaningful in the
/// target context.
fn display(&self, path: &[Token<String>]) -> Option<String>;
fn display(&self, path: &[Tok<String>]) -> Option<String>;
/// Convert the FS handler into a type-erased version of itself for packing in
/// a tree.
fn rc(self) -> Rc<dyn VirtFS>
@@ -81,15 +81,15 @@ pub trait VirtFS {
}
impl VirtFS for &dyn VirtFS {
fn get(&self, path: &[Token<String>], full_path: &PathSlice) -> FSResult {
fn get(&self, path: &[Tok<String>], full_path: &PathSlice) -> FSResult {
(*self).get(path, full_path)
}
fn display(&self, path: &[Token<String>]) -> Option<String> { (*self).display(path) }
fn display(&self, path: &[Tok<String>]) -> Option<String> { (*self).display(path) }
}
impl<T: VirtFS + ?Sized> VirtFS for Rc<T> {
fn get(&self, path: &[Token<String>], full_path: &PathSlice) -> FSResult {
fn get(&self, path: &[Tok<String>], full_path: &PathSlice) -> FSResult {
(**self).get(path, full_path)
}
fn display(&self, path: &[Token<String>]) -> Option<String> { (**self).display(path) }
fn display(&self, path: &[Tok<String>]) -> Option<String> { (**self).display(path) }
}

View File

@@ -32,7 +32,7 @@ impl<'a> Combine for &'a dyn VirtFS {
pub type DeclTree = ModEntry<Rc<dyn VirtFS>, (), ()>;
impl VirtFS for DeclTree {
fn get(&self, path: &[Token<String>], full_path: &PathSlice) -> FSResult {
fn get(&self, path: &[Tok<String>], full_path: &PathSlice) -> FSResult {
match &self.member {
ModMember::Item(it) => it.get(path, full_path),
ModMember::Sub(module) => match path.split_first() {
@@ -44,7 +44,7 @@ impl VirtFS for DeclTree {
}
}
fn display(&self, path: &[Token<String>]) -> Option<String> {
fn display(&self, path: &[Tok<String>]) -> Option<String> {
let (head, tail) = path.split_first()?;
match &self.member {
ModMember::Item(it) => it.display(path),
@@ -54,16 +54,16 @@ impl VirtFS for DeclTree {
}
impl VirtFS for String {
fn display(&self, _: &[Token<String>]) -> Option<String> { None }
fn get(&self, path: &[Token<String>], full_path: &PathSlice) -> FSResult {
fn display(&self, _: &[Tok<String>]) -> Option<String> { None }
fn get(&self, path: &[Tok<String>], full_path: &PathSlice) -> FSResult {
(path.is_empty().then(|| Loaded::Code(Arc::new(self.as_str().to_string()))))
.ok_or_else(|| CodeNotFound::new(full_path.to_vpath()).pack())
}
}
impl<'a> VirtFS for &'a str {
fn display(&self, _: &[Token<String>]) -> Option<String> { None }
fn get(&self, path: &[Token<String>], full_path: &PathSlice) -> FSResult {
fn display(&self, _: &[Tok<String>]) -> Option<String> { None }
fn get(&self, path: &[Tok<String>], full_path: &PathSlice) -> FSResult {
(path.is_empty().then(|| Loaded::Code(Arc::new(self.to_string()))))
.ok_or_else(|| CodeNotFound::new(full_path.to_vpath()).pack())
}

View File

@@ -99,14 +99,14 @@ impl DirNode {
}
}
fn mk_pathbuf(&self, path: &[Token<String>]) -> PathBuf {
fn mk_pathbuf(&self, path: &[Tok<String>]) -> PathBuf {
let mut fpath = self.root.clone();
path.iter().for_each(|seg| fpath.push(seg.as_str()));
fpath
}
}
impl VirtFS for DirNode {
fn get(&self, path: &[Token<String>], full_path: &PathSlice) -> FSResult {
fn get(&self, path: &[Tok<String>], full_path: &PathSlice) -> FSResult {
let fpath = self.mk_pathbuf(path);
let mut binding = self.cached.borrow_mut();
let (_, res) = (binding.raw_entry_mut().from_key(&fpath))
@@ -114,7 +114,7 @@ impl VirtFS for DirNode {
res.clone()
}
fn display(&self, path: &[Token<String>]) -> Option<String> {
fn display(&self, path: &[Tok<String>]) -> Option<String> {
let pathbuf = self.mk_pathbuf(path).with_extension(self.ext());
Some(pathbuf.to_string_lossy().to_string())
}

View File

@@ -56,7 +56,7 @@ impl EmbeddedFS {
}
impl VirtFS for EmbeddedFS {
fn get(&self, path: &[Token<String>], full_path: &PathSlice) -> FSResult {
fn get(&self, path: &[Tok<String>], full_path: &PathSlice) -> FSResult {
if path.is_empty() {
return Ok(Loaded::collection(self.tree.keys(|_| true)));
}
@@ -67,7 +67,7 @@ impl VirtFS for EmbeddedFS {
ModMember::Sub(sub) => Loaded::collection(sub.keys(|_| true)),
})
}
fn display(&self, path: &[Token<String>]) -> Option<String> {
fn display(&self, path: &[Tok<String>]) -> Option<String> {
let Self { gen, suffix, .. } = self;
Some(format!("{}{suffix} in {gen}", path.iter().join("/")))
}

View File

@@ -21,18 +21,18 @@ impl<'a> PrefixFS<'a> {
add: VPath::parse(add.as_ref()),
}
}
fn proc_path(&self, path: &[Token<String>]) -> Option<Vec<Token<String>>> {
fn proc_path(&self, path: &[Tok<String>]) -> Option<Vec<Tok<String>>> {
let path = path.strip_prefix(self.remove.as_slice())?;
Some(self.add.0.iter().chain(path).cloned().collect_vec())
}
}
impl<'a> VirtFS for PrefixFS<'a> {
fn get(&self, path: &[Token<String>], full_path: &PathSlice) -> super::FSResult {
fn get(&self, path: &[Tok<String>], full_path: &PathSlice) -> super::FSResult {
let path =
self.proc_path(path).ok_or_else(|| CodeNotFound::new(full_path.to_vpath()).pack())?;
self.wrapped.get(&path, full_path)
}
fn display(&self, path: &[Token<String>]) -> Option<String> {
fn display(&self, path: &[Tok<String>]) -> Option<String> {
self.wrapped.display(&self.proc_path(path)?)
}
}