Coverage Report

Created: 2025-02-25 06:39

/rust/registry/src/index.crates.io-6f17d22bba15001f/ciborium-ll-0.2.2/src/enc.rs
Line
Count
Source (jump to first uncovered line)
1
use super::*;
2
3
use ciborium_io::Write;
4
5
/// An encoder for serializing CBOR items
6
///
7
/// This structure wraps a writer and provides convenience functions for
8
/// writing `Header` objects to the wire.
9
pub struct Encoder<W: Write>(W);
10
11
impl<W: Write> From<W> for Encoder<W> {
12
    #[inline]
13
0
    fn from(value: W) -> Self {
14
0
        Self(value)
15
0
    }
Unexecuted instantiation: <ciborium_ll::enc::Encoder<&mut alloc::vec::Vec<u8>> as core::convert::From<&mut alloc::vec::Vec<u8>>>::from
Unexecuted instantiation: <ciborium_ll::enc::Encoder<_> as core::convert::From<_>>::from
16
}
17
18
impl<W: Write> Write for Encoder<W> {
19
    type Error = W::Error;
20
21
0
    fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
22
0
        self.0.write_all(data)
23
0
    }
Unexecuted instantiation: <ciborium_ll::enc::Encoder<&mut alloc::vec::Vec<u8>> as ciborium_io::Write>::write_all
Unexecuted instantiation: <ciborium_ll::enc::Encoder<_> as ciborium_io::Write>::write_all
24
25
0
    fn flush(&mut self) -> Result<(), Self::Error> {
26
0
        self.0.flush()
27
0
    }
28
}
29
30
impl<W: Write> Encoder<W> {
31
    /// Push a `Header` to the wire
32
    #[inline]
33
0
    pub fn push(&mut self, header: Header) -> Result<(), W::Error> {
34
0
        let title = Title::from(header);
35
36
0
        let major = match title.0 {
37
0
            Major::Positive => 0,
38
0
            Major::Negative => 1,
39
0
            Major::Bytes => 2,
40
0
            Major::Text => 3,
41
0
            Major::Array => 4,
42
0
            Major::Map => 5,
43
0
            Major::Tag => 6,
44
0
            Major::Other => 7,
45
        };
46
47
0
        let minor = match title.1 {
48
0
            Minor::This(x) => x,
49
0
            Minor::Next1(..) => 24,
50
0
            Minor::Next2(..) => 25,
51
0
            Minor::Next4(..) => 26,
52
0
            Minor::Next8(..) => 27,
53
0
            Minor::More => 31,
54
        };
55
56
0
        self.0.write_all(&[major << 5 | minor])?;
57
0
        self.0.write_all(title.1.as_ref())
58
0
    }
Unexecuted instantiation: <ciborium_ll::enc::Encoder<&mut alloc::vec::Vec<u8>>>::push
Unexecuted instantiation: <ciborium_ll::enc::Encoder<_>>::push
59
60
    /// Serialize a byte slice as CBOR
61
    ///
62
    /// Optionally, segment the output into `segment` size segments. Note that
63
    /// if `segment == Some(0)` it will be silently upgraded to `Some(1)`. This
64
    /// minimum value is highly inefficient and should not be relied upon.
65
    #[inline]
66
0
    pub fn bytes(
67
0
        &mut self,
68
0
        value: &[u8],
69
0
        segment: impl Into<Option<usize>>,
70
0
    ) -> Result<(), W::Error> {
71
0
        let max = segment.into().unwrap_or(value.len());
72
0
        let max = core::cmp::max(max, 1);
73
0
74
0
        if max >= value.len() {
75
0
            self.push(Header::Bytes(Some(value.len())))?;
76
0
            self.write_all(value)?;
77
        } else {
78
0
            self.push(Header::Bytes(None))?;
79
80
0
            for chunk in value.chunks(max) {
81
0
                self.push(Header::Bytes(Some(chunk.len())))?;
82
0
                self.write_all(chunk)?;
83
            }
84
85
0
            self.push(Header::Break)?;
86
        }
87
88
0
        Ok(())
89
0
    }
90
91
    /// Serialize a string slice as CBOR
92
    ///
93
    /// Optionally, segment the output into `segment` size segments. Note that
94
    /// since care is taken to ensure that each segment is itself a valid UTF-8
95
    /// string, if `segment` contains a value of less than 4, it will be
96
    /// silently upgraded to 4. This minimum value is highly inefficient and
97
    /// should not be relied upon.
98
    #[inline]
99
0
    pub fn text(&mut self, value: &str, segment: impl Into<Option<usize>>) -> Result<(), W::Error> {
100
0
        let max = segment.into().unwrap_or(value.len());
101
0
        let max = core::cmp::max(max, 4);
102
0
103
0
        if max >= value.len() {
104
0
            self.push(Header::Text(Some(value.len())))?;
105
0
            self.write_all(value.as_bytes())?;
106
        } else {
107
0
            self.push(Header::Text(None))?;
108
109
0
            let mut bytes = value.as_bytes();
110
0
            while !bytes.is_empty() {
111
0
                let mut len = core::cmp::min(bytes.len(), max);
112
0
                while len > 0 && core::str::from_utf8(&bytes[..len]).is_err() {
113
0
                    len -= 1
114
                }
115
116
0
                let (prefix, suffix) = bytes.split_at(len);
117
0
                self.push(Header::Text(Some(prefix.len())))?;
118
0
                self.write_all(prefix)?;
119
0
                bytes = suffix;
120
            }
121
122
0
            self.push(Header::Break)?;
123
        }
124
125
0
        Ok(())
126
0
    }
127
}