cu-sensor-payloads 1.0.0-rc1

Those are standardized payloads for the Copper sensors. Feel free to contribute your own.
Documentation
use alloc::boxed::Box;
use bincode::de::Decoder;
use bincode::enc::Encoder;
use bincode::error::{DecodeError, EncodeError};
use bincode::{Decode, Encode};
use core::fmt::Debug;
use core::marker::PhantomData;
use cu29::prelude::*;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

pub trait CuHandlePayloadMeta {
    const TYPE_PATH: &'static str;
    const SHORT_TYPE_PATH: &'static str;
    const TYPE_IDENT: Option<&'static str>;
    const CRATE_NAME: Option<&'static str>;
    const MODULE_PATH: Option<&'static str>;
}

pub trait CuHandlePayloadInit: Debug + Send + Sync + 'static {
    fn boxed_init() -> Box<Self>;

    fn decode_boxed<D>(decoder: &mut D) -> Result<Box<Self>, DecodeError>
    where
        Self: Decode<()>,
        D: Decoder<Context = ()>,
    {
        let inner = Self::decode(decoder)?;
        Ok(Box::new(inner))
    }
}

#[derive(Reflect)]
#[reflect(from_reflect = false, no_field_bounds, type_path = false)]
pub struct CuHandlePayload<T, M>
where
    T: Debug + Send + Sync + 'static,
    M: CuHandlePayloadMeta + 'static,
{
    #[reflect(ignore)]
    pub handle: CuHandle<T>,
    #[reflect(ignore)]
    _meta: PhantomData<M>,
}

impl<T, M> Debug for CuHandlePayload<T, M>
where
    T: Debug + Send + Sync + 'static,
    M: CuHandlePayloadMeta + 'static,
{
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("CuHandlePayload")
            .field("handle", &self.handle)
            .finish()
    }
}

impl<T, M> Clone for CuHandlePayload<T, M>
where
    T: Debug + Send + Sync + 'static,
    M: CuHandlePayloadMeta + 'static,
{
    fn clone(&self) -> Self {
        Self {
            handle: self.handle.clone(),
            _meta: PhantomData,
        }
    }
}

impl<T, M> Default for CuHandlePayload<T, M>
where
    T: CuHandlePayloadInit,
    M: CuHandlePayloadMeta + 'static,
{
    fn default() -> Self {
        Self::from_box(T::boxed_init())
    }
}

impl<T, M> TypePath for CuHandlePayload<T, M>
where
    T: Debug + Send + Sync + 'static,
    M: CuHandlePayloadMeta + 'static,
{
    fn type_path() -> &'static str {
        M::TYPE_PATH
    }

    fn short_type_path() -> &'static str {
        M::SHORT_TYPE_PATH
    }

    fn type_ident() -> Option<&'static str> {
        M::TYPE_IDENT
    }

    fn crate_name() -> Option<&'static str> {
        M::CRATE_NAME
    }

    fn module_path() -> Option<&'static str> {
        M::MODULE_PATH
    }
}

impl<T, M> CuHandlePayload<T, M>
where
    T: Debug + Send + Sync + 'static,
    M: CuHandlePayloadMeta + 'static,
{
    pub fn from_handle(handle: CuHandle<T>) -> Self {
        Self {
            handle,
            _meta: PhantomData,
        }
    }

    pub fn new_detached(inner: T) -> Self {
        Self::from_handle(CuHandle::new_detached(inner))
    }

    pub fn from_box(inner: Box<T>) -> Self {
        Self::from_handle(CuHandle::new_detached_box(inner))
    }

    pub fn with_inner<R>(&self, f: impl FnOnce(&T) -> R) -> R {
        self.handle.with_inner(|inner| f(inner.as_ref()))
    }

    pub fn with_inner_mut<R>(&mut self, f: impl FnOnce(&mut T) -> R) -> R {
        self.handle.with_inner_mut(|inner| f(inner.as_mut()))
    }
}

impl<T, M> Serialize for CuHandlePayload<T, M>
where
    T: Debug + Send + Sync + Serialize + 'static,
    M: CuHandlePayloadMeta + 'static,
{
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        self.with_inner(|inner| inner.serialize(serializer))
    }
}

impl<'de, T, M> Deserialize<'de> for CuHandlePayload<T, M>
where
    T: Debug + Send + Sync + Deserialize<'de> + 'static,
    M: CuHandlePayloadMeta + 'static,
{
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        let inner = Box::<T>::deserialize(deserializer)?;
        Ok(Self::from_box(inner))
    }
}

impl<T, M> Encode for CuHandlePayload<T, M>
where
    T: Debug + Send + Sync + Encode + 'static,
    M: CuHandlePayloadMeta + 'static,
{
    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
        self.with_inner(|inner| inner.encode(encoder))
    }
}

impl<T, M> Decode<()> for CuHandlePayload<T, M>
where
    T: CuHandlePayloadInit + Decode<()>,
    M: CuHandlePayloadMeta + 'static,
{
    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, DecodeError> {
        let inner = T::decode_boxed(decoder)?;
        Ok(Self::from_box(inner))
    }
}