use std::{
marker::PhantomData,
sync::{Arc, Weak},
};
use crate::{
entity::Entity,
property::{
backend::{pn_counter::PNValue, PNBackend},
traits::{FromActiveType, FromEntity, InitializeWith, PropertyError},
PropertyName,
},
};
#[derive(Debug)]
pub struct PNCounter<I>
where I: Into<PNValue> + From<PNValue> + Copy + Clone
{
pub property_name: PropertyName,
pub backend: Weak<PNBackend>,
phantom: PhantomData<I>,
}
impl<I> PNCounter<I>
where I: Into<PNValue> + From<PNValue> + Copy + Clone
{
pub fn new(property_name: PropertyName, backend: Arc<PNBackend>) -> Self {
Self { property_name, backend: Arc::downgrade(&backend), phantom: PhantomData }
}
pub fn backend(&self) -> Arc<PNBackend> { self.backend.upgrade().expect("Expected `PN` property backend to exist") }
pub fn add(&self, amount: impl Into<PNValue>) { self.backend().add(self.property_name.clone(), amount.as_i64()); }
}
impl<I: From<PNValue>> PNCounter<I>
where I: Into<PNValue> + From<PNValue> + Copy + Clone
{
pub fn value(&self) -> I {
let pn_value = self.backend().get(self.property_name.clone());
I::from(pn_value)
}
}
impl<I> FromEntity for PNCounter<I>
where I: Into<PNValue> + From<PNValue> + Copy + Clone
{
fn from_entity(property_name: PropertyName, entity: &Entity) -> Self {
let backend = entity.get_backend::<PNBackend>().expect("PNBackend should exist");
Self::new(property_name, backend)
}
}
impl<I> FromActiveType<PNCounter<I>> for I
where I: Into<PNValue> + From<PNValue> + Copy + Clone
{
fn from_active(active: PNCounter<I>) -> Result<Self, PropertyError>
where Self: Sized {
Ok(active.value())
}
}
impl<I> InitializeWith<I> for PNCounter<I>
where I: Into<PNValue> + From<PNValue> + Copy + Clone
{
fn initialize_with(entity: &Entity, property_name: PropertyName, value: &I) -> Self {
let new = Self::from_entity(property_name, entity);
new.add(*value);
new
}
}