forked from Orchid/orchid
Orchid-base uses task-local context.
Everything else is broken at the moment.
This commit is contained in:
@@ -9,19 +9,19 @@ use crate::proj_error::{ErrorSansOrigin, ErrorSansOriginObj};
|
||||
/// as the file system. Cheap to clone.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Loaded {
|
||||
/// Conceptually equivalent to a sourcefile
|
||||
Code(Arc<String>),
|
||||
/// Conceptually equivalent to the list of *.orc files in a folder, without
|
||||
/// the extension
|
||||
Collection(Arc<Vec<Tok<String>>>),
|
||||
/// Conceptually equivalent to a sourcefile
|
||||
Code(Arc<String>),
|
||||
/// Conceptually equivalent to the list of *.orc files in a folder, without
|
||||
/// the extension
|
||||
Collection(Arc<Vec<IStr>>),
|
||||
}
|
||||
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 = Tok<String>>) -> Self {
|
||||
Self::Collection(Arc::new(items.into_iter().collect()))
|
||||
}
|
||||
/// 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 = IStr>) -> Self {
|
||||
Self::Collection(Arc::new(items.into_iter().collect()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returned by any source loading callback
|
||||
@@ -30,66 +30,62 @@ pub type FSResult = Result<Loaded, ErrorSansOriginObj>;
|
||||
/// Type that indicates the type of an entry without reading the contents
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
|
||||
pub enum FSKind {
|
||||
/// Invalid path or read error
|
||||
None,
|
||||
/// Source code
|
||||
Code,
|
||||
/// Internal tree node
|
||||
Collection,
|
||||
/// Invalid path or read error
|
||||
None,
|
||||
/// Source code
|
||||
Code,
|
||||
/// Internal tree node
|
||||
Collection,
|
||||
}
|
||||
|
||||
/// Distinguished error for missing code
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct CodeNotFound(pub VPath);
|
||||
impl CodeNotFound {
|
||||
/// Instantiate error
|
||||
pub fn new(path: VPath) -> Self { Self(path) }
|
||||
/// Instantiate error
|
||||
pub fn new(path: VPath) -> Self { Self(path) }
|
||||
}
|
||||
impl ErrorSansOrigin for CodeNotFound {
|
||||
const DESCRIPTION: &'static str = "No source code for path";
|
||||
fn message(&self) -> String { format!("{} not found", self.0) }
|
||||
const DESCRIPTION: &'static str = "No source code for path";
|
||||
fn message(&self) -> String { format!("{} not found", self.0) }
|
||||
}
|
||||
|
||||
/// A simplified view of a file system for the purposes of source code loading.
|
||||
/// This includes the real FS and source code, but also various in-memory
|
||||
/// formats and other sources for libraries and dependencies.
|
||||
pub trait VirtFS {
|
||||
/// Implementation of [VirtFS::read]
|
||||
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
|
||||
fn kind(&self, path: &PathSlice) -> FSKind {
|
||||
match self.read(path) {
|
||||
Err(_) => FSKind::None,
|
||||
Ok(Loaded::Code(_)) => FSKind::Code,
|
||||
Ok(Loaded::Collection(_)) => FSKind::Collection,
|
||||
}
|
||||
}
|
||||
/// Convert a path into a human-readable string that is meaningful in the
|
||||
/// target context.
|
||||
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>
|
||||
where Self: Sized + 'static {
|
||||
Rc::new(self)
|
||||
}
|
||||
/// Read a path, returning either a text file, a directory listing or an
|
||||
/// error. Wrapper for [VirtFS::get]
|
||||
fn read(&self, path: &PathSlice) -> FSResult { self.get(path, path) }
|
||||
/// Implementation of [VirtFS::read]
|
||||
fn get(&self, path: &[IStr], full_path: &PathSlice) -> FSResult;
|
||||
/// Discover information about a path without reading it.
|
||||
///
|
||||
/// Implement this if your vfs backend can do expensive operations
|
||||
fn kind(&self, path: &PathSlice) -> FSKind {
|
||||
match self.read(path) {
|
||||
Err(_) => FSKind::None,
|
||||
Ok(Loaded::Code(_)) => FSKind::Code,
|
||||
Ok(Loaded::Collection(_)) => FSKind::Collection,
|
||||
}
|
||||
}
|
||||
/// Convert a path into a human-readable string that is meaningful in the
|
||||
/// target context.
|
||||
fn display(&self, path: &[IStr]) -> Option<String>;
|
||||
/// Convert the FS handler into a type-erased version of itself for packing in
|
||||
/// a tree.
|
||||
fn rc(self) -> Rc<dyn VirtFS>
|
||||
where Self: Sized + 'static {
|
||||
Rc::new(self)
|
||||
}
|
||||
/// Read a path, returning either a text file, a directory listing or an
|
||||
/// error. Wrapper for [VirtFS::get]
|
||||
fn read(&self, path: &PathSlice) -> FSResult { self.get(path, path) }
|
||||
}
|
||||
|
||||
impl VirtFS for &dyn VirtFS {
|
||||
fn get(&self, path: &[Tok<String>], full_path: &PathSlice) -> FSResult {
|
||||
(*self).get(path, full_path)
|
||||
}
|
||||
fn display(&self, path: &[Tok<String>]) -> Option<String> { (*self).display(path) }
|
||||
fn get(&self, path: &[IStr], full_path: &PathSlice) -> FSResult { (*self).get(path, full_path) }
|
||||
fn display(&self, path: &[IStr]) -> Option<String> { (*self).display(path) }
|
||||
}
|
||||
|
||||
impl<T: VirtFS + ?Sized> VirtFS for Rc<T> {
|
||||
fn get(&self, path: &[Tok<String>], full_path: &PathSlice) -> FSResult {
|
||||
(**self).get(path, full_path)
|
||||
}
|
||||
fn display(&self, path: &[Tok<String>]) -> Option<String> { (**self).display(path) }
|
||||
fn get(&self, path: &[IStr], full_path: &PathSlice) -> FSResult { (**self).get(path, full_path) }
|
||||
fn display(&self, path: &[IStr]) -> 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: &[Tok<String>], full_path: &PathSlice) -> FSResult {
|
||||
fn get(&self, path: &[IStr], 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: &[Tok<String>]) -> Option<String> {
|
||||
fn display(&self, path: &[IStr]) -> 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, _: &[Tok<String>]) -> Option<String> { None }
|
||||
fn get(&self, path: &[Tok<String>], full_path: &PathSlice) -> FSResult {
|
||||
fn display(&self, _: &[IStr]) -> Option<String> { None }
|
||||
fn get(&self, path: &[IStr], 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, _: &[Tok<String>]) -> Option<String> { None }
|
||||
fn get(&self, path: &[Tok<String>], full_path: &PathSlice) -> FSResult {
|
||||
fn display(&self, _: &[IStr]) -> Option<String> { None }
|
||||
fn get(&self, path: &[IStr], 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: &[Tok<String>]) -> PathBuf {
|
||||
fn mk_pathbuf(&self, path: &[IStr]) -> 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: &[Tok<String>], full_path: &PathSlice) -> FSResult {
|
||||
fn get(&self, path: &[IStr], 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: &[Tok<String>]) -> Option<String> {
|
||||
fn display(&self, path: &[IStr]) -> 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: &[Tok<String>], full_path: &PathSlice) -> FSResult {
|
||||
fn get(&self, path: &[IStr], 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: &[Tok<String>]) -> Option<String> {
|
||||
fn display(&self, path: &[IStr]) -> 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: &[Tok<String>]) -> Option<Vec<Tok<String>>> {
|
||||
fn proc_path(&self, path: &[IStr]) -> Option<Vec<IStr>> {
|
||||
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: &[Tok<String>], full_path: &PathSlice) -> super::FSResult {
|
||||
fn get(&self, path: &[IStr], 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: &[Tok<String>]) -> Option<String> {
|
||||
fn display(&self, path: &[IStr]) -> Option<String> {
|
||||
self.wrapped.display(&self.proc_path(path)?)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user