use std::ops::Range;
use std::sync::OnceLock;
use crate::entity::Entity;
pub trait EntitySource: Send + Sync + std::fmt::Debug {
fn decode(&self, span: Range<usize>) -> Entity;
}
#[derive(Debug, Clone)]
pub(crate) struct Slot {
entity: OnceLock<Entity>,
span: Range<usize>,
}
impl Slot {
pub(crate) fn decoded(entity: Entity) -> Self {
Self {
entity: OnceLock::from(entity),
span: 0..0,
}
}
pub(crate) fn lazy(span: Range<usize>) -> Self {
Self {
entity: OnceLock::new(),
span,
}
}
pub(crate) fn get(&self, source: Option<&dyn EntitySource>) -> &Entity {
self.entity.get_or_init(|| {
source
.expect("a lazy slot exists only in a model with a source")
.decode(self.span.clone())
})
}
pub(crate) fn get_mut(&mut self, source: Option<&dyn EntitySource>) -> &mut Entity {
self.get(source);
self.entity
.get_mut()
.expect("`get` just initialised the slot")
}
pub(crate) fn into_entity(self, source: Option<&dyn EntitySource>) -> Entity {
self.get(source);
self.entity
.into_inner()
.expect("`get` just initialised the slot")
}
pub(crate) fn is_decoded(&self) -> bool {
self.entity.get().is_some()
}
}