pub mod manifest;
pub mod request;
pub mod shortcut;
pub mod url;
pub mod utils;
pub mod vfs;
pub mod prelude {
pub use super::utils::prelude::ResourceState;
pub use super::ResourceParams;
}
mod system;
use std::sync::Arc;
use failure::ResultExt;
use uuid::Uuid;
use crate::sched::prelude::{CountLatch, Latch};
use self::ins::{ctx, CTX};
use self::request::{Request, Response};
use self::shortcut::ShortcutResolver;
use self::system::ResourceSystem;
use self::vfs::SchemaResolver;
#[derive(Debug, Clone)]
pub struct ResourceParams {
pub shortcuts: ShortcutResolver,
pub schemas: SchemaResolver,
pub dirs: Vec<String>,
}
impl Default for ResourceParams {
fn default() -> Self {
let mut params = ResourceParams {
shortcuts: ShortcutResolver::new(),
schemas: SchemaResolver::new(),
dirs: Vec::new(),
};
#[cfg(not(target_arch = "wasm32"))]
params.schemas.add("file", self::vfs::dir::Dir::new());
#[cfg(target_arch = "wasm32")]
params.schemas.add("http", self::vfs::http::Http::new());
params
}
}
pub(crate) unsafe fn setup(params: ResourceParams) -> Result<(), failure::Error> {
debug_assert!(CTX.is_null(), "duplicated setup of resource system.");
let ctx = ResourceSystem::new(params)?;
CTX = Box::into_raw(Box::new(ctx));
Ok(())
}
pub(crate) fn load_manifests(dirs: Vec<String>) -> Result<Arc<CountLatch>, failure::Error> {
let latch = Arc::new(CountLatch::new());
for v in dirs {
let clone = latch.clone();
clone.increment();
let prefix = v.clone();
ctx().load_manifest_with_callback(v, move |rsp| {
let bytes = rsp
.with_context(|_| format!("Failed to load manifest from {}", prefix))
.unwrap();
let mut cursor = std::io::Cursor::new(bytes);
ctx().attach(&prefix, &mut cursor).unwrap();
clone.set();
})?;
}
latch.set();
Ok(latch)
}
pub(crate) unsafe fn discard() {
if CTX.is_null() {
return;
}
drop(Box::from_raw(CTX as *mut ResourceSystem));
CTX = std::ptr::null();
}
#[inline]
pub fn valid() -> bool {
unsafe { !CTX.is_null() }
}
#[inline]
pub fn resolve<T: AsRef<str>>(url: T) -> Option<String> {
ctx().resolve(url)
}
#[inline]
pub fn find<T: AsRef<str>>(filename: T) -> Option<Uuid> {
ctx().find(filename)
}
#[inline]
pub fn exists(uuid: Uuid) -> bool {
ctx().exists(uuid)
}
#[inline]
pub fn load_with_callback<T>(uuid: Uuid, func: T) -> Result<(), failure::Error>
where
T: FnOnce(Response) + Send + 'static,
{
ctx().load_with_callback(uuid, func)
}
#[inline]
pub fn load_from_with_callback<T1, T2>(filename: T1, func: T2) -> Result<(), failure::Error>
where
T1: AsRef<str>,
T2: FnOnce(Response) + Send + 'static,
{
ctx().load_from_with_callback(filename, func)
}
pub fn load(uuid: Uuid) -> Result<Request, failure::Error> {
ctx().load(uuid)
}
pub fn load_from<T: AsRef<str>>(filename: T) -> Result<Request, failure::Error> {
ctx().load_from(filename)
}
mod ins {
use super::system::ResourceSystem;
pub static mut CTX: *const ResourceSystem = std::ptr::null();
#[inline]
pub fn ctx() -> &'static ResourceSystem {
unsafe {
debug_assert!(
!CTX.is_null(),
"resource system has not been initialized properly."
);
&*CTX
}
}
}