git.delta.rocks / jrsonnet / refs/commits / 0831da3ed8d9

difftreelog

source

crates/jrsonnet-evaluator/src/import.rs3.0 KiBsourcehistory
1use std::{2	any::Any,3	fs,4	io::Read,5	path::{Path, PathBuf},6};78use fs::File;9use jrsonnet_parser::SourcePath;1011use crate::{12	error::{Error::*, Result},13	throw,14};1516/// Implements file resolution logic for `import` and `importStr`17pub trait ImportResolver {18	/// Resolves real file path, e.g. `(/home/user/manifests, b.libjsonnet)` can correspond19	/// both to `/home/user/manifests/b.libjsonnet` and to `/home/user/${vendor}/b.libjsonnet`20	/// where `${vendor}` is a library path.21	fn resolve_file_relative(&self, from: &Path, path: &str) -> Result<SourcePath>;2223	/// Load resolved file24	/// This should only be called with value returned from `resolve_file`, this cannot be resolved using associated type,25	/// as evaluator uses object instead of generic for [`ImportResolver`]26	fn load_file_contents(&self, resolved: &SourcePath) -> Result<Vec<u8>>;2728	/// # Safety29	///30	/// For use only in bindings, should not be used elsewhere.31	/// Implementations which are not intended to be used in bindings32	/// should panic on call to this method.33	unsafe fn as_any(&self) -> &dyn Any;34}3536/// Dummy resolver, can't resolve/load any file37pub struct DummyImportResolver;38impl ImportResolver for DummyImportResolver {39	fn resolve_file_relative(&self, from: &Path, path: &str) -> Result<SourcePath> {40		throw!(ImportNotSupported(from.into(), path.into()))41	}4243	fn load_file_contents(&self, _resolved: &SourcePath) -> Result<Vec<u8>> {44		panic!("dummy resolver can't load any file")45	}4647	unsafe fn as_any(&self) -> &dyn Any {48		panic!("`as_any(&self)` is not supported by dummy resolver")49	}50}51#[allow(clippy::use_self)]52impl Default for Box<dyn ImportResolver> {53	fn default() -> Self {54		Box::new(DummyImportResolver)55	}56}5758/// File resolver, can load file from both FS and library paths59#[derive(Default)]60pub struct FileImportResolver {61	/// Library directories to search for file.62	/// Referred to as `jpath` in original jsonnet implementation.63	pub library_paths: Vec<PathBuf>,64}65impl ImportResolver for FileImportResolver {66	fn resolve_file_relative(&self, from: &Path, path: &str) -> Result<SourcePath> {67		let mut direct = from.to_path_buf();68		direct.push(path);69		if direct.exists() {70			Ok(SourcePath::Path(71				direct.canonicalize().map_err(|e| ImportIo(e.to_string()))?,72			))73		} else {74			for library_path in &self.library_paths {75				let mut cloned = library_path.clone();76				cloned.push(path);77				if cloned.exists() {78					return Ok(SourcePath::Path(79						cloned.canonicalize().map_err(|e| ImportIo(e.to_string()))?,80					));81				}82			}83			throw!(ImportFileNotFound(from.to_owned(), path.to_owned()))84		}85	}8687	fn load_file_contents(&self, id: &SourcePath) -> Result<Vec<u8>> {88		let path = match id {89			SourcePath::Path(path) => path,90			_ => {91				panic!("this resolver can only resolve to path")92			}93		};94		let mut file = File::open(path).map_err(|_e| ResolvedFileNotFound(id.clone()))?;95		let mut out = Vec::new();96		file.read_to_end(&mut out)97			.map_err(|e| ImportIo(e.to_string()))?;98		Ok(out)99	}100	unsafe fn as_any(&self) -> &dyn Any {101		panic!("this resolver can't be used as any")102	}103}