use std::hash::{Hash, Hasher};
use std::panic::Location;
use std::sync::Arc;
use crate::core::element::{Element, ElementKind};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) struct MemoCallSite(pub(crate) u64);
#[derive(Clone)]
pub(crate) struct MemoElement {
pub(crate) deps_hash: u64,
pub(crate) call_site: MemoCallSite,
pub(crate) builder: Arc<dyn Fn() -> Element>,
}
#[derive(Clone, Copy, Debug)]
pub struct Memo {
deps_hash: u64,
call_site: MemoCallSite,
}
impl Memo {
#[track_caller]
pub fn new(deps_hash: u64) -> Self {
Self {
deps_hash,
call_site: stable_memo_call_site(),
}
}
pub fn with_call_site(deps_hash: u64, call_site: u64) -> Self {
Self {
deps_hash,
call_site: MemoCallSite(call_site),
}
}
pub fn build<F, E>(self, builder: F) -> Element
where
F: Fn() -> E + 'static,
E: Into<Element>,
{
Element::new(ElementKind::Memo(MemoElement {
deps_hash: self.deps_hash,
call_site: self.call_site,
builder: Arc::new(move || builder().into()),
}))
}
}
#[track_caller]
pub(crate) fn stable_memo_call_site() -> MemoCallSite {
let location = Location::caller();
let mut hasher = rustc_hash::FxHasher::default();
location.file().hash(&mut hasher);
location.line().hash(&mut hasher);
location.column().hash(&mut hasher);
MemoCallSite(hasher.finish())
}