tessera_shard/state/
handle.rs1use std::hash::{Hash, Hasher};
2
3use tessera_ui::State;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub enum ShardStateError {
8 ControllerDropped,
10 Stale,
12}
13
14pub struct ShardState<T> {
19 value: State<T>,
20 controller: State<()>,
21}
22
23impl<T> Copy for ShardState<T> {}
24impl<T> Clone for ShardState<T> {
25 fn clone(&self) -> Self {
26 *self
27 }
28}
29impl<T> PartialEq for ShardState<T> {
30 fn eq(&self, other: &Self) -> bool {
31 self.value == other.value && self.controller == other.controller
32 }
33}
34impl<T> Eq for ShardState<T> {}
35impl<T> Hash for ShardState<T> {
36 fn hash<H: Hasher>(&self, state: &mut H) {
37 self.value.hash(state);
38 self.controller.hash(state);
39 }
40}
41
42impl<T: Send + Sync + 'static> ShardState<T> {
43 pub(crate) fn new(value: State<T>, controller: State<()>) -> Self {
44 Self { value, controller }
45 }
46
47 fn check(&self) -> Result<(), ShardStateError> {
48 if !self.controller.is_alive() {
49 Err(ShardStateError::ControllerDropped)
50 } else if !self.value.is_alive() {
51 Err(ShardStateError::Stale)
52 } else {
53 Ok(())
54 }
55 }
56
57 pub fn with<R>(&self, f: impl FnOnce(&T) -> R) -> R {
59 self.try_with(f)
60 .unwrap_or_else(|error| panic!("ShardState access failed: {error:?}"))
61 }
62
63 pub fn with_mut<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
65 self.try_with_mut(f)
66 .unwrap_or_else(|error| panic!("ShardState access failed: {error:?}"))
67 }
68
69 pub fn try_with<R>(&self, f: impl FnOnce(&T) -> R) -> Result<R, ShardStateError> {
71 self.check()?;
72 Ok(self.value.with(f))
73 }
74
75 pub fn try_with_mut<R>(&self, f: impl FnOnce(&mut T) -> R) -> Result<R, ShardStateError> {
77 self.check()?;
78 Ok(self.value.with_mut(f))
79 }
80
81 pub fn get(&self) -> T
83 where
84 T: Clone,
85 {
86 self.with(Clone::clone)
87 }
88
89 pub fn set(&self, value: T) {
91 self.with_mut(|current| *current = value);
92 }
93}