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
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
use super::CborIter;
use crate::Cbor;
use std::{
    borrow::Cow,
    fmt::{Debug, Display, Formatter, Write},
    io::Read,
};

/// Iterator yielding the fragments of a text string item
///
/// Parsing an item can in general not return a contiguous string due to
/// [indefinite-length encoding](https://www.rfc-editor.org/rfc/rfc8949.html#section-3.2.3).
/// This Iterator gives you the choice whether you want to inspect the fragments or build
/// a contiguous string by allocating the necessary memory.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct StringIter<'a>(CborIter<'a>);

impl<'a> StringIter<'a> {
    pub(crate) fn new(bytes: &'a [u8], len: Option<u64>) -> Self {
        Self(CborIter::new(bytes, len))
    }

    /// Indicates whether the underlying encoding was definite or indefinite
    ///
    /// If you want to check whether the string is available as contiguous slice, see
    /// [`as_str`](#method.as_str), which will also work for 0- and 1-fragment strings
    /// using indefinite-length encoding.
    pub fn is_indefinite(&self) -> bool {
        self.0.size().is_none()
    }

    /// Returns true if the string consists of zero fragments
    ///
    /// **A return value of `false` does not indicate that the string contains characters!**
    pub fn is_empty(&self) -> bool {
        let mut this = *self;
        this.next().is_none()
    }

    /// Try to borrow the string as a single slice
    ///
    /// This will only succeed for definite length encoding or strings with 0 or 1 fragments.
    pub fn as_str(&self) -> Option<&'a str> {
        let mut this = *self;
        if let Some(first) = this.next() {
            if this.next().is_none() {
                Some(first)
            } else {
                None
            }
        } else {
            Some("")
        }
    }

    /// Extract the full string, borrowing if possible and allocating if necessary
    pub fn as_cow(&self) -> Cow<'a, str> {
        if let Some(s) = self.as_str() {
            Cow::Borrowed(s)
        } else {
            Cow::Owned(self.collect())
        }
    }
}

impl<'a> Debug for StringIter<'a> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.write_str("StringIter")
    }
}

impl<'a> Display for StringIter<'a> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        for s in *self {
            f.write_str(s)?;
        }
        Ok(())
    }
}

impl<'a> Iterator for StringIter<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<Self::Item> {
        let v = self
            .0
            .next()?
            .0
            .expect("string fragments must be in definite size encoding");
        Some(unsafe { std::str::from_utf8_unchecked(v) })
    }
}

impl<'a, S: AsRef<str>> PartialEq<S> for StringIter<'a> {
    fn eq(&self, other: &S) -> bool {
        let this = *self;
        let mut other = other.as_ref();
        for prefix in this {
            if other.starts_with(prefix) {
                other = &other[prefix.len()..];
            } else {
                return false;
            }
        }
        other.is_empty()
    }
}

/// Iterator yielding the fragments of a byte string item
///
/// Parsing an item can in general not return a contiguous string due to
/// [indefinite-length encoding](https://www.rfc-editor.org/rfc/rfc8949.html#section-3.2.3).
/// This Iterator gives you the choice whether you want to inspect the fragments or build
/// a contiguous string by allocating the necessary memory.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct BytesIter<'a>(CborIter<'a>, &'a [u8]);

impl<'a> BytesIter<'a> {
    pub(crate) fn new(bytes: &'a [u8], len: Option<u64>) -> Self {
        Self(CborIter::new(bytes, len), b"")
    }

    /// Indicates whether the underlying encoding was definite or indefinite
    ///
    /// If you want to check whether the string is available as contiguous slice, see
    /// [`as_slice`](#method.as_slice), which will also work for 0- and 1-fragment strings
    /// using indefinite-length encoding.
    pub fn is_indefinite(&self) -> bool {
        self.0.size().is_none()
    }

    /// Returns true if the string consists of zero fragments
    ///
    /// **A return value of `false` does not indicate that the string contains bytes!**
    pub fn is_empty(&self) -> bool {
        let mut this = *self;
        this.next().is_none()
    }

    /// Try to borrow the string as a single slice
    ///
    /// This will only succeed for definite length encoding or strings with 0 or 1 fragments.
    pub fn as_slice(&self) -> Option<&'a [u8]> {
        let mut this = *self;
        if let Some(first) = this.next() {
            if this.next().is_none() {
                Some(first)
            } else {
                None
            }
        } else {
            Some(b"")
        }
    }

    /// Extract the full string, borrowing if possible and allocating if necessary
    pub fn as_cow(&self) -> Cow<'a, [u8]> {
        if let Some(s) = self.as_slice() {
            Cow::Borrowed(s)
        } else {
            let mut v = Vec::new();
            for b in *self {
                v.extend_from_slice(b);
            }
            Cow::Owned(v)
        }
    }

    /// Extract the full string by allocating a fresh Vec
    pub fn to_vec(self) -> Vec<u8> {
        let mut ret = Vec::new();
        for v in self {
            ret.extend_from_slice(v);
        }
        ret
    }
}

impl<'a> Debug for BytesIter<'a> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.write_str("BytesIter")
    }
}

impl<'a> Display for BytesIter<'a> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let mut first = true;
        for b in *self {
            if first {
                first = false;
            } else {
                f.write_char(' ')?;
            }
            for byte in b {
                write!(f, "{:02x}", byte)?;
            }
        }
        Ok(())
    }
}

impl<'a> Iterator for BytesIter<'a> {
    type Item = &'a [u8];

    fn next(&mut self) -> Option<Self::Item> {
        Some(
            self.0
                .next()?
                .0
                .expect("byte string fragments must be in definite size encoding"),
        )
    }
}

impl<'a> Read for BytesIter<'a> {
    fn read(&mut self, mut buf: &mut [u8]) -> std::io::Result<usize> {
        let mut in_hand = self.1;
        let mut read = 0;
        loop {
            let transfer = in_hand.len().min(buf.len());
            let (left, right) = buf.split_at_mut(transfer);
            left.copy_from_slice(&in_hand[..transfer]);
            in_hand = &in_hand[transfer..];
            buf = right;
            read += transfer;
            if buf.is_empty() {
                break;
            }
            // in_hand must be empty
            if let Some(bytes) = self.next() {
                in_hand = bytes;
            } else {
                break;
            }
        }
        self.1 = in_hand;
        Ok(read)
    }
}

impl<'a, S: AsRef<[u8]>> PartialEq<S> for BytesIter<'a> {
    fn eq(&self, other: &S) -> bool {
        let this = *self;
        let mut other = other.as_ref();
        for prefix in this {
            if other.starts_with(prefix) {
                other = &other[prefix.len()..];
            } else {
                return false;
            }
        }
        other.is_empty()
    }
}

/// Iterator over the CBOR items within an array
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct ArrayIter<'a>(CborIter<'a>);

impl<'a> ArrayIter<'a> {
    pub(crate) fn new(bytes: &'a [u8], len: Option<u64>) -> Self {
        Self(CborIter::new(bytes, len))
    }

    /// Number of items still remaining, or `None` in case of
    /// [indefinite-length encoding](https://www.rfc-editor.org/rfc/rfc8949.html#section-3.2.2)
    pub fn size(&self) -> Option<u64> {
        self.0.size()
    }
}

impl<'a> Debug for ArrayIter<'a> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.write_str("ArrayIter")
    }
}
impl<'a> Iterator for ArrayIter<'a> {
    type Item = &'a Cbor;

    fn next(&mut self) -> Option<Self::Item> {
        Some(self.0.next()?.1)
    }
}

/// Iterator over the key–value mappings within a dictionary
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct DictIter<'a>(CborIter<'a>);

impl<'a> DictIter<'a> {
    pub(crate) fn new(bytes: &'a [u8], len: Option<u64>) -> Self {
        Self(CborIter::new(bytes, len.map(|x| x * 2)))
    }

    /// Number of items still remaining, or `None` in case of
    /// [indefinite-length encoding](https://www.rfc-editor.org/rfc/rfc8949.html#section-3.2.2)
    pub fn size(&self) -> Option<u64> {
        self.0.size().map(|x| x / 2)
    }
}

impl<'a> Debug for DictIter<'a> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.write_str("DictIter")
    }
}
impl<'a> Iterator for DictIter<'a> {
    type Item = (&'a Cbor, &'a Cbor);

    fn next(&mut self) -> Option<Self::Item> {
        Some((self.0.next()?.1, self.0.next()?.1))
    }
}