amethystate_core/primitives/
field_core.rs1use crate::change::Change;
2use crate::primitives::signal::{Signal, SignalSubscription, held};
3use serde::Serialize;
4use serde::de::DeserializeOwned;
5use std::sync::{Arc, Mutex};
6use uuid::Uuid;
7
8pub trait FieldValue: DeserializeOwned + Serialize + Clone + Send + Sync + 'static {}
9impl<T: DeserializeOwned + Serialize + Clone + Send + Sync + 'static> FieldValue for T {}
10
11pub type DeclaredRule<T> = Arc<dyn Fn(&mut T) + Send + Sync + 'static>;
13
14pub struct FieldCore<T> {
15 pub signal: Signal<T>,
16 pub rules: Arc<Mutex<Vec<DeclaredRule<T>>>>,
17}
18
19impl<T> Clone for FieldCore<T> {
20 fn clone(&self) -> Self {
21 Self {
22 signal: self.signal.clone(),
23 rules: self.rules.clone(),
24 }
25 }
26}
27
28impl<T: Clone + 'static> FieldCore<T> {
29 pub fn new_with_signal(initial: Signal<T>) -> Self {
30 Self {
31 signal: initial,
32 rules: Arc::new(Mutex::new(Vec::new())),
33 }
34 }
35
36 pub fn new(initial: T) -> Self {
37 Self::new_with_signal(Signal::new(initial))
38 }
39
40 pub fn rule<F>(&self, rule: F)
43 where
44 F: Fn(&mut T) + Send + Sync + 'static,
45 {
46 held(&self.rules).push(Arc::new(rule));
47 }
48
49 pub fn ruled(&self, value: &mut T) {
51 let rules = held(&self.rules).clone();
52 for rule in rules {
53 rule(value);
54 }
55 }
56
57 pub fn get(&self) -> T {
58 self.signal.get()
59 }
60
61 #[track_caller]
62 pub fn subscribe<F>(&self, callback: F) -> SignalSubscription
63 where
64 F: for<'a> Fn(&'a T) + Send + Sync + 'static,
65 {
66 self.signal.subscribe(callback)
67 }
68
69 #[track_caller]
70 pub fn subscribe_with_source<F>(&self, callback: F) -> SignalSubscription
71 where
72 F: for<'a> Fn(&'a T, Option<Uuid>) + Send + Sync + 'static,
73 {
74 self.signal.subscribe_with_source(callback)
75 }
76
77 pub fn change(&self, value: T, source: Option<Uuid>) -> Change<T> {
79 let mut change = Change {
80 source,
81 old_value: self.get(),
82 new_value: value,
83 };
84 self.ruled(&mut change.new_value);
85 change
86 }
87}