tauri_plugin_sync_state/
slice.rs1use crate::error::{Error, Result};
2use serde::{de::DeserializeOwned, Serialize};
3use serde_json::Value;
4use std::any::Any;
5use std::collections::HashMap;
6use std::sync::Mutex;
7
8pub trait SyncState: Serialize + DeserializeOwned + Clone + Send + Sync + 'static {
9 const NAME: &'static str;
10}
11
12trait StateSlice: Send + Sync {
13 fn as_any(&self) -> &dyn Any;
14 fn as_any_mut(&mut self) -> &mut dyn Any;
15 fn to_json(&self) -> Result<Value>;
16 fn replace_from_json(&mut self, value: Value) -> Result<()>;
17}
18
19impl<S: SyncState> StateSlice for S {
20 fn as_any(&self) -> &dyn Any {
21 self
22 }
23 fn as_any_mut(&mut self) -> &mut dyn Any {
24 self
25 }
26 fn to_json(&self) -> Result<Value> {
27 serde_json::to_value(self).map_err(|e| Error::Serialize(e.to_string()))
28 }
29 fn replace_from_json(&mut self, value: Value) -> Result<()> {
30 *self = serde_json::from_value(value).map_err(|e| Error::Deserialize(e.to_string()))?;
31 Ok(())
32 }
33}
34
35pub struct StateRegistry {
36 slices: Mutex<HashMap<&'static str, Box<dyn StateSlice>>>,
37}
38
39impl StateRegistry {
40 pub fn new() -> Self {
41 Self {
42 slices: Mutex::new(HashMap::new()),
43 }
44 }
45
46 pub fn insert<S: SyncState>(&self, value: S) -> Result<()> {
47 let mut map = self.slices.lock().map_err(|_| Error::LockPoisoned)?;
48 if map.contains_key(S::NAME) {
49 return Err(Error::DuplicateRegistration(S::NAME.to_owned()));
50 }
51 map.insert(S::NAME, Box::new(value));
52 Ok(())
53 }
54
55 pub fn read<S: SyncState>(&self) -> Result<S> {
56 let map = self.slices.lock().map_err(|_| Error::LockPoisoned)?;
57 let slice = map
58 .get(S::NAME)
59 .ok_or_else(|| Error::NotFound(S::NAME.to_owned()))?;
60 slice
61 .as_any()
62 .downcast_ref::<S>()
63 .cloned()
64 .ok_or_else(|| Error::TypeMismatch(S::NAME.to_owned()))
65 }
66
67 pub fn mutate<S: SyncState>(&self, f: impl FnOnce(&mut S)) -> Result<S> {
68 let mut map = self.slices.lock().map_err(|_| Error::LockPoisoned)?;
69 let slice = map
70 .get_mut(S::NAME)
71 .ok_or_else(|| Error::NotFound(S::NAME.to_owned()))?;
72 let value = slice
73 .as_any_mut()
74 .downcast_mut::<S>()
75 .ok_or_else(|| Error::TypeMismatch(S::NAME.to_owned()))?;
76 f(value);
77 Ok(value.clone())
78 }
79
80 pub fn get_json(&self, name: &str) -> Result<Value> {
81 let map = self.slices.lock().map_err(|_| Error::LockPoisoned)?;
82 map.get(name)
83 .ok_or_else(|| Error::NotFound(name.to_owned()))?
84 .to_json()
85 }
86
87 pub fn set_json(&self, name: &str, value: Value) -> Result<()> {
88 let mut map = self.slices.lock().map_err(|_| Error::LockPoisoned)?;
89 map.get_mut(name)
90 .ok_or_else(|| Error::NotFound(name.to_owned()))?
91 .replace_from_json(value)
92 }
93
94 pub fn contains(&self, name: &str) -> bool {
95 self.slices
96 .lock()
97 .map(|m| m.contains_key(name))
98 .unwrap_or(false)
99 }
100}
101
102impl Default for StateRegistry {
103 fn default() -> Self {
104 Self::new()
105 }
106}