use std::fmt::Debug;
use std::io::{Error, ErrorKind, Result};
use mime::Mime;
use url::Url;
mod curl;
mod file;
pub(crate) mod image;
pub(crate) mod prefetch;
pub(crate) mod svg;
pub(crate) use self::image::InlineImageProtocol;
pub use curl::CurlResourceHandler;
pub use file::FileResourceHandler;
pub use prefetch::{prefetch_and_wrap, CachingResourceHandler};
#[derive(Debug, Clone)]
pub struct MimeData {
pub mime_type: Option<Mime>,
pub data: Vec<u8>,
}
impl MimeData {
pub fn mime_type_essence(&self) -> Option<&str> {
self.mime_type.as_ref().map(|m| m.essence_str())
}
}
pub trait ResourceUrlHandler {
fn read_resource(&self, url: &Url) -> Result<MimeData>;
}
impl<R: ResourceUrlHandler + ?Sized> ResourceUrlHandler for &'_ R {
fn read_resource(&self, url: &Url) -> Result<MimeData> {
(*self).read_resource(url)
}
}
pub fn filter_schemes<'a>(schemes: &[&str], url: &'a Url) -> Result<&'a Url> {
if schemes.contains(&url.scheme()) {
Ok(url)
} else {
Err(Error::new(
ErrorKind::Unsupported,
format!("Unsupported scheme in {url}, expected one of {schemes:?}"),
))
}
}
pub struct DispatchingResourceHandler {
handlers: Vec<Box<dyn ResourceUrlHandler>>,
}
impl DispatchingResourceHandler {
pub fn new(handlers: Vec<Box<dyn ResourceUrlHandler>>) -> Self {
Self { handlers }
}
}
impl ResourceUrlHandler for DispatchingResourceHandler {
fn read_resource(&self, url: &Url) -> Result<MimeData> {
for handler in &self.handlers {
match handler.read_resource(url) {
Ok(data) => return Ok(data),
Err(error) if error.kind() == ErrorKind::Unsupported => {}
Err(error) => return Err(error),
}
}
Err(Error::new(
ErrorKind::Unsupported,
format!("No handler supported reading from {url}"),
))
}
}
#[derive(Debug, Clone, Copy)]
pub struct NoopResourceHandler;
impl ResourceUrlHandler for NoopResourceHandler {
fn read_resource(&self, url: &Url) -> Result<MimeData> {
Err(Error::new(
ErrorKind::Unsupported,
format!("Reading from resource {url} is not supported"),
))
}
}