1use crate::{2 error::{Error::*, Result},3 throw,4};5use fs::File;6use jrsonnet_interner::IStr;7use std::fs;8use std::{9 any::Any,10 path::{Path, PathBuf},11 rc::Rc,12};13use std::{convert::TryFrom, io::Read};141516pub trait ImportResolver {17 18 19 20 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>>;2122 fn load_file_contents(&self, resolved: &Path) -> Result<Vec<u8>>;2324 25 fn load_file_str(&self, resolved: &Path) -> Result<IStr> {26 Ok(IStr::try_from(&self.load_file_contents(resolved)? as &[u8])27 .map_err(|_| ImportBadFileUtf8(resolved.to_path_buf()))?)28 }2930 31 fn load_file_bin(&self, resolved: &Path) -> Result<Rc<[u8]>> {32 Ok(self.load_file_contents(resolved)?.into())33 }3435 36 37 38 39 40 unsafe fn as_any(&self) -> &dyn Any;41}424344pub struct DummyImportResolver;45impl ImportResolver for DummyImportResolver {46 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>> {47 throw!(ImportNotSupported(from.into(), path.into()))48 }4950 fn load_file_contents(&self, _resolved: &Path) -> Result<Vec<u8>> {51 panic!("dummy resolver can't load any file")52 }5354 unsafe fn as_any(&self) -> &dyn Any {55 panic!("`as_any($self)` is not supported by dummy resolver")56 }57}58#[allow(clippy::use_self)]59impl Default for Box<dyn ImportResolver> {60 fn default() -> Self {61 Box::new(DummyImportResolver)62 }63}646566#[derive(Default)]67pub struct FileImportResolver {68 69 70 pub library_paths: Vec<PathBuf>,71}72impl ImportResolver for FileImportResolver {73 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>> {74 let mut direct = from.to_path_buf();75 direct.push(path);76 if direct.exists() {77 Ok(direct.into())78 } else {79 for library_path in self.library_paths.iter() {80 let mut cloned = library_path.clone();81 cloned.push(path);82 if cloned.exists() {83 return Ok(cloned.into());84 }85 }86 throw!(ImportFileNotFound(from.to_owned(), path.to_owned()))87 }88 }89 fn load_file_contents(&self, id: &Path) -> Result<Vec<u8>> {90 let mut file = File::open(id).map_err(|_e| ResolvedFileNotFound(id.to_owned()))?;91 let mut out = Vec::new();92 file.read_to_end(&mut out)93 .map_err(|e| ImportIo(e.to_string()))?;94 Ok(out)95 }96 unsafe fn as_any(&self) -> &dyn Any {97 panic!("this resolver can't be used as any")98 }99}