minicbor-adapters 0.0.8

Adapters between `minicbor` and other crates such as `heapless` and `cboritem`
Documentation
//! Tools for encoding and decoding heapless collections in minicbor
//!
//! These can only work on the owned [`heapless::String`] and [`heapless::Vec`] types and not the
//! corresponding `*View` because minicbor's decoding produces an owned type (possibly with
//! references to the input) and does not populate a `&mut` (like a `.decode_into()` would).

use crate::with::{OurCborLen, OurDecode, OurEncode};
use heapless::CapacityError;

impl<'b, C, const N: usize> OurDecode<'b, C> for heapless::String<N> {
    fn decode(
        d: &mut minicbor::Decoder<'b>,
        _ctx: &mut C,
    ) -> Result<Self, minicbor::decode::Error> {
        // Context gets discarded: At this level, there's no exotic CBOR allowed any more.
        let mut result = heapless::String::new();
        for chunk in d.str_iter()? {
            result.push_str(chunk?).map_err(|CapacityError { .. }| {
                minicbor::decode::Error::message("string too long")
            })?;
        }
        Ok(result)
    }
}

impl<'b, T, C, const N: usize> OurDecode<'b, C> for heapless::Vec<T, N>
where
    T: minicbor::Decode<'b, C>,
{
    fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
        // This is inspired by the decode_sequential macro in minicbor
        let iter: minicbor::decode::ArrayIterWithCtx<C, T> = d.array_iter_with(ctx)?;
        let mut vec = heapless::Vec::new();
        for item in iter {
            vec.push(item?)
                .map_err(|_| minicbor::decode::Error::message("vec capacity exceeded"))?;
        }
        Ok(vec)
    }
}

// These are all copy-pasted implementations because I didn't get the proper version, which would
// be like
//
// macro_rules! impl_encode_cborlen_through_deref {
//     ($t:ident $(<$($generics:tt $(: $condition:tt )?),*>)?) => {
//
//
// to run when there are also const args in the mix. (See also
// https://github.com/rust-lang/rfcs/pull/3442)

impl<C, T, const N: usize> OurEncode<C> for heapless::Vec<T, N>
where
    T: minicbor::Encode<C>,
{
    fn encode<W: minicbor::encode::Write>(
        &self,
        e: &mut minicbor::Encoder<W>,
        ctx: &mut C,
    ) -> Result<(), minicbor::encode::Error<W::Error>> {
        minicbor::Encode::encode(core::ops::Deref::deref(self), e, ctx)
    }
}

impl<C, T, const N: usize> OurCborLen<C> for heapless::Vec<T, N>
where
    T: minicbor::CborLen<C>,
{
    fn cbor_len(&self, ctx: &mut C) -> usize {
        minicbor::CborLen::cbor_len(core::ops::Deref::deref(self), ctx)
    }
}

impl<C, const N: usize> OurEncode<C> for heapless::String<N> {
    fn encode<W: minicbor::encode::Write>(
        &self,
        e: &mut minicbor::Encoder<W>,
        ctx: &mut C,
    ) -> Result<(), minicbor::encode::Error<W::Error>> {
        minicbor::Encode::encode(core::ops::Deref::deref(self), e, ctx)
    }
}

impl<C, const N: usize> OurCborLen<C> for heapless::String<N> {
    fn cbor_len(&self, ctx: &mut C) -> usize {
        minicbor::CborLen::cbor_len(core::ops::Deref::deref(self), ctx)
    }
}