use crate::output::diagnostic;
pub use glob;
use std::collections::HashMap;
pub type BinaryData = Box<dyn AsRef<[u8]>>;
pub type ErrorData = Box<dyn std::error::Error>;
pub type UriResolver = Box<dyn Fn(&str) -> std::result::Result<BinaryData, ErrorData> + Send>;
#[cfg(feature = "curl")]
fn resolve_with_curl(uri: &str) -> Result<Vec<u8>, curl::Error> {
let mut binary_data: Vec<u8> = vec![];
let mut curl_handle = curl::easy::Easy::new();
curl_handle.url(uri)?;
{
let mut transfer = curl_handle.transfer();
transfer.write_function(|buf| {
binary_data.extend_from_slice(buf);
Ok(buf.len())
})?;
transfer.perform()?;
}
Ok(binary_data)
}
pub struct Config {
pub ignore_unknown_fields: bool,
pub allowed_proto_any_urls: Vec<glob::Pattern>,
pub diagnostic_level_overrides:
HashMap<diagnostic::Classification, (diagnostic::Level, diagnostic::Level)>,
pub uri_overrides: Vec<(glob::Pattern, Option<String>)>,
pub uri_resolver: Option<UriResolver>,
pub max_uri_resolution_depth: Option<usize>,
}
impl Default for Config {
fn default() -> Self {
Self {
ignore_unknown_fields: Default::default(),
allowed_proto_any_urls: Default::default(),
diagnostic_level_overrides: Default::default(),
uri_overrides: Default::default(),
uri_resolver: Default::default(),
max_uri_resolution_depth: Some(0),
}
}
}
impl Config {
pub fn new() -> Self {
Self::default()
}
pub fn ignore_unknown_fields(&mut self) {
self.ignore_unknown_fields = true;
}
pub fn allow_proto_any_url(&mut self, pattern: glob::Pattern) {
self.allowed_proto_any_urls.push(pattern);
}
pub fn override_diagnostic_level(
&mut self,
class: diagnostic::Classification,
minimum: diagnostic::Level,
maximum: diagnostic::Level,
) {
self.diagnostic_level_overrides
.insert(class, (minimum, maximum));
}
pub fn override_uri<S: Into<String>>(&mut self, pattern: glob::Pattern, resolve_as: Option<S>) {
self.uri_overrides
.push((pattern, resolve_as.map(|s| s.into())));
}
pub fn add_uri_resolver<F, D, E>(&mut self, resolver: F)
where
F: Fn(&str) -> Result<D, E> + Send + 'static,
D: AsRef<[u8]> + 'static,
E: std::error::Error + 'static,
{
let previous = self.uri_resolver.take();
self.uri_resolver = Some(Box::new(move |uri| match resolver(uri) {
Ok(d) => Ok(Box::new(d)),
Err(e) => match &previous {
Some(f) => f.as_ref()(uri),
None => Err(Box::new(e)),
},
}));
}
#[cfg(feature = "curl")]
pub fn add_curl_uri_resolver(&mut self) {
self.add_uri_resolver(resolve_with_curl)
}
pub fn set_max_uri_resolution_depth(&mut self, depth: Option<usize>) {
self.max_uri_resolution_depth = depth;
}
}