npsd 0.2.0

Network payload serializer / deserializer framework
Documentation
use std::{borrow::Cow, cell::{Cell, Ref, RefCell, UnsafeCell}, pin::Pin, ptr, rc::Rc, sync::{Arc, Weak}};

use super::{Error, Middleware, Payload, IntoPayload, FromPayload};

macro_rules! impl_payload_smart_slice_traits {
    ($container:ident) => {
        impl<'a, C, T: IntoPayload<C>> IntoPayload<C> for $container<T> {
            #[inline]
            fn into_payload<'b, M: Middleware<'b>>(&self, ctx: &mut C, next: &mut M) -> Result<(), Error> {
                next.into_payload(self.as_ref(), ctx)
            }
        }

        impl<'a, C, T: FromPayload<'a, C>> FromPayload<'a, C> for $container<T> 
            where T: ToOwned 
        {
            #[inline]
            fn from_payload<M: Middleware<'a>>(ctx: &mut C, next: &mut M) -> Result<Self, Error> {
                Ok($container::new(next.from_payload::<C, T>(ctx)?))
            }
        }

        impl<'a, C, T: Payload<'a, C>> Payload<'a, C> for $container<T> 
            where T: Clone {}

        impl<'a, C, T: IntoPayload<C>> IntoPayload<C> for $container<[T]> {
            #[inline]
            fn into_payload<'b, M: Middleware<'b>>(&self, ctx: &mut C, next: &mut M) -> Result<(), Error> {
                next.into_payload(&self.as_ref(), ctx)
            }
        }

        impl<'a, C, T: FromPayload<'a, C>> FromPayload<'a, C> for $container<[T]> 
            where T: Clone + 'a 
        {
            #[inline]
            fn from_payload<M: Middleware<'a>>(ctx: &mut C, next: &mut M) -> Result<Self, Error> {
                Ok($container::from(next.from_payload::<C, Cow<'a, [T]>>(ctx)?.into_owned()))
            }
        }

        impl<'a, C, T: Payload<'a, C> + 'a> Payload<'a, C> for $container<[T]> 
            where T: Clone {}

    };
}

impl_payload_smart_slice_traits!(Box);
impl_payload_smart_slice_traits!(Arc);
impl_payload_smart_slice_traits!(Rc);

impl<'a, C, T: IntoPayload<C> + Copy> IntoPayload<C> for UnsafeCell<T> {
    #[inline]
    fn into_payload<'b, M: Middleware<'b>>(&self, ctx: &mut C, next: &mut M) -> Result<(), Error> {
        next.into_payload::<C, T>(unsafe { &*self.get() }, ctx)
    }
}

impl<'a, C, T: FromPayload<'a, C>> FromPayload<'a, C> for UnsafeCell<T> {
    #[inline]
    fn from_payload<M: Middleware<'a>>(ctx: &mut C, next: &mut M) -> Result<Self, Error> {
        Ok(UnsafeCell::new(next.from_payload::<C, T>(ctx)?))
    }
}

impl<'a, C, T: Payload<'a, C> + Copy> Payload<'a, C> for UnsafeCell<T> {}

impl<'a, C, T: IntoPayload<C> + Copy> IntoPayload<C> for Cell<T> {
    #[inline]
    fn into_payload<'m, M: Middleware<'m>>(&self, ctx: &mut C, next: &mut M) -> Result<(), Error> {
        next.into_payload::<C, T>(&self.get(), ctx)
    }
}

impl<'a, C, T: FromPayload<'a, C>> FromPayload<'a, C> for Cell<T> {
    #[inline]
    fn from_payload<M: Middleware<'a>>(ctx: &mut C, next: &mut M) -> Result<Self, Error> {
        Ok(Cell::new(next.from_payload::<C, T>(ctx)?))
    }
}

impl<'a, C, T: Payload<'a, C> + Copy> Payload<'a, C> for Cell<T> {}

impl<'a, C, T: IntoPayload<C>> IntoPayload<C> for Ref<'a, T> {
    #[inline]
    fn into_payload<'m, M: Middleware<'m>>(&self, ctx: &mut C, next: &mut M) -> Result<(), Error> {
        next.into_payload(&**self, ctx)
    }
}

impl<'a, C, T: FromPayload<'a, C>> FromPayload<'a, C> for Ref<'a, T> {
    fn from_payload<M: Middleware<'a>>(ctx: &mut C, next: &mut M) -> Result<Self, Error> {
        let boxed_ref_cell = Box::new(RefCell::new(next.from_payload::<C, T>(ctx)?));
        let cell: &'a RefCell<T> = Box::leak(boxed_ref_cell);

        let borrowed = cell.borrow();
        let borrowed_ptr: *const T = &*borrowed;

        Ok(unsafe { ptr::read(borrowed_ptr as *const Ref<'a, T>) })
    }
}

impl<'a, C, T: Payload<'a, C>> Payload<'a, C> for Ref<'a, T> {}

impl<'a, C, T: IntoPayload<C>> IntoPayload<C> for RefCell<T> {
    #[inline]
    fn into_payload<'m, M: Middleware<'m>>(&self, ctx: &mut C, next: &mut M) -> Result<(), Error> {
        next.into_payload(&*self.borrow(), ctx)
    }
}

impl<'a, C, T: FromPayload<'a, C>> FromPayload<'a, C> for RefCell<T> {
    #[inline]
    fn from_payload<M: Middleware<'a>>(ctx: &mut C, next: &mut M) -> Result<Self, Error> {
        Ok(RefCell::new(next.from_payload::<C, T>(ctx)?))
    }
}

impl<'a, C, T: Payload<'a, C>> Payload<'a, C> for RefCell<T> {}

impl<'a, C, T: IntoPayload<C>> IntoPayload<C> for Pin<Box<T>> {
    #[inline]
    fn into_payload<'m, M: Middleware<'m>>(&self, ctx: &mut C, next: &mut M) -> Result<(), Error> {
        next.into_payload(self.as_ref().get_ref(), ctx)
    }
}

impl<'a, C, T: FromPayload<'a, C>> FromPayload<'a, C> for Pin<Box<T>> {
    #[inline]
    fn from_payload<M: Middleware<'a>>(ctx: &mut C, next: &mut M) -> Result<Self, Error> {
        Ok(Pin::from(Box::pin(next.from_payload::<C, T>(ctx)?)))
    }
}

impl<'a, C, T: Payload<'a, C>> Payload<'a, C> for Pin<Box<T>> {}

impl<'a, C, T: IntoPayload<C>> IntoPayload<C> for Weak<T> {
    fn into_payload<'m, M: Middleware<'m>>(&self, ctx: &mut C, next: &mut M) -> Result<(), Error> {
        if let Some(strong) = self.upgrade() {
            next.into_payload(&strong, ctx)
        } else {
            Err(Error::WeakUpgrade)
        }
    }
}

impl<'a, C, T: FromPayload<'a, C> + Clone> FromPayload<'a, C> for Weak<T> {
    #[inline]
    fn from_payload<M: Middleware<'a>>(ctx: &mut C, next: &mut M) -> Result<Self, Error> {
        Ok(Arc::downgrade(&next.from_payload::<C, Arc<T>>(ctx)?))
    }
}

impl<'a, C, T: Payload<'a, C> + Clone> Payload<'a, C> for Weak<T> {}