Skip to content

Commit

Permalink
loader: allow to replace entirely
Browse files Browse the repository at this point in the history
  • Loading branch information
santhosh-tekuri committed May 23, 2024
1 parent 609fbcf commit da002ca
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 35 deletions.
13 changes: 3 additions & 10 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<dyn UrlLoader>) {
self.roots.loader.register(scheme, url_loader);
/// Overrides default [`UrlLoader`] used to load schema resources
pub fn use_loader(&mut self, url_loader: Box<dyn UrlLoader>) {
self.roots.loader.use_loader(url_loader);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand Down
58 changes: 42 additions & 16 deletions src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -42,22 +42,53 @@ impl UrlLoader for FileLoader {

// --

#[derive(Default)]
pub struct SchemeUrlLoader {
loaders: HashMap<&'static str, Box<dyn UrlLoader>>,
}

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<dyn UrlLoader>) {
self.loaders.insert(scheme, url_loader);
}
}

impl UrlLoader for SchemeUrlLoader {
fn load(&self, url: &str) -> Result<Value, Box<dyn Error>> {
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<HashMap<Url, usize>>,
doc_list: AppendList<Value>,
loaders: HashMap<&'static str, Box<dyn UrlLoader>>,
loader: Box<dyn UrlLoader>,
}

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> {
Expand All @@ -77,8 +108,8 @@ impl DefaultUrlLoader {
.insert(url, self.doc_list.len() - 1);
}

pub fn register(&mut self, schema: &'static str, loader: Box<dyn UrlLoader>) {
self.loaders.insert(schema, loader);
pub fn use_loader(&mut self, loader: Box<dyn UrlLoader>) {
self.loader = loader;
}

pub(crate) fn load(&self, url: &Url) -> Result<&Value, CompileError> {
Expand All @@ -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(),
Expand Down
2 changes: 1 addition & 1 deletion tests/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn test_debug() -> Result<(), Box<dyn Error>> {
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)?;
Expand Down
13 changes: 9 additions & 4 deletions tests/examples.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -73,8 +73,11 @@ fn example_from_https() -> Result<(), Box<dyn Error>> {

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());
Expand Down Expand Up @@ -107,7 +110,9 @@ fn example_from_yaml_files() -> Result<(), Box<dyn Error>> {

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());
Expand Down
2 changes: 1 addition & 1 deletion tests/invalid-schemas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand Down
3 changes: 1 addition & 2 deletions tests/suite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ fn test_file(suite: &str, path: &str, draft: Draft) -> Result<(), Box<dyn Error>
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 {
Expand Down

0 comments on commit da002ca

Please sign in to comment.