forked from Orchid/orchid
very elegant extension API and parts of it used in std as POC
This commit is contained in:
@@ -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) }
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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("/")))
|
||||
}
|
||||
|
||||
@@ -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)?)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user