use super::*;
pub fn get_and_write_to_node<
G: Getter<AngularState, E> + ?Sized,
const N: usize,
E: Clone + Debug,
>(
getter: &G,
system: &mut System<N>,
node: NodeID,
) -> NothingOrError<E> {
let to_set = match getter.get() {
Ok(option) => option.map(|datum| datum.value),
Err(error) => {
system.set_state_local(node, None);
return Err(error);
}
};
system.set_state_local(node, to_set);
Ok(())
}
pub fn set_to_node_state<
S: Settable<AngularState, E> + ?Sized,
const N: usize,
E: Clone + Debug,
>(
settable: &mut S,
system: &mut System<N>,
node: NodeID,
) -> NothingOrError<E> {
if let Some(state) = system.get_state_connected(node) {
settable.set(state)
} else {
Ok(())
}
}
macro_rules! error_handle_update {
($updatable: expr, $system: expr, $node: expr) => {
if let Err(error) = $updatable.update() {
$system.set_state_local($node, None);
return Err(error);
}
};
}
pub struct GetterWrapper<G, E> {
getter: G,
node: NodeID,
phantom_e: PhantomData<E>,
}
macro_rules! constructor {
($name: ident, $wrapped_field: ident, $documentation: literal) => {
impl<T, E> $name<T, E> {
#[doc = $documentation]
#[inline]
pub const fn new(node: NodeID, $wrapped_field: T) -> Self {
Self {
$wrapped_field,
node,
phantom_e: PhantomData,
}
}
}
};
}
constructor!(
GetterWrapper,
getter,
"Constructor for `GetterWrapper`. Although it is possible to construct the wrapper without `getter` implementing [`Getter`], there is no reason to do this as the object would be useless."
);
impl<G: Getter<AngularState, E>, E: Clone + Debug> DeviceUpdatable<E> for GetterWrapper<G, E> {
fn device_update<const N: usize>(&mut self, system: &mut System<N>) -> NothingOrError<E> {
error_handle_update!(self.getter, system, self.node);
get_and_write_to_node(&self.getter, system, self.node)
}
}
pub struct SettableWrapper<S, E> {
settable: S,
node: NodeID,
phantom_e: PhantomData<E>,
}
constructor!(
SettableWrapper,
settable,
"Constructor for `SettableWrapper`. Although it is possible to construct the wrapper without `settable` implementing [`Settable`], there is no reason to do this as the object would be useless."
);
impl<S: Settable<AngularState, E>, E: Clone + Debug> DeviceUpdatable<E> for SettableWrapper<S, E> {
fn device_update<const N: usize>(&mut self, system: &mut System<N>) -> NothingOrError<E> {
error_handle_update!(self.settable, system, self.node);
set_to_node_state(&mut self.settable, system, self.node)
}
}
pub struct GetterSettableWrapper<T, E> {
getter_settable: T,
node: NodeID,
phantom_e: PhantomData<E>,
}
constructor!(
GetterSettableWrapper,
getter_settable,
"Constructor for `GetterSettableWrapper`. Although it is possible to construct the wrapper without `getter_settable` implementing [`Getter`] and [`Settable`], there is no reason to do this as the object would be useless.\n\nNote that the wrapper requires that `getter_settable` implement both traits to be usable. Other wrappers are available in the [module](self) for types only implementing one of the traits."
);
impl<T, E> DeviceUpdatable<E> for GetterSettableWrapper<T, E>
where
T: Getter<AngularState, E> + Settable<AngularState, E>,
E: Clone + Debug,
{
fn device_update<const N: usize>(&mut self, system: &mut System<N>) -> NothingOrError<E> {
error_handle_update!(self.getter_settable, system, self.node);
if let Err(error) = set_to_node_state(&mut self.getter_settable, system, self.node) {
system.set_state_local(self.node, None);
return Err(error);
}
get_and_write_to_node(&self.getter_settable, system, self.node)
}
}