tinycbor 0.12.2

A tiny CBOR codec library.
Documentation
use crate::Encoder;
use crate::{CborLen, Decode, Decoder, Encode, primitive};

impl<T: Encode + ?Sized> Encode for &T {
    fn encode<W: embedded_io::Write>(&self, e: &mut crate::Encoder<W>) -> Result<(), W::Error> {
        (*self).encode(e)
    }
}

impl<T: CborLen + ?Sized> CborLen for &T {
    fn cbor_len(&self) -> usize {
        (*self).cbor_len()
    }
}

impl<T: Encode + ?Sized> Encode for &mut T {
    fn encode<W: embedded_io::Write>(&self, e: &mut crate::Encoder<W>) -> Result<(), W::Error> {
        (**self).encode(e)
    }
}

impl<T: CborLen + ?Sized> CborLen for &mut T {
    fn cbor_len(&self) -> usize {
        (**self).cbor_len()
    }
}

#[cfg(feature = "alloc")]
impl<'b, T: Decode<'b>> Decode<'b> for alloc::boxed::Box<T> {
    type Error = T::Error;

    fn decode(d: &mut Decoder<'b>) -> Result<Self, T::Error> {
        T::decode(d).map(alloc::boxed::Box::new)
    }
}

#[cfg(feature = "alloc")]
impl<T: Encode + ?Sized> Encode for alloc::boxed::Box<T> {
    fn encode<W: embedded_io::Write>(&self, e: &mut Encoder<W>) -> Result<(), W::Error> {
        (**self).encode(e)
    }
}

#[cfg(feature = "alloc")]
impl<T: CborLen + ?Sized> CborLen for alloc::boxed::Box<T> {
    fn cbor_len(&self) -> usize {
        (**self).cbor_len()
    }
}

#[cfg(feature = "alloc")]
impl<'a, 'b, T> Decode<'b> for alloc::borrow::Cow<'a, T>
where
    T: alloc::borrow::ToOwned + ?Sized + 'a,
    &'a T: Decode<'b>,
    T::Owned: Decode<'b>,
{
    type Error = <T::Owned as Decode<'b>>::Error;

    fn decode(d: &mut Decoder<'b>) -> Result<Self, Self::Error> {
        if let Ok(borrowed) = <&'a T>::decode(d) {
            return Ok(alloc::borrow::Cow::Borrowed(borrowed));
        }

        Ok(alloc::borrow::Cow::Owned(T::Owned::decode(d)?))
    }
}

#[cfg(feature = "alloc")]
impl<T> Encode for alloc::borrow::Cow<'_, T>
where
    T: Encode + alloc::borrow::ToOwned + ?Sized,
{
    fn encode<W: embedded_io::Write>(&self, e: &mut Encoder<W>) -> Result<(), W::Error> {
        self.as_ref().encode(e)
    }
}

#[cfg(feature = "alloc")]
impl<T> CborLen for alloc::borrow::Cow<'_, T>
where
    T: CborLen + alloc::borrow::ToOwned + ?Sized,
{
    fn cbor_len(&self) -> usize {
        self.as_ref().cbor_len()
    }
}

impl<'a, T: Decode<'a>> Decode<'a> for Option<T> {
    type Error = T::Error;

    fn decode(d: &mut Decoder<'a>) -> Result<Self, T::Error> {
        if Ok(crate::Type::Null) == d.datatype() {
            d.read().expect("NULL was peeked");
            return Ok(None);
        }
        T::decode(d).map(Some)
    }
}

impl<T: Encode> Encode for Option<T> {
    fn encode<W: embedded_io::Write>(&self, e: &mut Encoder<W>) -> Result<(), W::Error> {
        if let Some(x) = self {
            x.encode(e)?;
        } else {
            primitive::Null.encode(e)?;
        }
        Ok(())
    }
}

impl<T: CborLen> CborLen for Option<T> {
    fn cbor_len(&self) -> usize {
        if let Some(x) = self { x.cbor_len() } else { 1 }
    }
}

impl<'b, T: Decode<'b>> Decode<'b> for core::num::Wrapping<T> {
    type Error = T::Error;

    fn decode(d: &mut Decoder<'b>) -> Result<Self, Self::Error> {
        T::decode(d).map(core::num::Wrapping)
    }
}

impl<T: Encode> Encode for core::num::Wrapping<T> {
    fn encode<W: embedded_io::Write>(&self, e: &mut Encoder<W>) -> Result<(), W::Error> {
        self.0.encode(e)
    }
}

impl<T: CborLen> CborLen for core::num::Wrapping<T> {
    fn cbor_len(&self) -> usize {
        self.0.cbor_len()
    }
}

impl<'b, T: Decode<'b>> Decode<'b> for core::cell::Cell<T> {
    type Error = T::Error;

    fn decode(d: &mut Decoder<'b>) -> Result<Self, Self::Error> {
        T::decode(d).map(core::cell::Cell::new)
    }
}

impl<T: Encode + Copy> Encode for core::cell::Cell<T> {
    fn encode<W: embedded_io::Write>(&self, e: &mut Encoder<W>) -> Result<(), W::Error> {
        self.get().encode(e)
    }
}

impl<T: CborLen + Copy> CborLen for core::cell::Cell<T> {
    fn cbor_len(&self) -> usize {
        self.get().cbor_len()
    }
}

impl<'b, T: Decode<'b>> Decode<'b> for core::cell::RefCell<T> {
    type Error = T::Error;

    fn decode(d: &mut Decoder<'b>) -> Result<Self, Self::Error> {
        T::decode(d).map(core::cell::RefCell::new)
    }
}

impl<T: Encode + ?Sized> Encode for core::cell::RefCell<T> {
    fn encode<W: embedded_io::Write>(&self, e: &mut Encoder<W>) -> Result<(), W::Error> {
        self.borrow().encode(e)
    }
}

impl<T: CborLen + ?Sized> CborLen for core::cell::RefCell<T> {
    fn cbor_len(&self) -> usize {
        self.borrow().cbor_len()
    }
}

#[cfg(test)]
mod tests {
    use crate::test;

    #[test]
    fn option() {
        assert!(test::<Option<u32>>(None, &[0xf6]).unwrap());
        assert!(test::<Option<u32>>(Some(42), &[0x18, 0x2a]).unwrap());
        assert!(test::<Option<i32>>(Some(-100), &[0x38, 0x63]).unwrap());
        assert!(test::<Option<&str>>(None, &[0xf6]).unwrap());
        assert!(
            test::<Option<&str>>(Some("hello"), &[0x65, 0x68, 0x65, 0x6c, 0x6c, 0x6f]).unwrap()
        );

        #[cfg(feature = "alloc")]
        {
            use alloc::string::String;
            assert!(test::<Option<String>>(None, &[0xf6]).unwrap());
            assert!(
                test::<Option<String>>(Some(String::from("test")), &[0x64, 0x74, 0x65, 0x73, 0x74])
                    .unwrap()
            );
        }
    }
}