1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// Copyright 2021-2022 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

//! A module to unpack any value that implements [`Packable`](crate::Packable).
//!
//! The [`Unpacker`] trait represents types that can be used to read bytes from it. It can be thought as a `no_std`
//! friendly alternative to the [`Read`](std::io::Read) trait.

mod counter;
#[cfg(feature = "io")]
mod io;
mod slice;

pub use counter::CounterUnpacker;
#[cfg(feature = "io")]
pub use io::IoUnpacker;
pub use slice::SliceUnpacker;

/// A type that can unpack any value that implements [`Packable`](crate::Packable).
pub trait Unpacker: Sized {
    /// An error type representing any error related to reading bytes.
    type Error;

    /// Reads a sequence of bytes from the [`Unpacker`]. This sequence must be long enough to fill `bytes` completely.
    /// This method **must** fail if the unpacker does not have enough bytes to fulfill the request.
    fn unpack_bytes<B: AsMut<[u8]>>(&mut self, bytes: B) -> Result<(), Self::Error>;

    /// Tries to guarantee that the [`Unpacker`] has at least `len` bytes.
    ///
    /// This method **must** fail if and only if it is certain that there are not enough bytes and
    /// it is allowed to return `Ok(())` in any other case.
    #[inline]
    fn ensure_bytes(&self, _len: usize) -> Result<(), Self::Error> {
        Ok(())
    }

    /// Returns the exact number of read bytes if possible.
    #[inline]
    fn read_bytes(&self) -> Option<usize> {
        None
    }
}

impl<U: Unpacker + ?Sized> Unpacker for &mut U {
    type Error = U::Error;

    #[inline]
    fn unpack_bytes<B: AsMut<[u8]>>(&mut self, bytes: B) -> Result<(), Self::Error> {
        U::unpack_bytes(*self, bytes)
    }

    #[inline]
    fn ensure_bytes(&self, len: usize) -> Result<(), Self::Error> {
        U::ensure_bytes(*self, len)
    }

    #[inline]
    fn read_bytes(&self) -> Option<usize> {
        U::read_bytes(*self)
    }
}