Skip to main content

tauri_plugin_sync_state/
slice.rs

1use 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}