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)
}
}