1use std::{2 any::Any,3 convert::TryFrom,4 fs,5 io::Read,6 path::{Path, PathBuf},7 rc::Rc,8};910use fs::File;11use jrsonnet_interner::IStr;1213use crate::{14 error::{Error::*, Result},15 throw,16};171819pub trait ImportResolver {20 21 22 23 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>>;2425 fn load_file_contents(&self, resolved: &Path) -> Result<Vec<u8>>;2627 28 fn load_file_str(&self, resolved: &Path) -> Result<IStr> {29 Ok(IStr::try_from(&self.load_file_contents(resolved)? as &[u8])30 .map_err(|_| ImportBadFileUtf8(resolved.to_path_buf()))?)31 }3233 34 fn load_file_bin(&self, resolved: &Path) -> Result<Rc<[u8]>> {35 Ok(self.load_file_contents(resolved)?.into())36 }3738 39 40 41 42 43 unsafe fn as_any(&self) -> &dyn Any;44}454647pub struct DummyImportResolver;48impl ImportResolver for DummyImportResolver {49 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>> {50 throw!(ImportNotSupported(from.into(), path.into()))51 }5253 fn load_file_contents(&self, _resolved: &Path) -> Result<Vec<u8>> {54 panic!("dummy resolver can't load any file")55 }5657 unsafe fn as_any(&self) -> &dyn Any {58 panic!("`as_any($self)` is not supported by dummy resolver")59 }60}61#[allow(clippy::use_self)]62impl Default for Box<dyn ImportResolver> {63 fn default() -> Self {64 Box::new(DummyImportResolver)65 }66}676869#[derive(Default)]70pub struct FileImportResolver {71 72 73 pub library_paths: Vec<PathBuf>,74}75impl ImportResolver for FileImportResolver {76 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>> {77 let mut direct = from.to_path_buf();78 direct.push(path);79 if direct.exists() {80 Ok(direct.into())81 } else {82 for library_path in self.library_paths.iter() {83 let mut cloned = library_path.clone();84 cloned.push(path);85 if cloned.exists() {86 return Ok(cloned.into());87 }88 }89 throw!(ImportFileNotFound(from.to_owned(), path.to_owned()))90 }91 }92 fn load_file_contents(&self, id: &Path) -> Result<Vec<u8>> {93 let mut file = File::open(id).map_err(|_e| ResolvedFileNotFound(id.to_owned()))?;94 let mut out = Vec::new();95 file.read_to_end(&mut out)96 .map_err(|e| ImportIo(e.to_string()))?;97 Ok(out)98 }99 unsafe fn as_any(&self) -> &dyn Any {100 panic!("this resolver can't be used as any")101 }102}