Skip to main content

nice_plug_core/params/
persist.rs

1//! Traits and helpers for persistent fields. See the [`Params`][super::Params] trait for more
2//! information.
3
4use std::sync::Arc;
5
6/// Re-export for use in the [`Params`][super::Params] proc-macro.
7pub use serde_json::from_str as deserialize_field;
8/// Re-export for use in the [`Params`][super::Params] proc-macro.
9pub use serde_json::to_string as serialize_field;
10
11/// Handles the functionality needed for persisting a non-parameter fields in a plugin's state.
12/// These types can be used with [`Params`][super::Params]' `#[persist = "..."]` attributes.
13///
14/// This should be implemented for some type with interior mutability containing a `T`.
15//
16// TODO: Modifying these fields (or any parameter for that matter) should mark the plugin's state
17//       as dirty.
18pub trait PersistentField<'a, T>: Send + Sync
19where
20    T: serde::Serialize + serde::Deserialize<'a>,
21{
22    /// Update the stored `T` value using interior mutability.
23    fn set(&self, new_value: T);
24
25    /// Get a reference to the stored `T` value, and apply a function to it. This is used to
26    /// serialize the `T` value.
27    fn map<F, R>(&self, f: F) -> R
28    where
29        F: Fn(&T) -> R;
30}
31
32/// Wrapper for implementing an `Arc<I>` wrapper for an `I: PersistentField<T>`. Having both options
33/// gives you more flexibility in data can be shared with an editor.
34macro_rules! impl_persistent_arc {
35    ($ty:ty, T) => {
36        impl<'a, T> PersistentField<'a, T> for Arc<$ty>
37        where
38            T: serde::Serialize + serde::Deserialize<'a> + Send + Sync,
39        {
40            fn set(&self, new_value: T) {
41                PersistentField::set(self.as_ref(), new_value);
42            }
43            fn map<F, R>(&self, f: F) -> R
44            where
45                F: Fn(&T) -> R,
46            {
47                self.as_ref().map(f)
48            }
49        }
50    };
51
52    ($ty:ty, T: $($bounds:tt)*) => {
53        impl<'a, T> PersistentField<'a, T> for Arc<$ty>
54        where
55            T: $($bounds)*,
56        {
57            fn set(&self, new_value: T) {
58                self.as_ref().set(new_value);
59            }
60            fn map<F, R>(&self, f: F) -> R
61            where
62                F: Fn(&T) -> R,
63            {
64                self.as_ref().map(f)
65            }
66        }
67    };
68    ($ty:ty, $inner_ty:ty) => {
69        impl<'a> PersistentField<'a, $inner_ty> for Arc<$ty> {
70            fn set(&self, new_value: $inner_ty) {
71                self.as_ref().set(new_value);
72            }
73            fn map<F, R>(&self, f: F) -> R
74            where
75                F: Fn(&$inner_ty) -> R,
76            {
77                self.as_ref().map(f)
78            }
79        }
80    };
81}
82
83impl<'a, T> PersistentField<'a, T> for std::sync::RwLock<T>
84where
85    T: serde::Serialize + serde::Deserialize<'a> + Send + Sync,
86{
87    fn set(&self, new_value: T) {
88        *self.write().expect("Poisoned RwLock on write") = new_value;
89    }
90    fn map<F, R>(&self, f: F) -> R
91    where
92        F: Fn(&T) -> R,
93    {
94        f(&self.read().expect("Poisoned RwLock on read"))
95    }
96}
97impl_persistent_arc!(std::sync::RwLock<T>, T);
98
99impl<'a, T> PersistentField<'a, T> for parking_lot::RwLock<T>
100where
101    T: serde::Serialize + serde::Deserialize<'a> + Send + Sync,
102{
103    fn set(&self, new_value: T) {
104        *self.write() = new_value;
105    }
106    fn map<F, R>(&self, f: F) -> R
107    where
108        F: Fn(&T) -> R,
109    {
110        f(&self.read())
111    }
112}
113impl_persistent_arc!(parking_lot::RwLock<T>, T);
114
115impl<'a, T> PersistentField<'a, T> for std::sync::Mutex<T>
116where
117    T: serde::Serialize + serde::Deserialize<'a> + Send + Sync,
118{
119    fn set(&self, new_value: T) {
120        *self.lock().expect("Poisoned Mutex") = new_value;
121    }
122    fn map<F, R>(&self, f: F) -> R
123    where
124        F: Fn(&T) -> R,
125    {
126        f(&self.lock().expect("Poisoned Mutex"))
127    }
128}
129impl_persistent_arc!(std::sync::Mutex<T>, T);
130
131impl<'a, T> PersistentField<'a, T> for atomic_refcell::AtomicRefCell<T>
132where
133    T: serde::Serialize + serde::Deserialize<'a> + Send + Sync,
134{
135    fn set(&self, new_value: T) {
136        *self.borrow_mut() = new_value;
137    }
138    fn map<F, R>(&self, f: F) -> R
139    where
140        F: Fn(&T) -> R,
141    {
142        f(&self.borrow())
143    }
144}
145impl_persistent_arc!(atomic_refcell::AtomicRefCell<T>, T);
146
147macro_rules! impl_persistent_field_parking_lot_mutex {
148    ($ty:ty) => {
149        impl<'a, T> PersistentField<'a, T> for $ty
150        where
151            T: serde::Serialize + serde::Deserialize<'a> + Send + Sync,
152        {
153            fn set(&self, new_value: T) {
154                *self.lock() = new_value;
155            }
156            fn map<F, R>(&self, f: F) -> R
157            where
158                F: Fn(&T) -> R,
159            {
160                f(&self.lock())
161            }
162        }
163
164        impl_persistent_arc!($ty, T);
165    };
166}
167
168impl_persistent_field_parking_lot_mutex!(parking_lot::Mutex<T>);
169impl_persistent_field_parking_lot_mutex!(parking_lot::FairMutex<T>);
170
171macro_rules! impl_persistent_atomic {
172    ($ty:ty, $inner_ty:ty) => {
173        impl PersistentField<'_, $inner_ty> for $ty {
174            fn set(&self, new_value: $inner_ty) {
175                self.store(new_value, std::sync::atomic::Ordering::SeqCst);
176            }
177            fn map<F, R>(&self, f: F) -> R
178            where
179                F: Fn(&$inner_ty) -> R,
180            {
181                f(&self.load(std::sync::atomic::Ordering::SeqCst))
182            }
183        }
184
185        impl_persistent_arc!($ty, $inner_ty);
186    };
187}
188
189impl_persistent_atomic!(std::sync::atomic::AtomicBool, bool);
190impl_persistent_atomic!(std::sync::atomic::AtomicI8, i8);
191impl_persistent_atomic!(std::sync::atomic::AtomicI16, i16);
192impl_persistent_atomic!(std::sync::atomic::AtomicI32, i32);
193impl_persistent_atomic!(std::sync::atomic::AtomicI64, i64);
194impl_persistent_atomic!(std::sync::atomic::AtomicIsize, isize);
195impl_persistent_atomic!(std::sync::atomic::AtomicU8, u8);
196impl_persistent_atomic!(std::sync::atomic::AtomicU16, u16);
197impl_persistent_atomic!(std::sync::atomic::AtomicU32, u32);
198impl_persistent_atomic!(std::sync::atomic::AtomicU64, u64);
199impl_persistent_atomic!(std::sync::atomic::AtomicUsize, usize);
200impl_persistent_atomic!(atomic_float::AtomicF32, f32);
201impl_persistent_atomic!(atomic_float::AtomicF64, f64);
202
203impl<'a, T> PersistentField<'a, T> for crossbeam_utils::atomic::AtomicCell<T>
204where
205    T: serde::Serialize + serde::Deserialize<'a> + Copy + Send,
206{
207    fn set(&self, new_value: T) {
208        self.store(new_value);
209    }
210    fn map<F, R>(&self, f: F) -> R
211    where
212        F: Fn(&T) -> R,
213    {
214        f(&self.load())
215    }
216}
217impl_persistent_arc!(crossbeam_utils::atomic::AtomicCell<T>,
218                     T: serde::Serialize + serde::Deserialize<'a> + Copy + Send);
219
220/// Can be used with the `#[serde(with = "nice_plug::params::internals::serialize_atomic_cell")]`
221/// attribute to serialize `AtomicCell<T>`s.
222pub mod serialize_atomic_cell {
223    use crossbeam_utils::atomic::AtomicCell;
224    use serde::{Deserialize, Deserializer, Serialize, Serializer};
225
226    pub fn serialize<S, T>(cell: &AtomicCell<T>, serializer: S) -> Result<S::Ok, S::Error>
227    where
228        S: Serializer,
229        T: Serialize + Copy,
230    {
231        cell.load().serialize(serializer)
232    }
233
234    pub fn deserialize<'de, D, T>(deserializer: D) -> Result<AtomicCell<T>, D::Error>
235    where
236        D: Deserializer<'de>,
237        T: Deserialize<'de> + Copy,
238    {
239        T::deserialize(deserializer).map(AtomicCell::new)
240    }
241}