rstm_state/
state.rs

1/*
2    Appellation: state <module>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5use crate::traits::{Halt, RawState};
6use crate::types::Halter;
7
8/// [State] is a generalized state implementation, representing the state of a system or
9/// object.
10#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
11#[cfg_attr(
12    feature = "serde",
13    derive(serde::Deserialize, serde::Serialize),
14    serde(transparent)
15)]
16#[repr(transparent)]
17pub struct State<Q: ?Sized = bool>(pub Q);
18
19impl<Q> State<Q>
20where
21    Q: RawState,
22{
23    /// a constructor method for the [`State`] type.
24    pub const fn new(state: Q) -> Self {
25        Self(state)
26    }
27    /// generate a new state by invoking the given function and capturing its output.
28    pub fn create<F>(f: F) -> Self
29    where
30        F: FnOnce() -> Q,
31    {
32        State(f())
33    }
34    /// returns a new state with a value of one.
35    pub fn one() -> Self
36    where
37        Q: num_traits::One,
38    {
39        State::create(Q::one)
40    }
41    /// returns a new state with a value of zero.
42    pub fn zero() -> Self
43    where
44        Q: num_traits::Zero,
45    {
46        State::create(Q::zero)
47    }
48    /// returns a new instance of state with a raw pointer to the inner value.
49    pub const fn as_ptr(&self) -> *const Q {
50        core::ptr::addr_of!(self.0)
51    }
52    /// returns a new instance of state with a mutable raw pointer to the inner value.
53    pub const fn as_mut_ptr(&mut self) -> *mut Q {
54        core::ptr::addr_of_mut!(self.0)
55    }
56    #[allow(clippy::missing_safety_doc)]
57    /// Casts the state to a new type, returning a new instance of [State].
58    ///
59    /// # Saftey
60    ///
61    /// This method is unsafe because it is up to the caller to ensure that the cast is valid.
62    pub unsafe fn cast<R>(self) -> State<R> {
63        unsafe { State(core::ptr::read(&self.0 as *const Q as *const R)) }
64    }
65    /// returns an immutable reference to the inner value of the state.
66    pub const fn get(&self) -> &Q {
67        &self.0
68    }
69    /// returns a mutable reference to the inner value of the state.
70    pub const fn get_mut(&mut self) -> &mut Q {
71        &mut self.0
72    }
73    /// consumes and returns the inner value of the state.
74    #[inline]
75    pub fn value(self) -> Q {
76        self.0
77    }
78    /// [State::map] applies the given function onto the inner value of the state, returning a
79    /// new state with the result.
80    pub fn map<R, F>(self, f: F) -> State<R>
81    where
82        F: FnOnce(Q) -> R,
83    {
84        State(f(self.value()))
85    }
86    /// [`replace`](core::mem::replace) the inner value of the state with the given state,
87    pub const fn replace(&mut self, state: Q) -> Q {
88        core::mem::replace(self.get_mut(), state)
89    }
90    /// Clears the state, setting it to its default value.
91    #[inline]
92    pub fn reset(&mut self) -> &mut Self
93    where
94        Q: Default,
95    {
96        self.set(Default::default());
97        self
98    }
99    /// update the state with the given value
100    pub fn set(&mut self, state: Q) {
101        self.0 = state;
102    }
103    /// [`swap`](core::mem::swap) the inner value of the state with that of the given state.
104    pub const fn swap(&mut self, other: &mut State<Q>) {
105        core::mem::swap(self.get_mut(), other.get_mut());
106    }
107    /// [`take`](core::mem::take) the inner value of the state, leaving the logical default in
108    /// its place
109    pub fn take(&mut self) -> Q
110    where
111        Q: Default,
112    {
113        core::mem::take(self.get_mut())
114    }
115    /// returns true if the current state is said to be halted.
116    pub fn is_halted(&self) -> bool
117    where
118        Q: Halt,
119    {
120        self.get().is_halted()
121    }
122    /// converts the current reference into a haltable state initialized with the current state
123    pub fn as_halt(&self) -> State<Halter<&Q>> {
124        State::new(Halter::halt(self.view()))
125    }
126    /// consumes the wrapper to create another, haltable state that is initialized with the
127    /// current state
128    pub fn into_halt(self) -> State<Halter<Q>> {
129        State::new(Halter::state(self))
130    }
131    /// consumes the current state, returning a new one with a [`Halt`](HaltState::Halt)
132    /// variant initialized with the current value.
133    pub fn halt(self) -> State<Halter<Q>> {
134        State::new(Halter::halt(self))
135    }
136    /// returns a new state with a boxed inner value.
137    pub fn boxed(self) -> State<Box<Q>> {
138        self.map(Box::new)
139    }
140    /// Converts the inner type into a boxed "any" state, returning a new instance of state
141    pub fn as_any(&self) -> State<Box<dyn std::any::Any>>
142    where
143        Q: Clone + 'static,
144    {
145        State(Box::new(self.get().clone()))
146    }
147    /// Converts the inner type into a boxed "any" state, returning a new instance of state
148    pub fn into_any(self) -> State<Box<dyn std::any::Any>>
149    where
150        Q: 'static,
151    {
152        State(Box::new(self.value()))
153    }
154
155    #[cfg(feature = "std")]
156    /// Wraps the inner value of the state with an [`Arc`] and returns a new instance of [State]
157    pub fn shared(self) -> State<std::sync::Arc<Q>> {
158        self.map(std::sync::Arc::new)
159    }
160    #[cfg(feature = "std")]
161    /// returns a shared reference to the state.
162    pub fn to_shared(&self) -> State<std::sync::Arc<Q>>
163    where
164        Q: Clone,
165    {
166        self.clone().shared()
167    }
168    /// returns a state with an owned inner value.
169    pub const fn view(&self) -> State<&Q> {
170        State(self.get())
171    }
172    /// returns a state with a mutable reference to the inner value.
173    pub const fn view_mut(&mut self) -> State<&mut Q> {
174        State(self.get_mut())
175    }
176    /// returns the `name` of the generic inner type, `Q`.
177    pub fn get_inner_type_name(&self) -> &'static str {
178        core::any::type_name::<Q>()
179    }
180    /// returns the `type id` of the generic inner type, `Q`.
181    pub fn get_inner_type_id(&self) -> core::any::TypeId
182    where
183        Q: 'static,
184    {
185        core::any::TypeId::of::<Q>()
186    }
187}