minicbor_embedded_io/
writer.rs

1use embedded_io_async::Write;
2use minicbor::{
3    encode::{self, write::EndOfSlice},
4    Encode,
5};
6
7pub enum Error {
8    Io(embedded_io_async::ErrorKind),
9    Encode(encode::Error<EndOfSlice>),
10}
11
12impl core::fmt::Debug for Error {
13    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14        match self {
15            Self::Io(io) => f.debug_tuple("Io").field(io).finish(),
16            Self::Encode(enc) => f.debug_tuple("Encode").field(enc).finish(),
17        }
18    }
19}
20
21impl<T: embedded_io_async::Error> From<T> for Error {
22    fn from(value: T) -> Self {
23        Error::Io(value.kind())
24    }
25}
26
27pub trait CborArrayWriter<C> {
28    fn write_begin_array(&mut self, len: Option<u64>, ctx: &mut C);
29    async fn write_array_item<'b, R: Write>(
30        &mut self,
31        writer: &mut CborWriter<'b, R>,
32        ctx: &mut C,
33    ) -> Result<(), Error>;
34}
35
36pub trait CborMapWriter<C> {
37    fn write_begin_map(&mut self, len: Option<u64>, ctx: &mut C);
38    async fn write_map_item<'b, R: Write>(
39        &mut self,
40        writer: &mut CborWriter<'b, R>,
41        ctx: &mut C,
42    ) -> Result<(), Error>;
43}
44
45pub struct CborWriter<'b, W>
46where
47    W: Write,
48{
49    sink: W,
50    buf: &'b mut [u8],
51}
52
53impl<'b, W: Write> CborWriter<'b, W> {
54    /// Create a new writer
55    ///
56    /// The provided `buf` must be sufficiently large to contain what corresponds
57    /// to one encoded item.
58    pub fn new(sink: W, buf: &'b mut [u8]) -> Self {
59        Self { sink, buf }
60    }
61
62    /// Encode and write a CBOR value and return its size in bytes.
63    pub async fn write<T: Encode<()>>(&mut self, val: T) -> Result<usize, Error> {
64        self.write_with(val, &mut ()).await
65    }
66
67    /// Like [`AsyncWriter::write`] but accepting a user provided encoding context.
68    pub async fn write_with<C, T: Encode<C>>(
69        &mut self,
70        value: T,
71        ctx: &mut C,
72    ) -> Result<usize, Error> {
73        let mut cursor = Cursor(&mut self.buf, 0);
74        minicbor::encode_with(value, &mut cursor, ctx).map_err(Error::Encode)?;
75
76        let len = cursor.1;
77        self.sink.write_all(&self.buf[..len]).await?;
78        Ok(len)
79    }
80
81    pub async fn flush(&mut self) -> Result<(), Error> {
82        self.sink.flush().await?;
83        Ok(())
84    }
85}
86
87pub struct Cursor<'a, W>(&'a mut W, usize);
88
89impl minicbor::encode::Write for Cursor<'_, &mut [u8]> {
90    type Error = EndOfSlice;
91
92    fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
93        let slice = &mut self.0[self.1..];
94        let len = buf.len();
95        slice[..len].copy_from_slice(buf);
96        self.1 += len;
97        Ok(())
98    }
99}