git.delta.rocks / jrsonnet / refs/commits / 3ee61c42d34d

difftreelog

source

crates/jrsonnet-evaluator/src/import.rs2.6 KiBsourcehistory
1use std::{2	any::Any,3	fs,4	io::Read,5	path::{Path, PathBuf},6};78use fs::File;910use crate::{11	error::{Error::*, Result},12	throw,13};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: &str) -> Result<PathBuf>;2122	fn load_file_contents(&self, resolved: &Path) -> Result<Vec<u8>>;2324	/// # Safety25	///26	/// For use only in bindings, should not be used elsewhere.27	/// Implementations which are not intended to be used in bindings28	/// should panic on call to this method.29	unsafe fn as_any(&self) -> &dyn Any;30}3132/// Dummy resolver, can't resolve/load any file33pub struct DummyImportResolver;34impl ImportResolver for DummyImportResolver {35	fn resolve_file(&self, from: &Path, path: &str) -> Result<PathBuf> {36		throw!(ImportNotSupported(from.into(), path.into()))37	}3839	fn load_file_contents(&self, _resolved: &Path) -> Result<Vec<u8>> {40		panic!("dummy resolver can't load any file")41	}4243	unsafe fn as_any(&self) -> &dyn Any {44		panic!("`as_any(&self)` is not supported by dummy resolver")45	}46}47#[allow(clippy::use_self)]48impl Default for Box<dyn ImportResolver> {49	fn default() -> Self {50		Box::new(DummyImportResolver)51	}52}5354/// File resolver, can load file from both FS and library paths55#[derive(Default)]56pub struct FileImportResolver {57	/// Library directories to search for file.58	/// Referred to as `jpath` in original jsonnet implementation.59	pub library_paths: Vec<PathBuf>,60}61impl ImportResolver for FileImportResolver {62	fn resolve_file(&self, from: &Path, path: &str) -> Result<PathBuf> {63		let mut direct = from.to_path_buf();64		direct.push(path);65		if direct.exists() {66			Ok(direct.canonicalize().map_err(|e| ImportIo(e.to_string()))?)67		} else {68			for library_path in &self.library_paths {69				let mut cloned = library_path.clone();70				cloned.push(path);71				if cloned.exists() {72					return Ok(cloned.canonicalize().map_err(|e| ImportIo(e.to_string()))?);73				}74			}75			throw!(ImportFileNotFound(from.to_owned(), path.to_owned()))76		}77	}7879	fn load_file_contents(&self, id: &Path) -> Result<Vec<u8>> {80		let mut file = File::open(id).map_err(|_e| ResolvedFileNotFound(id.to_owned()))?;81		let mut out = Vec::new();82		file.read_to_end(&mut out)83			.map_err(|e| ImportIo(e.to_string()))?;84		Ok(out)85	}86	unsafe fn as_any(&self) -> &dyn Any {87		panic!("this resolver can't be used as any")88	}89}