Coverage Report

Created: 2026-04-14 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ciborium-ll-0.2.2/src/dec.rs
Line
Count
Source
1
use super::*;
2
3
use ciborium_io::Read;
4
5
/// An error that occurred while decoding
6
#[derive(Debug)]
7
pub enum Error<T> {
8
    /// An error occurred while reading bytes
9
    ///
10
    /// Contains the underlying error returned while reading.
11
    Io(T),
12
13
    /// An error occurred while parsing bytes
14
    ///
15
    /// Contains the offset into the stream where the syntax error occurred.
16
    Syntax(usize),
17
}
18
19
impl<T> From<T> for Error<T> {
20
    #[inline]
21
0
    fn from(value: T) -> Self {
22
0
        Self::Io(value)
23
0
    }
Unexecuted instantiation: <ciborium_ll::dec::Error<std::io::error::Error> as core::convert::From<std::io::error::Error>>::from
Unexecuted instantiation: <ciborium_ll::dec::Error<_> as core::convert::From<_>>::from
24
}
25
26
/// A decoder for deserializing CBOR items
27
///
28
/// This decoder manages the low-level decoding of CBOR items into `Header`
29
/// objects. It also contains utility functions for parsing segmented bytes
30
/// and text inputs.
31
pub struct Decoder<R: Read> {
32
    reader: R,
33
    offset: usize,
34
    buffer: Option<Title>,
35
}
36
37
impl<R: Read> From<R> for Decoder<R> {
38
    #[inline]
39
0
    fn from(value: R) -> Self {
40
0
        Self {
41
0
            reader: value,
42
0
            offset: 0,
43
0
            buffer: None,
44
0
        }
45
0
    }
Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]> as core::convert::From<&[u8]>>::from
Unexecuted instantiation: <ciborium_ll::dec::Decoder<_> as core::convert::From<_>>::from
46
}
47
48
impl<R: Read> Read for Decoder<R> {
49
    type Error = R::Error;
50
51
    #[inline]
52
0
    fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
53
0
        assert!(self.buffer.is_none());
54
0
        self.reader.read_exact(data)?;
55
0
        self.offset += data.len();
56
0
        Ok(())
57
0
    }
Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]> as ciborium_io::Read>::read_exact
Unexecuted instantiation: <ciborium_ll::dec::Decoder<_> as ciborium_io::Read>::read_exact
58
}
59
60
impl<R: Read> Decoder<R> {
61
    #[inline]
62
0
    fn pull_title(&mut self) -> Result<Title, Error<R::Error>> {
63
0
        if let Some(title) = self.buffer.take() {
64
0
            self.offset += title.1.as_ref().len() + 1;
65
0
            return Ok(title);
66
0
        }
67
68
0
        let mut prefix = [0u8; 1];
69
0
        self.read_exact(&mut prefix[..])?;
70
71
0
        let major = match prefix[0] >> 5 {
72
0
            0 => Major::Positive,
73
0
            1 => Major::Negative,
74
0
            2 => Major::Bytes,
75
0
            3 => Major::Text,
76
0
            4 => Major::Array,
77
0
            5 => Major::Map,
78
0
            6 => Major::Tag,
79
0
            7 => Major::Other,
80
0
            _ => unreachable!(),
81
        };
82
83
0
        let mut minor = match prefix[0] & 0b00011111 {
84
0
            x if x < 24 => Minor::This(x),
85
0
            24 => Minor::Next1([0; 1]),
86
0
            25 => Minor::Next2([0; 2]),
87
0
            26 => Minor::Next4([0; 4]),
88
0
            27 => Minor::Next8([0; 8]),
89
0
            31 => Minor::More,
90
0
            _ => return Err(Error::Syntax(self.offset - 1)),
91
        };
92
93
0
        self.read_exact(minor.as_mut())?;
94
0
        Ok(Title(major, minor))
95
0
    }
Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::pull_title
Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::pull_title
96
97
    #[inline]
98
0
    fn push_title(&mut self, item: Title) {
99
0
        assert!(self.buffer.is_none());
100
0
        self.buffer = Some(item);
101
0
        self.offset -= item.1.as_ref().len() + 1;
102
0
    }
Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::push_title
Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::push_title
103
104
    /// Pulls the next header from the input
105
    #[inline]
106
0
    pub fn pull(&mut self) -> Result<Header, Error<R::Error>> {
107
0
        let offset = self.offset;
108
0
        self.pull_title()?
109
0
            .try_into()
110
0
            .map_err(|_| Error::Syntax(offset))
Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::pull::{closure#0}
Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::pull::{closure#0}
111
0
    }
Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::pull
Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::pull
112
113
    /// Push a single header into the input buffer
114
    ///
115
    /// # Panics
116
    ///
117
    /// This function panics if called while there is already a header in the
118
    /// input buffer. You should take care to call this function only after
119
    /// pulling a header to ensure there is nothing in the input buffer.
120
    #[inline]
121
0
    pub fn push(&mut self, item: Header) {
122
0
        self.push_title(Title::from(item))
123
0
    }
Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::push
Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::push
124
125
    /// Gets the current byte offset into the stream
126
    ///
127
    /// The offset starts at zero when the decoder is created. Therefore, if
128
    /// bytes were already read from the reader before the decoder was created,
129
    /// you must account for this.
130
    #[inline]
131
0
    pub fn offset(&mut self) -> usize {
132
0
        self.offset
133
0
    }
Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::offset
Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::offset
134
135
    /// Process an incoming bytes item
136
    ///
137
    /// In CBOR, bytes can be segmented. The logic for this can be a bit tricky,
138
    /// so we encapsulate that logic using this function. This function **MUST**
139
    /// be called immediately after first pulling a `Header::Bytes(len)` from
140
    /// the wire and `len` must be provided to this function from that value.
141
    ///
142
    /// The `buf` parameter provides a buffer used when reading in the segmented
143
    /// bytes. A large buffer will result in fewer calls to read incoming bytes
144
    /// at the cost of memory usage. You should consider this trade off when
145
    /// deciding the size of your buffer.
146
    #[inline]
147
0
    pub fn bytes(&mut self, len: Option<usize>) -> Segments<R, crate::seg::Bytes> {
148
0
        self.push(Header::Bytes(len));
149
0
        Segments::new(self, |header| match header {
150
0
            Header::Bytes(len) => Ok(len),
151
0
            _ => Err(()),
152
0
        })
Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::bytes::{closure#0}
Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::bytes::{closure#0}
153
0
    }
Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::bytes
Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::bytes
154
155
    /// Process an incoming text item
156
    ///
157
    /// In CBOR, text can be segmented. The logic for this can be a bit tricky,
158
    /// so we encapsulate that logic using this function. This function **MUST**
159
    /// be called immediately after first pulling a `Header::Text(len)` from
160
    /// the wire and `len` must be provided to this function from that value.
161
    ///
162
    /// The `buf` parameter provides a buffer used when reading in the segmented
163
    /// text. A large buffer will result in fewer calls to read incoming bytes
164
    /// at the cost of memory usage. You should consider this trade off when
165
    /// deciding the size of your buffer.
166
    #[inline]
167
0
    pub fn text(&mut self, len: Option<usize>) -> Segments<R, crate::seg::Text> {
168
0
        self.push(Header::Text(len));
169
0
        Segments::new(self, |header| match header {
170
0
            Header::Text(len) => Ok(len),
171
0
            _ => Err(()),
172
0
        })
Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::text::{closure#0}
Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::text::{closure#0}
173
0
    }
Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::text
Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::text
174
}