From da002ca97f8c59b813d10dca1a92cb1a21f7d5f9 Mon Sep 17 00:00:00 2001 From: Santhosh Kumar Tekuri Date: Fri, 24 May 2024 01:28:00 +0530 Subject: [PATCH] loader: allow to replace entirely --- src/compiler.rs | 13 +++------ src/lib.rs | 2 +- src/loader.rs | 58 +++++++++++++++++++++++++++++----------- tests/debug.rs | 2 +- tests/examples.rs | 13 ++++++--- tests/invalid-schemas.rs | 2 +- tests/suite.rs | 3 +-- 7 files changed, 58 insertions(+), 35 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index f9f435e..6cc87ce 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -129,16 +129,9 @@ impl Compiler { self.assert_content = true; } - /** - Registers [`UrlLoader`] for given url `scheme` - - # Note - - loader for `file` scheme is included by default and - - all standard meta-schemas from `http(s)://json-schema.org` are loaded internally - without network access - */ - pub fn register_url_loader(&mut self, scheme: &'static str, url_loader: Box) { - self.roots.loader.register(scheme, url_loader); + /// Overrides default [`UrlLoader`] used to load schema resources + pub fn use_loader(&mut self, url_loader: Box) { + self.roots.loader.use_loader(url_loader); } /** diff --git a/src/lib.rs b/src/lib.rs index 724baac..c3fa3f9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -118,7 +118,7 @@ pub use { compiler::{CompileError, Compiler, Draft}, content::{Decoder, MediaType}, formats::Format, - loader::UrlLoader, + loader::{FileLoader, SchemeUrlLoader, UrlLoader}, output::{ AbsoluteKeywordLocation, FlagOutput, KeywordPath, OutputError, OutputUnit, SchemaToken, }, diff --git a/src/loader.rs b/src/loader.rs index 7e929e8..37c0680 100644 --- a/src/loader.rs +++ b/src/loader.rs @@ -28,7 +28,7 @@ pub trait UrlLoader { // -- #[cfg(not(target_arch = "wasm32"))] -struct FileLoader; +pub struct FileLoader; #[cfg(not(target_arch = "wasm32"))] impl UrlLoader for FileLoader { @@ -42,22 +42,53 @@ impl UrlLoader for FileLoader { // -- +#[derive(Default)] +pub struct SchemeUrlLoader { + loaders: HashMap<&'static str, Box>, +} + +impl SchemeUrlLoader { + pub fn new() -> Self { + Self::default() + } + + /// Registers [`UrlLoader`] for given url `scheme` + pub fn register(&mut self, scheme: &'static str, url_loader: Box) { + self.loaders.insert(scheme, url_loader); + } +} + +impl UrlLoader for SchemeUrlLoader { + fn load(&self, url: &str) -> Result> { + let url = Url::parse(url)?; + let Some(loader) = self.loaders.get(url.scheme()) else { + return Err(CompileError::UnsupportedUrlScheme { + url: url.as_str().to_owned(), + } + .into()); + }; + loader.load(url.as_str()) + } +} + +// -- + pub(crate) struct DefaultUrlLoader { doc_map: RefCell>, doc_list: AppendList, - loaders: HashMap<&'static str, Box>, + loader: Box, } impl DefaultUrlLoader { pub fn new() -> Self { - let mut v = Self { + let mut loader = SchemeUrlLoader::new(); + #[cfg(not(target_arch = "wasm32"))] + loader.register("file", Box::new(FileLoader)); + Self { doc_map: Default::default(), doc_list: AppendList::new(), - loaders: Default::default(), - }; - #[cfg(not(target_arch = "wasm32"))] - v.loaders.insert("file", Box::new(FileLoader)); - v + loader: Box::new(loader), + } } pub fn get_doc(&self, url: &Url) -> Option<&Value> { @@ -77,8 +108,8 @@ impl DefaultUrlLoader { .insert(url, self.doc_list.len() - 1); } - pub fn register(&mut self, schema: &'static str, loader: Box) { - self.loaders.insert(schema, loader); + pub fn use_loader(&mut self, loader: Box) { + self.loader = loader; } pub(crate) fn load(&self, url: &Url) -> Result<&Value, CompileError> { @@ -93,12 +124,7 @@ impl DefaultUrlLoader { src: e.into(), })? } else { - let Some(loader) = self.loaders.get(url.scheme()) else { - return Err(CompileError::UnsupportedUrlScheme { - url: url.as_str().to_owned(), - }); - }; - loader + self.loader .load(url.as_str()) .map_err(|src| CompileError::LoadUrlError { url: url.as_str().to_owned(), diff --git a/tests/debug.rs b/tests/debug.rs index d807f3f..32b9914 100644 --- a/tests/debug.rs +++ b/tests/debug.rs @@ -11,7 +11,7 @@ fn test_debug() -> Result<(), Box> { compiler.enable_format_assertions(); compiler.enable_content_assertions(); let remotes = Remotes(test["remotes"].as_object().unwrap().clone()); - compiler.register_url_loader("http", Box::new(remotes)); + compiler.use_loader(Box::new(remotes)); let url = "http://debug.com/schema.json"; compiler.add_resource(url, test["schema"].clone())?; let sch = compiler.compile(url, &mut schemas)?; diff --git a/tests/examples.rs b/tests/examples.rs index c399c08..5c9eab8 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -1,6 +1,6 @@ use std::{error::Error, fs::File}; -use boon::{Compiler, Decoder, Format, MediaType, Schemas, UrlLoader}; +use boon::{Compiler, Decoder, FileLoader, Format, MediaType, Schemas, SchemeUrlLoader, UrlLoader}; use serde::de::IgnoredAny; use serde_json::{json, Value}; use url::Url; @@ -73,8 +73,11 @@ fn example_from_https() -> Result<(), Box> { let mut schemas = Schemas::new(); let mut compiler = Compiler::new(); - compiler.register_url_loader("http", Box::new(HttpUrlLoader)); - compiler.register_url_loader("https", Box::new(HttpUrlLoader)); + let mut loader = SchemeUrlLoader::new(); + loader.register("file", Box::new(FileLoader)); + loader.register("http", Box::new(HttpUrlLoader)); + loader.register("https", Box::new(HttpUrlLoader)); + compiler.use_loader(Box::new(loader)); let sch_index = compiler.compile(schema_url, &mut schemas)?; let result = schemas.validate(&instance, sch_index); assert!(result.is_ok()); @@ -107,7 +110,9 @@ fn example_from_yaml_files() -> Result<(), Box> { let mut schemas = Schemas::new(); let mut compiler = Compiler::new(); - compiler.register_url_loader("file", Box::new(FileUrlLoader)); + let mut loader = SchemeUrlLoader::new(); + loader.register("file", Box::new(FileUrlLoader)); + compiler.use_loader(Box::new(loader)); let sch_index = compiler.compile(schema_file, &mut schemas)?; let result = schemas.validate(&instance, sch_index); assert!(result.is_ok()); diff --git a/tests/invalid-schemas.rs b/tests/invalid-schemas.rs index aa841d1..590d065 100644 --- a/tests/invalid-schemas.rs +++ b/tests/invalid-schemas.rs @@ -48,7 +48,7 @@ fn compile(test: &Test) -> Result<(), CompileError> { let mut compiler = Compiler::new(); let url = "http://fake.com/schema.json"; if let Some(remotes) = &test.remotes { - compiler.register_url_loader("http", Box::new(Remotes(remotes.clone()))); + compiler.use_loader(Box::new(Remotes(remotes.clone()))); } compiler.add_resource(url, test.schema.clone())?; compiler.compile(url, &mut schemas)?; diff --git a/tests/suite.rs b/tests/suite.rs index bbb12d2..e2536d2 100644 --- a/tests/suite.rs +++ b/tests/suite.rs @@ -85,8 +85,7 @@ fn test_file(suite: &str, path: &str, draft: Draft) -> Result<(), Box compiler.enable_format_assertions(); compiler.enable_content_assertions(); } - compiler.register_url_loader("http", Box::new(RemotesLoader(suite.to_owned()))); - compiler.register_url_loader("https", Box::new(RemotesLoader(suite.to_owned()))); + compiler.use_loader(Box::new(RemotesLoader(suite.to_owned()))); compiler.add_resource(url, group.schema)?; let sch_index = compiler.compile(url, &mut schemas)?; for test in group.tests {