git.delta.rocks / jrsonnet / refs/commits / 74199ce77317

difftreelog

source

crates/jrsonnet-evaluator/src/import.rs3.0 KiBsourcehistory
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};1415/// Implements file resolution logic for `import` and `importStr`16pub trait ImportResolver {17	/// Resolves real file path, e.g. `(/home/user/manifests, b.libjsonnet)` can correspond18	/// both to `/home/user/manifests/b.libjsonnet` and to `/home/user/${vendor}/b.libjsonnet`19	/// where `${vendor}` is a library path.20	fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>>;2122	fn load_file_contents(&self, resolved: &Path) -> Result<Vec<u8>>;2324	/// Reads file from filesystem, should be used only with path received from `resolve_file`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	/// Reads file from filesystem, should be used only with path received from `resolve_file`31	fn load_file_bin(&self, resolved: &Path) -> Result<Rc<[u8]>> {32		Ok(self.load_file_contents(resolved)?.into())33	}3435	/// # Safety36	///37	/// For use only in bindings, should not be used elsewhere.38	/// Implementations which are not intended to be used in bindings39	/// should panic on call to this method.40	unsafe fn as_any(&self) -> &dyn Any;41}4243/// Dummy resolver, can't resolve/load any file44pub 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}6465/// File resolver, can load file from both FS and library paths66#[derive(Default)]67pub struct FileImportResolver {68	/// Library directories to search for file.69	/// Referred to as `jpath` in original jsonnet implementation.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}