git.delta.rocks / jrsonnet / refs/commits / e53349155ac3

difftreelog

source

crates/jrsonnet-evaluator/src/import.rs3.0 KiBsourcehistory
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};1718/// Implements file resolution logic for `import` and `importStr`19pub trait ImportResolver {20	/// Resolves real file path, e.g. `(/home/user/manifests, b.libjsonnet)` can correspond21	/// both to `/home/user/manifests/b.libjsonnet` and to `/home/user/${vendor}/b.libjsonnet`22	/// where `${vendor}` is a library path.23	fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>>;2425	fn load_file_contents(&self, resolved: &Path) -> Result<Vec<u8>>;2627	/// Reads file from filesystem, should be used only with path received from `resolve_file`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	/// Reads file from filesystem, should be used only with path received from `resolve_file`34	fn load_file_bin(&self, resolved: &Path) -> Result<Rc<[u8]>> {35		Ok(self.load_file_contents(resolved)?.into())36	}3738	/// # Safety39	///40	/// For use only in bindings, should not be used elsewhere.41	/// Implementations which are not intended to be used in bindings42	/// should panic on call to this method.43	unsafe fn as_any(&self) -> &dyn Any;44}4546/// Dummy resolver, can't resolve/load any file47pub 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}6768/// File resolver, can load file from both FS and library paths69#[derive(Default)]70pub struct FileImportResolver {71	/// Library directories to search for file.72	/// Referred to as `jpath` in original jsonnet implementation.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}