use crate::engine::{Config, Engine, ImportKey, SourceRead};
use crate::vfs::VirtualFs;
use crate::ErrorList;
use go_parser::Map;
use std::io;
use std::path::{Path, PathBuf};
use std::rc::Rc;
pub fn run(
config: Config,
source: &SourceReader,
path: &Path,
panic_handler: Option<Rc<dyn Fn(String, String)>>,
) -> Result<(), ErrorList> {
let engine = Engine::new();
#[cfg(feature = "go_std")]
engine.set_std_io(config.std_in, config.std_out, config.std_err);
engine.run_source(
config.trace_parser,
config.trace_checker,
source,
path,
panic_handler,
)
}
pub struct SourceReader {
base_dir: Option<PathBuf>,
working_dir: PathBuf,
vfs: Box<dyn VirtualFs>,
}
impl SourceReader {
pub fn new(
base_dir: Option<PathBuf>,
working_dir: PathBuf,
vfs: Box<dyn VirtualFs>,
) -> SourceReader {
SourceReader {
base_dir,
working_dir,
vfs,
}
}
#[cfg(feature = "read_fs")]
pub fn local_fs(base_dir: PathBuf, working_dir: PathBuf) -> SourceReader {
SourceReader::new(Some(base_dir), working_dir, Box::new(crate::VfsFs {}))
}
#[cfg(feature = "read_fs")]
pub fn fs_lib_and_string(
base_dir: PathBuf,
source: std::borrow::Cow<'static, str>,
) -> (SourceReader, PathBuf) {
let temp_file_name = "temp_file.gos";
let vfs_map_name = "vfs_map";
let vfs_fs_name = "vfs_fs";
(
SourceReader::new(
Some(Path::new(vfs_fs_name).join(base_dir)),
PathBuf::from(format!("{}/", vfs_map_name)),
Box::new(crate::CompoundFs::new(Map::from([
(
vfs_fs_name.to_owned(),
Box::new(crate::VfsFs {}) as Box<dyn VirtualFs>,
),
(
vfs_map_name.to_owned(),
Box::new(crate::VfsMap::new(Map::from([(
PathBuf::from(temp_file_name),
source,
)]))),
),
]))),
),
PathBuf::from(format!("./{}", temp_file_name)),
)
}
#[cfg(feature = "read_zip")]
pub fn zip_lib_and_string(
archive: std::borrow::Cow<'static, [u8]>,
base_dir: PathBuf,
source: std::borrow::Cow<'static, str>,
) -> (SourceReader, PathBuf) {
let temp_file_name = "temp_file.gos";
let vfs_map_name = "vfs_map";
let vfs_zip_name = "vfs_zip";
(
SourceReader::new(
Some(Path::new(vfs_zip_name).join(base_dir)),
PathBuf::from(format!("{}/", vfs_map_name)),
Box::new(crate::CompoundFs::new(Map::from([
(
vfs_zip_name.to_owned(),
Box::new(crate::VfsZip::new(archive).unwrap()) as Box<dyn VirtualFs>,
),
(
vfs_map_name.to_owned(),
Box::new(crate::VfsMap::new(Map::from([(
PathBuf::from(temp_file_name),
source,
)]))),
),
]))),
),
PathBuf::from(format!("./{}", temp_file_name)),
)
}
#[cfg(feature = "read_zip")]
pub fn zip_lib_and_local_fs(
archive: std::borrow::Cow<'static, [u8]>,
base_dir: PathBuf,
working_dir: PathBuf,
) -> SourceReader {
let vfs_fs_name = "local_fs";
let vfs_zip_name = "vfs_zip";
SourceReader::new(
Some(Path::new(vfs_zip_name).join(base_dir)),
Path::new(&vfs_fs_name).join(working_dir),
Box::new(crate::CompoundFs::new(Map::from([
(
vfs_fs_name.to_owned(),
Box::new(crate::VfsFs {}) as Box<dyn VirtualFs>,
),
(
vfs_zip_name.to_owned(),
Box::new(crate::VfsZip::new(archive).unwrap()) as Box<dyn VirtualFs>,
),
]))),
)
}
}
impl SourceRead for SourceReader {
fn working_dir(&self) -> &Path {
&self.working_dir
}
fn base_dir(&self) -> Option<&Path> {
self.base_dir.as_ref().map(|x| x.as_path())
}
fn read_file(&self, path: &Path) -> io::Result<String> {
self.vfs.read_file(path)
}
fn read_dir(&self, path: &Path) -> io::Result<Vec<PathBuf>> {
self.vfs.read_dir(path)
}
fn is_file(&self, path: &Path) -> bool {
self.vfs.is_file(path)
}
fn is_dir(&self, path: &Path) -> bool {
self.vfs.is_dir(path)
}
fn canonicalize_import(&self, key: &ImportKey) -> io::Result<(PathBuf, String)> {
let mut import_path = key.path.clone();
let path = if self.vfs.is_local(&key.path) {
let mut wd = self.working_dir().to_owned();
wd.push(self.vfs.strip_prefix(Path::new(&key.dir)));
wd.push(&key.path);
if let Some(base) = &self.base_dir() {
if let Ok(rel) = wd.as_path().strip_prefix(base) {
import_path = rel.to_string_lossy().to_string()
}
}
wd
} else {
if let Some(base) = &self.base_dir() {
let mut p = PathBuf::new();
p.push(base);
p.push(&key.path);
p
} else {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("base dir required for path: {}", key.path),
));
}
};
self.vfs.canonicalize_path(&path).map(|p| (p, import_path))
}
}