use crate::core::resource::probe::HasProbe;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LoadError {
NotMine,
Failed(&'static str),
}
impl LoadError {
pub fn message(&self) -> Option<&'static str> {
match self {
LoadError::NotMine => None,
LoadError::Failed(m) => Some(m),
}
}
}
pub trait Loader<T>: 'static {
fn try_load(&self, token: &str) -> Result<T, LoadError>;
}
pub trait ProbeLoader<T: HasProbe>: Loader<T> {
fn try_probe(&self, token: &str) -> Result<T::Meta, LoadError> {
self.try_load(token).map(|v| v.extract_meta())
}
}
impl<T: HasProbe, L: Loader<T> + ?Sized> ProbeLoader<T> for L {}
impl<T, F> Loader<T> for F
where
F: Fn(&str) -> Result<T, LoadError> + 'static,
{
fn try_load(&self, token: &str) -> Result<T, LoadError> {
self(token)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::cache::HasSize;
use crate::core::resource::probe::HasProbe;
use alloc::string::{String, ToString};
#[derive(Clone, Debug, PartialEq)]
struct Img {
data: String,
w: u16,
h: u16,
}
#[derive(Clone, Debug, PartialEq)]
struct ImgMeta {
w: u16,
h: u16,
}
impl HasSize for ImgMeta {
fn cache_size(&self) -> usize {
1
}
}
impl HasProbe for Img {
type Meta = ImgMeta;
fn extract_meta(&self) -> ImgMeta {
ImgMeta {
w: self.w,
h: self.h,
}
}
}
#[test]
fn closure_loader_returns_ok() {
let loader = |token: &str| -> Result<Img, LoadError> {
if token == "logo" {
Ok(Img {
data: "bytes".to_string(),
w: 16,
h: 16,
})
} else {
Err(LoadError::NotMine)
}
};
assert_eq!(loader.try_load("logo").map(|i| (i.w, i.h)), Ok((16, 16)));
assert_eq!(loader.try_load("other"), Err(LoadError::NotMine));
}
#[test]
fn default_try_probe_runs_full_load() {
let loader = |_t: &str| -> Result<Img, LoadError> {
Ok(Img {
data: "bytes".to_string(),
w: 32,
h: 32,
})
};
let meta: Result<ImgMeta, _> = ProbeLoader::<Img>::try_probe(&loader, "anything");
assert_eq!(meta, Ok(ImgMeta { w: 32, h: 32 }));
}
#[test]
fn override_try_probe_avoids_full_load() {
struct ProbeAware;
impl Loader<Img> for ProbeAware {
fn try_load(&self, _t: &str) -> Result<Img, LoadError> {
panic!("try_load should not run when try_probe is overridden");
}
}
impl ProbeAware {
fn try_probe_override(&self, _t: &str) -> Result<ImgMeta, LoadError> {
Ok(ImgMeta { w: 64, h: 32 })
}
}
let p = ProbeAware;
assert_eq!(p.try_probe_override("hero"), Ok(ImgMeta { w: 64, h: 32 }));
}
}