dremoc-service 0.1.7

Microservices utilities
Documentation
use dremoc_sync::watch::{channel, Receiver, Sender};
use remoc::{codec, RemoteSend};
use serde::{Deserialize, Serialize};
use std::fmt::{Debug, Display};

pub trait Stateful {
    type StateSet;

    fn get_state(&self) -> &Self::StateSet;
    fn get_state_mut(&mut self) -> &mut Self::StateSet;
}

pub struct State<
    T,
    const READ: bool = true,
    const WRITE: bool = true,
    const WATCH: bool = true,
    Codec = codec::Default,
> {
    value: T,
    watch: Option<Box<Sender<T, Codec>>>,
}

impl<T, const READ: bool, const WRITE: bool, Codec> State<T, READ, WRITE, false, Codec> {
    pub fn new(value: T) -> Self {
        Self { value, watch: None }
    }

    pub fn to_unwatched(self) -> Self {
        self
    }
}

impl<T: RemoteSend + Clone, const READ: bool, const WRITE: bool, Codec>
    State<T, READ, WRITE, false, Codec>
{
    pub fn to_watched(self) -> State<T, READ, WRITE, true, Codec> {
        self.into()
    }
}

impl<T: Default, const READ: bool, const WRITE: bool, Codec> Default
    for State<T, READ, WRITE, false, Codec>
{
    fn default() -> Self {
        Self::new(T::default())
    }
}

impl<T: RemoteSend + Clone, const READ: bool, const WRITE: bool, Codec>
    State<T, READ, WRITE, true, Codec>
{
    pub fn new(value: T) -> Self {
        let (tx, _) = channel(value.clone());
        Self {
            value,
            watch: Some(Box::new(tx)),
        }
    }

    pub fn to_watched(self) -> Self {
        self
    }
}

impl<T, const READ: bool, const WRITE: bool, Codec> State<T, READ, WRITE, true, Codec> {
    pub fn to_unwatched(self) -> State<T, READ, WRITE, false, Codec> {
        self.into()
    }
}

impl<T: Default + RemoteSend + Clone, const READ: bool, const WRITE: bool, Codec> Default
    for State<T, READ, WRITE, true, Codec>
{
    fn default() -> Self {
        Self::new(T::default())
    }
}

impl<T: Debug, const READ: bool, const WRITE: bool, const WATCH: bool, Codec> Debug
    for State<T, READ, WRITE, WATCH, Codec>
{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.value.fmt(f)
    }
}

impl<T: Display, const READ: bool, const WRITE: bool, const WATCH: bool, Codec> Display
    for State<T, READ, WRITE, WATCH, Codec>
{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.value.fmt(f)
    }
}

impl<T: Clone, const READ: bool, const WRITE: bool, Codec> Clone
    for State<T, READ, WRITE, false, Codec>
{
    fn clone(&self) -> Self {
        Self::new(self.value.clone())
    }
}

impl<T: RemoteSend + Clone + Clone, const READ: bool, const WRITE: bool, Codec> Clone
    for State<T, READ, WRITE, true, Codec>
{
    fn clone(&self) -> Self {
        Self::new(self.value.clone())
    }
}

impl<T, const READ: bool, const WRITE: bool, const WATCH: bool, Codec> std::ops::Deref
    for State<T, READ, WRITE, WATCH, Codec>
{
    type Target = T;

    #[inline(always)]
    fn deref(&self) -> &Self::Target {
        &self.get()
    }
}

impl<T, const READ: bool, const WRITE: bool, const WATCH: bool, Codec>
    State<T, READ, WRITE, WATCH, Codec>
{
    #[inline(always)]
    pub fn get(&self) -> &T {
        &self.value
    }
}

impl<T, const READ: bool, const WRITE: bool, Codec> State<T, READ, WRITE, false, Codec> {
    #[inline(always)]
    pub fn set(&mut self, value: T) {
        self.value = value;
    }

    #[inline(always)]
    pub fn modify(&mut self, f: impl FnOnce(&mut T)) {
        f(&mut self.value);
    }
}

impl<T: Clone + Send + 'static, const READ: bool, const WRITE: bool, Codec>
    State<T, READ, WRITE, true, Codec>
{
    #[inline(always)]
    pub fn set(&mut self, value: T) {
        self.value = value;
        self.send_value();
    }

    #[inline(always)]
    pub fn modify(&mut self, f: impl FnOnce(&mut T)) {
        f(&mut self.value);
        self.send_value();
    }

    pub fn subscribe(&self) -> Receiver<T, Codec> {
        self.watch.as_ref().unwrap().subscribe()
    }

    #[inline(always)]
    fn send_value(&mut self) {
        let watch = self.watch.as_ref().unwrap();
        if !watch.is_closed() {
            let _ = watch.send(self.value.clone());
        }
    }
}

impl<T: Clone, const WRITE: bool, const WATCH: bool, Codec> State<T, true, WRITE, WATCH, Codec> {
    #[inline(always)]
    pub fn remote_get(&self) -> T {
        self.get().clone()
    }
}

impl<T, const READ: bool, Codec> State<T, READ, true, false, Codec> {
    #[inline(always)]
    pub fn remote_set(&mut self, value: T) {
        self.set(value);
    }
}

impl<T: Clone + Send + 'static, const READ: bool, Codec> State<T, READ, true, true, Codec> {
    #[inline(always)]
    pub fn remote_set(&mut self, value: T) {
        self.set(value);
    }
}

impl<T: Serialize, const READ: bool, const WRITE: bool, Codec> Serialize
    for State<T, READ, WRITE, false, Codec>
{
    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        self.value.serialize(serializer)
    }
}

impl<T: RemoteSend + Clone + Sync, const READ: bool, const WRITE: bool, Codec: codec::Codec>
    Serialize for State<T, READ, WRITE, true, Codec>
{
    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut struct_serializer = serde::Serializer::serialize_struct(serializer, "State", 2)?;
        serde::ser::SerializeStruct::serialize_field(&mut struct_serializer, "value", &self.value)?;
        serde::ser::SerializeStruct::serialize_field(
            &mut struct_serializer,
            "watch",
            self.watch.as_ref().unwrap(),
        )?;

        serde::ser::SerializeStruct::end(struct_serializer)
    }
}

impl<'de, T: Deserialize<'de>, const READ: bool, const WRITE: bool, Codec> Deserialize<'de>
    for State<T, READ, WRITE, false, Codec>
{
    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        T::deserialize(deserializer).map(Self::new)
    }
}

impl<
        'de,
        T: RemoteSend + Clone + Sync,
        const READ: bool,
        const WRITE: bool,
        Codec: codec::Codec,
    > Deserialize<'de> for State<T, READ, WRITE, true, Codec>
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        #[derive(Deserialize)]
        #[serde(bound(deserialize = "T: RemoteSend, Codec: codec::Codec"))]
        struct StateDeserializer<T: Clone + Sync, Codec> {
            value: T,
            watch: Sender<T, Codec>,
        }

        let StateDeserializer { value, watch } = serde::Deserialize::deserialize(deserializer)?;
        Ok(Self {
            value: value,
            watch: Some(Box::new(watch)),
        })
    }
}

impl<T: RemoteSend + Clone, const READ: bool, const WRITE: bool, Codec>
    Into<State<T, READ, WRITE, true, Codec>> for State<T, READ, WRITE, false, Codec>
{
    fn into(self) -> State<T, READ, WRITE, true, Codec> {
        State::<T, READ, WRITE, true, Codec>::new(self.value)
    }
}

impl<T, const READ: bool, const WRITE: bool, Codec> Into<State<T, READ, WRITE, false, Codec>>
    for State<T, READ, WRITE, true, Codec>
{
    fn into(self) -> State<T, READ, WRITE, false, Codec> {
        State::<T, READ, WRITE, false, Codec>::new(self.value)
    }
}