git.delta.rocks / jrsonnet / refs/commits / 7eb32146c8af

difftreelog

source

crates/jsonnet-evaluator/src/import.rs2.5 KiBsourcehistory
1use crate::create_error_result;2use crate::{3	create_error,4	error::{Error, Result},5};6use fs::File;7use std::fs;8use std::io::Read;9use std::{cell::RefCell, collections::HashMap, path::PathBuf, rc::Rc};1011pub trait ImportResolver {12	fn resolve_file(&self, from: &PathBuf, path: &PathBuf) -> Result<Rc<PathBuf>>;13	fn load_file_contents(&self, resolved: &PathBuf) -> Result<Rc<str>>;14}1516pub struct DummyImportResolver;17impl ImportResolver for DummyImportResolver {18	fn resolve_file(&self, from: &PathBuf, path: &PathBuf) -> Result<Rc<PathBuf>> {19		create_error_result(Error::ImportNotSupported(from.clone(), path.clone()))20	}21	fn load_file_contents(&self, _resolved: &PathBuf) -> Result<Rc<str>> {22		// Can be only caused by library direct consumer, not by supplied jsonnet23		panic!("dummy resolver can't load any file")24	}25}26impl Default for Box<dyn ImportResolver> {27	fn default() -> Self {28		Box::new(DummyImportResolver)29	}30}3132pub struct FileImportResolver {33	pub library_paths: Vec<PathBuf>,34}35impl ImportResolver for FileImportResolver {36	fn resolve_file(&self, from: &PathBuf, path: &PathBuf) -> Result<Rc<PathBuf>> {37		let mut new_path = from.clone();38		new_path.push(path);39		if new_path.exists() {40			Ok(Rc::new(new_path))41		} else {42			for library_path in self.library_paths.iter() {43				let mut cloned = library_path.clone();44				cloned.push(path);45				if cloned.exists() {46					return Ok(Rc::new(cloned));47				}48			}49			create_error_result(Error::ImportFileNotFound(from.clone(), path.clone()))50		}51	}52	fn load_file_contents(&self, id: &PathBuf) -> Result<Rc<str>> {53		let mut file =54			File::open(id).map_err(|_e| create_error(Error::ResolvedFileNotFound(id.clone())))?;55		let mut out = String::new();56		file.read_to_string(&mut out)57			.map_err(|_e| create_error(Error::ImportBadFileUtf8(id.clone())))?;58		Ok(out.into())59	}60}6162type ResolutionData = (PathBuf, PathBuf);63pub struct CachingImportResolver {64	resolution_cache: RefCell<HashMap<ResolutionData, Result<Rc<PathBuf>>>>,65	loading_cache: RefCell<HashMap<PathBuf, Result<Rc<str>>>>,66	inner: Box<dyn ImportResolver>,67}68impl ImportResolver for CachingImportResolver {69	fn resolve_file(&self, from: &PathBuf, path: &PathBuf) -> Result<Rc<PathBuf>> {70		self.resolution_cache71			.borrow_mut()72			.entry((from.clone(), path.clone()))73			.or_insert_with(|| self.inner.resolve_file(from, path))74			.clone()75	}76	fn load_file_contents(&self, resolved: &PathBuf) -> Result<Rc<str>> {77		self.loading_cache78			.borrow_mut()79			.entry(resolved.clone())80			.or_insert_with(|| self.inner.load_file_contents(resolved))81			.clone()82	}83}