use crate::{Hasher, Rectangle, Size};
use std::hash::{Hash, Hasher as _};
use std::path::PathBuf;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct Handle {
id: u64,
data: Data,
}
impl Handle {
pub fn from_path<T: Into<PathBuf>>(path: T) -> Handle {
Self::from_data(Data::Path(path.into()))
}
pub fn from_pixels(
width: u32,
height: u32,
pixels: impl AsRef<[u8]> + Send + Sync + 'static,
) -> Handle {
Self::from_data(Data::Rgba {
width,
height,
pixels: Bytes::new(pixels),
})
}
pub fn from_memory(
bytes: impl AsRef<[u8]> + Send + Sync + 'static,
) -> Handle {
Self::from_data(Data::Bytes(Bytes::new(bytes)))
}
fn from_data(data: Data) -> Handle {
let mut hasher = Hasher::default();
data.hash(&mut hasher);
Handle {
id: hasher.finish(),
data,
}
}
pub fn id(&self) -> u64 {
self.id
}
pub fn data(&self) -> &Data {
&self.data
}
}
impl<T> From<T> for Handle
where
T: Into<PathBuf>,
{
fn from(path: T) -> Handle {
Handle::from_path(path.into())
}
}
impl Hash for Handle {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.id.hash(state);
}
}
#[derive(Clone)]
pub struct Bytes(Arc<dyn AsRef<[u8]> + Send + Sync + 'static>);
impl Bytes {
pub fn new(data: impl AsRef<[u8]> + Send + Sync + 'static) -> Self {
Self(Arc::new(data))
}
}
impl std::fmt::Debug for Bytes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.as_ref().as_ref().fmt(f)
}
}
impl std::hash::Hash for Bytes {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.as_ref().as_ref().hash(state);
}
}
impl AsRef<[u8]> for Bytes {
fn as_ref(&self) -> &[u8] {
self.0.as_ref().as_ref()
}
}
impl std::ops::Deref for Bytes {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.0.as_ref().as_ref()
}
}
#[derive(Clone, Hash)]
pub enum Data {
Path(PathBuf),
Bytes(Bytes),
Rgba {
width: u32,
height: u32,
pixels: Bytes,
},
}
impl std::fmt::Debug for Data {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Data::Path(path) => write!(f, "Path({path:?})"),
Data::Bytes(_) => write!(f, "Bytes(...)"),
Data::Rgba { width, height, .. } => {
write!(f, "Pixels({width} * {height})")
}
}
}
}
pub trait Renderer: crate::Renderer {
type Handle: Clone + Hash;
fn dimensions(&self, handle: &Self::Handle) -> Size<u32>;
fn draw(&mut self, handle: Self::Handle, bounds: Rectangle);
}