Preparation for sharing
- rustfmt - clippy - comments - README
This commit is contained in:
@@ -1,25 +1,23 @@
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::path::PathBuf;
|
||||
use std::io;
|
||||
use std::fs;
|
||||
use std::{fs, io};
|
||||
|
||||
use crate::interner::{Interner, Sym};
|
||||
use crate::pipeline::error::{
|
||||
ErrorPosition, ProjectError, UnexpectedDirectory,
|
||||
};
|
||||
use crate::utils::iter::box_once;
|
||||
use crate::utils::{Cache, BoxedIter};
|
||||
use crate::interner::{Interner, Token};
|
||||
use crate::pipeline::error::UnexpectedDirectory;
|
||||
use crate::pipeline::error::{ProjectError, ErrorPosition};
|
||||
use crate::utils::{BoxedIter, Cache};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FileLoadingError{
|
||||
pub struct FileLoadingError {
|
||||
file: io::Error,
|
||||
dir: io::Error,
|
||||
path: Vec<String>
|
||||
path: Vec<String>,
|
||||
}
|
||||
impl ProjectError for FileLoadingError {
|
||||
fn description(&self) -> &str {
|
||||
"Neither a file nor a directory could be read from \
|
||||
the requested path"
|
||||
"Neither a file nor a directory could be read from the requested path"
|
||||
}
|
||||
fn positions(&self) -> BoxedIter<ErrorPosition> {
|
||||
box_once(ErrorPosition::just_file(self.path.clone()))
|
||||
@@ -37,57 +35,55 @@ pub enum Loaded {
|
||||
Collection(Rc<Vec<String>>),
|
||||
}
|
||||
impl Loaded {
|
||||
pub fn is_code(&self) -> bool {matches!(self, Loaded::Code(_))}
|
||||
pub fn is_code(&self) -> bool {
|
||||
matches!(self, Loaded::Code(_))
|
||||
}
|
||||
}
|
||||
|
||||
pub type IOResult = Result<Loaded, Rc<dyn ProjectError>>;
|
||||
|
||||
pub type FileCache<'a> = Cache<'a, Token<Vec<Token<String>>>, IOResult>;
|
||||
pub type FileCache<'a> = Cache<'a, Sym, IOResult>;
|
||||
|
||||
/// Load a file from a path expressed in Rust strings, but relative to
|
||||
/// a root expressed as an OS Path.
|
||||
pub fn load_file(root: &Path, path: &[impl AsRef<str>]) -> IOResult {
|
||||
// let os_path = path.into_iter()
|
||||
// .map_into::<OsString>()
|
||||
// .collect::<Vec<_>>();
|
||||
let full_path = path.iter().fold(
|
||||
root.to_owned(),
|
||||
|p, s| p.join(s.as_ref())
|
||||
);
|
||||
let full_path = path.iter().fold(root.to_owned(), |p, s| p.join(s.as_ref()));
|
||||
let file_path = full_path.with_extension("orc");
|
||||
let file_error = match fs::read_to_string(&file_path) {
|
||||
let file_error = match fs::read_to_string(file_path) {
|
||||
Ok(string) => return Ok(Loaded::Code(Rc::new(string))),
|
||||
Err(err) => err
|
||||
Err(err) => err,
|
||||
};
|
||||
let dir = match fs::read_dir(&full_path) {
|
||||
Ok(dir) => dir,
|
||||
Err(dir_error) => {
|
||||
return Err(FileLoadingError {
|
||||
file: file_error,
|
||||
dir: dir_error,
|
||||
path: path.iter()
|
||||
.map(|s| s.as_ref().to_string())
|
||||
.collect(),
|
||||
}.rc())
|
||||
}
|
||||
Err(dir_error) =>
|
||||
return Err(
|
||||
FileLoadingError {
|
||||
file: file_error,
|
||||
dir: dir_error,
|
||||
path: path.iter().map(|s| s.as_ref().to_string()).collect(),
|
||||
}
|
||||
.rc(),
|
||||
),
|
||||
};
|
||||
let names = dir.filter_map(Result::ok)
|
||||
let names = dir
|
||||
.filter_map(Result::ok)
|
||||
.filter_map(|ent| {
|
||||
let fname = ent.file_name().into_string().ok()?;
|
||||
let ftyp = ent.metadata().ok()?.file_type();
|
||||
Some(if ftyp.is_dir() {fname} else {
|
||||
Some(if ftyp.is_dir() {
|
||||
fname
|
||||
} else {
|
||||
fname.strip_suffix(".or")?.to_string()
|
||||
})
|
||||
}).collect();
|
||||
})
|
||||
.collect();
|
||||
Ok(Loaded::Collection(Rc::new(names)))
|
||||
}
|
||||
|
||||
/// Generates a cached file loader for a directory
|
||||
pub fn mk_cache(root: PathBuf, i: &Interner) -> FileCache {
|
||||
Cache::new(move |token: Token<Vec<Token<String>>>, _this| -> IOResult {
|
||||
let path = i.r(token).iter()
|
||||
.map(|t| i.r(*t).as_str())
|
||||
.collect::<Vec<_>>();
|
||||
Cache::new(move |token: Sym, _this| -> IOResult {
|
||||
let path = i.r(token).iter().map(|t| i.r(*t).as_str()).collect::<Vec<_>>();
|
||||
load_file(&root, &path)
|
||||
})
|
||||
}
|
||||
@@ -95,12 +91,18 @@ pub fn mk_cache(root: PathBuf, i: &Interner) -> FileCache {
|
||||
/// Loads the string contents of a file at the given location.
|
||||
/// If the path points to a directory, raises an error.
|
||||
pub fn load_text(
|
||||
path: Token<Vec<Token<String>>>,
|
||||
load_file: &impl Fn(Token<Vec<Token<String>>>) -> IOResult,
|
||||
i: &Interner
|
||||
path: Sym,
|
||||
load_file: &impl Fn(Sym) -> IOResult,
|
||||
i: &Interner,
|
||||
) -> Result<Rc<String>, Rc<dyn ProjectError>> {
|
||||
if let Loaded::Code(s) = load_file(path)? {Ok(s)}
|
||||
else {Err(UnexpectedDirectory{
|
||||
path: i.r(path).iter().map(|t| i.r(*t)).cloned().collect()
|
||||
}.rc())}
|
||||
}
|
||||
if let Loaded::Code(s) = load_file(path)? {
|
||||
Ok(s)
|
||||
} else {
|
||||
Err(
|
||||
UnexpectedDirectory {
|
||||
path: i.r(path).iter().map(|t| i.r(*t)).cloned().collect(),
|
||||
}
|
||||
.rc(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user