ankurah_core/property/value/
lww.rs1use std::{marker::PhantomData, sync::Arc};
2
3use crate::{
4 entity::Entity,
5 property::{
6 backend::{LWWBackend, PropertyBackend},
7 traits::{FromActiveType, FromEntity, PropertyError},
8 InitializeWith, Property, PropertyName, Value,
9 },
10};
11
12use ankurah_signals::{
13 signal::{Listener, ListenerGuard},
14 Signal,
15};
16
17#[derive(Clone)]
18pub struct LWW<T: Property> {
19 pub property_name: PropertyName,
20 pub backend: Arc<LWWBackend>,
21 pub entity: Entity,
22 phantom: PhantomData<T>,
23}
24
25impl<T: Property> std::fmt::Debug for LWW<T> {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 f.debug_struct("LWW").field("property_name", &self.property_name).finish()
28 }
29}
30
31impl<T: Property> LWW<T> {
32 pub fn set(&self, value: &T) -> Result<(), PropertyError> {
33 if !self.entity.is_writable() {
34 return Err(PropertyError::TransactionClosed);
35 }
36 let value = value.into_value()?;
37 self.backend.set(self.property_name.clone(), value);
38 Ok(())
39 }
40
41 pub fn get(&self) -> Result<T, PropertyError> {
42 let value = self.get_value();
43 T::from_value(value)
44 }
45
46 pub fn get_value(&self) -> Option<Value> { self.backend.get(&self.property_name) }
47}
48
49impl<T: Property> FromEntity for LWW<T> {
50 fn from_entity(property_name: PropertyName, entity: &Entity) -> Self {
51 let backend = entity.get_backend::<LWWBackend>().expect("LWW Backend should exist");
52 Self { property_name, backend, entity: entity.clone(), phantom: PhantomData }
53 }
54}
55
56impl<T: Property> FromActiveType<LWW<T>> for T {
57 fn from_active(active: LWW<T>) -> Result<Self, PropertyError>
58 where Self: Sized {
59 active.get()
60 }
61}
62
63impl<T: Property> InitializeWith<T> for LWW<T> {
64 fn initialize_with(entity: &Entity, property_name: PropertyName, value: &T) -> Self {
65 let new = Self::from_entity(property_name, entity);
66 new.set(value).unwrap();
67 new
68 }
69}
70
71impl<T: Property> ankurah_signals::Signal for LWW<T> {
72 fn listen(&self, listener: Listener) -> ListenerGuard { self.backend.listen_field(&self.property_name, listener) }
73
74 fn broadcast_id(&self) -> ankurah_signals::broadcast::BroadcastId { self.backend.field_broadcast_id(&self.property_name) }
75}
76
77impl<T: Property> ankurah_signals::Subscribe<T> for LWW<T>
78where T: Clone + Send + Sync + 'static
79{
80 fn subscribe<F>(&self, listener: F) -> ankurah_signals::SubscriptionGuard
81 where F: ankurah_signals::subscribe::IntoSubscribeListener<T> {
82 let listener = listener.into_subscribe_listener();
83 let lww = self.clone();
84 let subscription = self.listen(Arc::new(move |_| {
85 if let Ok(current_value) = lww.get() {
87 listener(current_value);
88 }
89 }));
90 ankurah_signals::SubscriptionGuard::new(subscription)
91 }
92}
93
94#[cfg(any(feature = "wasm", feature = "uniffi"))]
95pub mod ffi {
96 use super::*;
98 use crate::property::Json;
99 #[cfg(feature = "wasm")]
100 use ::wasm_bindgen::prelude::*;
101 use ankurah_derive::impl_provided_wrapper_types;
102 impl_provided_wrapper_types!("src/property/value/lww.ron");
103}
104#[cfg(any(feature = "wasm", feature = "uniffi"))]
105pub use ffi::*;