bitcoin_consensus_encoding/encode/
encoders.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Collection of "standard encoders".
4//!
5//! These encoders should not be used directly. Instead, when implementing the
6//! [`super::Encodable`] trait on a type, you should define a newtype around one
7//! or more of these encoders, and pass through the [`Encoder`] implementation
8//! to your newtype. This avoids leaking encoding implementation details to the
9//! users of your type.
10//!
11//! For implementing these newtypes, we provide the [`encoder_newtype`] macro.
12//!
13
14use internals::array_vec::ArrayVec;
15use internals::compact_size;
16
17use super::{Encodable, Encoder};
18
19/// The maximum length of a compact size encoding.
20const SIZE: usize = 9;
21
22/// An encoder for a single byte slice.
23pub struct BytesEncoder<'sl> {
24    sl: Option<&'sl [u8]>,
25}
26
27impl<'sl> BytesEncoder<'sl> {
28    /// Constructs a byte encoder which encodes the given byte slice, with no length prefix.
29    pub const fn without_length_prefix(sl: &'sl [u8]) -> Self { Self { sl: Some(sl) } }
30}
31
32impl Encoder for BytesEncoder<'_> {
33    fn current_chunk(&self) -> &[u8] { self.sl.unwrap_or_default() }
34
35    fn advance(&mut self) -> bool {
36        self.sl = None;
37        false
38    }
39}
40
41/// An encoder for a single array.
42pub struct ArrayEncoder<const N: usize> {
43    arr: Option<[u8; N]>,
44}
45
46impl<const N: usize> ArrayEncoder<N> {
47    /// Constructs an encoder which encodes the array with no length prefix.
48    pub const fn without_length_prefix(arr: [u8; N]) -> Self { Self { arr: Some(arr) } }
49}
50
51impl<const N: usize> Encoder for ArrayEncoder<N> {
52    #[inline]
53    fn current_chunk(&self) -> &[u8] { self.arr.as_ref().map(|x| &x[..]).unwrap_or_default() }
54
55    #[inline]
56    fn advance(&mut self) -> bool {
57        self.arr = None;
58        false
59    }
60}
61
62/// An encoder for a list of encodable types.
63pub struct SliceEncoder<'e, T: Encodable> {
64    /// The list of references to the objects we are encoding.
65    sl: &'e [T],
66    /// Encoder for the current object being encoded.
67    cur_enc: Option<T::Encoder<'e>>,
68}
69
70impl<'e, T: Encodable> SliceEncoder<'e, T> {
71    /// Constructs an encoder which encodes the slice _without_ adding the length prefix.
72    ///
73    /// To encode with a length prefix consider using the `Encoder2`.
74    ///
75    /// E.g, `Encoder2<CompactSizeEncoder, SliceEncoder<'e, Foo>>`.
76    pub fn without_length_prefix(sl: &'e [T]) -> Self {
77        // In this `map` call we cannot remove the closure. Seems to be a bug in the compiler.
78        // Perhaps https://github.com/rust-lang/rust/issues/102540 which is 3 years old with
79        // no replies or even an acknowledgement. We will not bother filing our own issue.
80        Self { sl, cur_enc: sl.first().map(|x| T::encoder(x)) }
81    }
82}
83
84impl<T: Encodable> Encoder for SliceEncoder<'_, T> {
85    fn current_chunk(&self) -> &[u8] {
86        // `advance` sets `cur_enc` to `None` once the slice encoder is completely exhausted.
87        self.cur_enc.as_ref().map(T::Encoder::current_chunk).unwrap_or_default()
88    }
89
90    fn advance(&mut self) -> bool {
91        let Some(cur) = self.cur_enc.as_mut() else {
92            return false;
93        };
94
95        loop {
96            // On subsequent calls, attempt to advance the current encoder and return
97            // success if this succeeds.
98            if cur.advance() {
99                return true;
100            }
101            // self.sl guaranteed to be non-empty if cur is non-None.
102            self.sl = &self.sl[1..];
103
104            // If advancing the current encoder failed, attempt to move to the next encoder.
105            if let Some(x) = self.sl.first() {
106                *cur = x.encoder();
107                if !cur.current_chunk().is_empty() {
108                    return true;
109                }
110            } else {
111                self.cur_enc = None; // shortcut the next call to advance()
112                return false;
113            }
114        }
115    }
116}
117
118/// An encoder which encodes two objects, one after the other.
119pub struct Encoder2<A, B> {
120    enc_idx: usize,
121    enc_1: A,
122    enc_2: B,
123}
124
125impl<A, B> Encoder2<A, B> {
126    /// Constructs a new composite encoder.
127    pub const fn new(enc_1: A, enc_2: B) -> Self { Self { enc_idx: 0, enc_1, enc_2 } }
128}
129
130impl<A: Encoder, B: Encoder> Encoder for Encoder2<A, B> {
131    #[inline]
132    fn current_chunk(&self) -> &[u8] {
133        if self.enc_idx == 0 {
134            self.enc_1.current_chunk()
135        } else {
136            self.enc_2.current_chunk()
137        }
138    }
139
140    #[inline]
141    fn advance(&mut self) -> bool {
142        if self.enc_idx == 0 {
143            if !self.enc_1.advance() {
144                self.enc_idx += 1;
145            }
146            true
147        } else {
148            self.enc_2.advance()
149        }
150    }
151}
152
153// For now we implement every higher encoder by composing Encoder2s, because
154// I'm lazy and this is trivial both to write and to review. For efficiency, we
155// should eventually unroll all of these. There are only a couple of them. The
156// unrolled versions should be macro-izable, if we want to do that.
157
158/// An encoder which encodes three objects, one after the other.
159pub struct Encoder3<A, B, C> {
160    inner: Encoder2<Encoder2<A, B>, C>,
161}
162
163impl<A, B, C> Encoder3<A, B, C> {
164    /// Constructs a new composite encoder.
165    pub const fn new(enc_1: A, enc_2: B, enc_3: C) -> Self {
166        Self { inner: Encoder2::new(Encoder2::new(enc_1, enc_2), enc_3) }
167    }
168}
169
170impl<A: Encoder, B: Encoder, C: Encoder> Encoder for Encoder3<A, B, C> {
171    #[inline]
172    fn current_chunk(&self) -> &[u8] { self.inner.current_chunk() }
173    #[inline]
174    fn advance(&mut self) -> bool { self.inner.advance() }
175}
176
177/// An encoder which encodes four objects, one after the other.
178pub struct Encoder4<A, B, C, D> {
179    inner: Encoder2<Encoder2<A, B>, Encoder2<C, D>>,
180}
181
182impl<A, B, C, D> Encoder4<A, B, C, D> {
183    /// Constructs a new composite encoder.
184    pub const fn new(enc_1: A, enc_2: B, enc_3: C, enc_4: D) -> Self {
185        Self { inner: Encoder2::new(Encoder2::new(enc_1, enc_2), Encoder2::new(enc_3, enc_4)) }
186    }
187}
188
189impl<A: Encoder, B: Encoder, C: Encoder, D: Encoder> Encoder for Encoder4<A, B, C, D> {
190    #[inline]
191    fn current_chunk(&self) -> &[u8] { self.inner.current_chunk() }
192    #[inline]
193    fn advance(&mut self) -> bool { self.inner.advance() }
194}
195
196/// An encoder which encodes six objects, one after the other.
197pub struct Encoder6<A, B, C, D, E, F> {
198    inner: Encoder2<Encoder3<A, B, C>, Encoder3<D, E, F>>,
199}
200
201impl<A, B, C, D, E, F> Encoder6<A, B, C, D, E, F> {
202    /// Constructs a new composite encoder.
203    pub const fn new(enc_1: A, enc_2: B, enc_3: C, enc_4: D, enc_5: E, enc_6: F) -> Self {
204        Self {
205            inner: Encoder2::new(
206                Encoder3::new(enc_1, enc_2, enc_3),
207                Encoder3::new(enc_4, enc_5, enc_6),
208            ),
209        }
210    }
211}
212
213impl<A: Encoder, B: Encoder, C: Encoder, D: Encoder, E: Encoder, F: Encoder> Encoder
214    for Encoder6<A, B, C, D, E, F>
215{
216    #[inline]
217    fn current_chunk(&self) -> &[u8] { self.inner.current_chunk() }
218    #[inline]
219    fn advance(&mut self) -> bool { self.inner.advance() }
220}
221
222/// Encoder for a compact size encoded integer.
223pub struct CompactSizeEncoder {
224    buf: Option<ArrayVec<u8, SIZE>>,
225}
226
227impl CompactSizeEncoder {
228    /// Constructs a new `CompactSizeEncoder`.
229    ///
230    /// Encodings are defined only for the range of u64. On systems where usize is
231    /// larger than u64, it will be possible to call this method with out-of-range
232    /// values. In such cases we will ignore the passed value and encode [`u64::MAX`].
233    /// But even on such exotic systems, we expect users to pass the length of an
234    /// in-memory object, meaning that such large values are impossible to obtain.
235    pub fn new(value: usize) -> Self {
236        let enc_value = value.try_into().unwrap_or(u64::MAX);
237        Self { buf: Some(compact_size::encode(enc_value)) }
238    }
239}
240
241impl Encoder for CompactSizeEncoder {
242    #[inline]
243    fn current_chunk(&self) -> &[u8] { self.buf.as_ref().map(|b| &b[..]).unwrap_or_default() }
244
245    #[inline]
246    fn advance(&mut self) -> bool {
247        self.buf = None;
248        false
249    }
250}
251
252#[cfg(test)]
253mod tests {
254    use super::*;
255
256    struct TestBytes<'a>(&'a [u8]);
257
258    impl Encodable for TestBytes<'_> {
259        type Encoder<'s>
260            = BytesEncoder<'s>
261        where
262            Self: 's;
263
264        fn encoder(&self) -> Self::Encoder<'_> { BytesEncoder::without_length_prefix(self.0) }
265    }
266
267    struct TestArray<const N: usize>([u8; N]);
268
269    impl<const N: usize> Encodable for TestArray<N> {
270        type Encoder<'s>
271            = ArrayEncoder<N>
272        where
273            Self: 's;
274
275        fn encoder(&self) -> Self::Encoder<'_> { ArrayEncoder::without_length_prefix(self.0) }
276    }
277
278    #[test]
279    fn encode_array_with_data() {
280        // Should have one chunk with the array data, then exhausted.
281        let test_array = TestArray([1u8, 2, 3, 4]);
282        let mut encoder = test_array.encoder();
283        assert_eq!(encoder.current_chunk(), &[1u8, 2, 3, 4][..]);
284        assert!(!encoder.advance());
285        assert!(encoder.current_chunk().is_empty());
286    }
287
288    #[test]
289    fn encode_empty_array() {
290        // Empty array should have one empty chunk, then exhausted.
291        let test_array = TestArray([]);
292        let mut encoder = test_array.encoder();
293        assert!(encoder.current_chunk().is_empty());
294        assert!(!encoder.advance());
295        assert!(encoder.current_chunk().is_empty());
296    }
297
298    #[test]
299    fn encode_byte_slice_without_prefix() {
300        // Should have one chunk with the byte data, then exhausted.
301        let obj = [1u8, 2, 3];
302        let test_bytes = TestBytes(&obj);
303        let mut encoder = test_bytes.encoder();
304
305        assert_eq!(encoder.current_chunk(), &[1u8, 2, 3][..]);
306        assert!(!encoder.advance());
307        assert!(encoder.current_chunk().is_empty());
308    }
309
310    #[test]
311    fn encode_empty_byte_slice_without_prefix() {
312        // Should have one empty chunk, then exhausted.
313        let obj = [];
314        let test_bytes = TestBytes(&obj);
315        let mut encoder = test_bytes.encoder();
316
317        assert!(encoder.current_chunk().is_empty());
318        assert!(!encoder.advance());
319        assert!(encoder.current_chunk().is_empty());
320    }
321
322    #[test]
323    fn encode_slice_with_elements() {
324        // Should have the element chunks, then exhausted.
325        let slice = &[TestArray([0x34, 0x12, 0x00, 0x00]), TestArray([0x78, 0x56, 0x00, 0x00])];
326        let mut encoder = SliceEncoder::without_length_prefix(slice);
327
328        assert_eq!(encoder.current_chunk(), &[0x34, 0x12, 0x00, 0x00][..]);
329        assert!(encoder.advance());
330        assert_eq!(encoder.current_chunk(), &[0x78, 0x56, 0x00, 0x00][..]);
331        assert!(!encoder.advance());
332        assert!(encoder.current_chunk().is_empty());
333    }
334
335    #[test]
336    fn encode_empty_slice() {
337        // Should immediately be exhausted.
338        let slice: &[TestArray<4>] = &[];
339        let mut encoder = SliceEncoder::without_length_prefix(slice);
340
341        assert!(!encoder.advance());
342        assert!(encoder.current_chunk().is_empty());
343    }
344
345    #[test]
346    fn encode_slice_with_zero_sized_arrays() {
347        // Should have empty array chunks, then exhausted.
348        let slice = &[TestArray([]), TestArray([])];
349        let mut encoder = SliceEncoder::without_length_prefix(slice);
350
351        assert!(encoder.current_chunk().is_empty());
352        // The slice advanced is optimized to skip over empty chunks.
353        assert!(!encoder.advance());
354        assert!(encoder.current_chunk().is_empty());
355    }
356
357    #[test]
358    fn encode_two_arrays() {
359        // Should encode first array, then second array, then exhausted.
360        let enc1 = TestArray([1u8, 2]).encoder();
361        let enc2 = TestArray([3u8, 4]).encoder();
362        let mut encoder = Encoder2::new(enc1, enc2);
363
364        assert_eq!(encoder.current_chunk(), &[1u8, 2][..]);
365        assert!(encoder.advance());
366        assert_eq!(encoder.current_chunk(), &[3u8, 4][..]);
367        assert!(!encoder.advance());
368        assert!(encoder.current_chunk().is_empty());
369    }
370
371    #[test]
372    fn encode_two_empty_arrays() {
373        // Should encode first empty array, then second empty array, then exhausted.
374        let enc1 = TestArray([]).encoder();
375        let enc2 = TestArray([]).encoder();
376        let mut encoder = Encoder2::new(enc1, enc2);
377
378        assert!(encoder.current_chunk().is_empty());
379        assert!(encoder.advance());
380        assert!(encoder.current_chunk().is_empty());
381        assert!(!encoder.advance());
382        assert!(encoder.current_chunk().is_empty());
383    }
384
385    #[test]
386    fn encode_three_arrays() {
387        // Should encode three arrays in sequence, then exhausted.
388        let enc1 = TestArray([1u8]).encoder();
389        let enc2 = TestArray([2u8, 3u8]).encoder();
390        let enc3 = TestArray([4u8, 5u8, 6u8]).encoder();
391        let mut encoder = Encoder3::new(enc1, enc2, enc3);
392
393        assert_eq!(encoder.current_chunk(), &[1u8][..]);
394        assert!(encoder.advance());
395        assert_eq!(encoder.current_chunk(), &[2u8, 3u8][..]);
396        assert!(encoder.advance());
397        assert_eq!(encoder.current_chunk(), &[4u8, 5u8, 6u8][..]);
398        assert!(!encoder.advance());
399        assert!(encoder.current_chunk().is_empty());
400    }
401
402    #[test]
403    fn encode_four_arrays() {
404        // Should encode four arrays in sequence, then exhausted.
405        let enc1 = TestArray([0x10]).encoder();
406        let enc2 = TestArray([0x20]).encoder();
407        let enc3 = TestArray([0x30]).encoder();
408        let enc4 = TestArray([0x40]).encoder();
409        let mut encoder = Encoder4::new(enc1, enc2, enc3, enc4);
410
411        assert_eq!(encoder.current_chunk(), &[0x10][..]);
412        assert!(encoder.advance());
413        assert_eq!(encoder.current_chunk(), &[0x20][..]);
414        assert!(encoder.advance());
415        assert_eq!(encoder.current_chunk(), &[0x30][..]);
416        assert!(encoder.advance());
417        assert_eq!(encoder.current_chunk(), &[0x40][..]);
418        assert!(!encoder.advance());
419        assert!(encoder.current_chunk().is_empty());
420    }
421
422    #[test]
423    fn encode_six_arrays() {
424        // Should encode six arrays in sequence, then exhausted.
425        let enc1 = TestArray([0x01]).encoder();
426        let enc2 = TestArray([0x02]).encoder();
427        let enc3 = TestArray([0x03]).encoder();
428        let enc4 = TestArray([0x04]).encoder();
429        let enc5 = TestArray([0x05]).encoder();
430        let enc6 = TestArray([0x06]).encoder();
431        let mut encoder = Encoder6::new(enc1, enc2, enc3, enc4, enc5, enc6);
432
433        assert_eq!(encoder.current_chunk(), &[0x01][..]);
434        assert!(encoder.advance());
435        assert_eq!(encoder.current_chunk(), &[0x02][..]);
436        assert!(encoder.advance());
437        assert_eq!(encoder.current_chunk(), &[0x03][..]);
438        assert!(encoder.advance());
439        assert_eq!(encoder.current_chunk(), &[0x04][..]);
440        assert!(encoder.advance());
441        assert_eq!(encoder.current_chunk(), &[0x05][..]);
442        assert!(encoder.advance());
443        assert_eq!(encoder.current_chunk(), &[0x06][..]);
444        assert!(!encoder.advance());
445        assert!(encoder.current_chunk().is_empty());
446    }
447
448    #[test]
449    fn encode_mixed_composition_with_byte_slices() {
450        // Should encode byte slice, then array, then exhausted.
451        let enc1 = TestBytes(&[0xFF, 0xEE]).encoder();
452        let enc2 = TestArray([0xDD, 0xCC]).encoder();
453        let mut encoder = Encoder2::new(enc1, enc2);
454
455        assert_eq!(encoder.current_chunk(), &[0xFF, 0xEE][..]);
456        assert!(encoder.advance());
457        assert_eq!(encoder.current_chunk(), &[0xDD, 0xCC][..]);
458        assert!(!encoder.advance());
459        assert!(encoder.current_chunk().is_empty());
460    }
461
462    #[test]
463    fn encode_nested_composition() {
464        // Should encode empty array, single byte array, then three byte array, then exhausted.
465        let enc1 = TestArray([]).encoder();
466        let enc2 = TestArray([0x42]).encoder();
467        let enc3 = TestArray([0x43, 0x44, 0x45]).encoder();
468        let mut encoder = Encoder3::new(enc1, enc2, enc3);
469
470        assert!(encoder.current_chunk().is_empty());
471        assert!(encoder.advance());
472        assert_eq!(encoder.current_chunk(), &[0x42][..]);
473        assert!(encoder.advance());
474        assert_eq!(encoder.current_chunk(), &[0x43, 0x44, 0x45][..]);
475        assert!(!encoder.advance());
476        assert!(encoder.current_chunk().is_empty());
477    }
478
479    #[test]
480    fn encode_slice_with_array_composition() {
481        // Should encode slice elements, then array, then exhausted.
482        let slice = &[TestArray([0x10, 0x11]), TestArray([0x12, 0x13])];
483        let slice_enc = SliceEncoder::without_length_prefix(slice);
484        let array_enc = TestArray([0x20, 0x21]).encoder();
485        let mut encoder = Encoder2::new(slice_enc, array_enc);
486
487        assert_eq!(encoder.current_chunk(), &[0x10, 0x11][..]);
488        assert!(encoder.advance());
489        assert_eq!(encoder.current_chunk(), &[0x12, 0x13][..]);
490        assert!(encoder.advance());
491        assert_eq!(encoder.current_chunk(), &[0x20, 0x21][..]);
492        assert!(!encoder.advance());
493        assert!(encoder.current_chunk().is_empty());
494    }
495
496    #[test]
497    fn encode_array_with_slice_composition() {
498        // Should encode header array, then slice elements, then exhausted.
499        let header = TestArray([0xFF, 0xFE]).encoder();
500        let slice = &[TestArray([0x01]), TestArray([0x02]), TestArray([0x03])];
501        let slice_enc = SliceEncoder::without_length_prefix(slice);
502        let mut encoder = Encoder2::new(header, slice_enc);
503
504        assert_eq!(encoder.current_chunk(), &[0xFF, 0xFE][..]);
505        assert!(encoder.advance());
506        assert_eq!(encoder.current_chunk(), &[0x01][..]);
507        assert!(encoder.advance());
508        assert_eq!(encoder.current_chunk(), &[0x02][..]);
509        assert!(encoder.advance());
510        assert_eq!(encoder.current_chunk(), &[0x03][..]);
511        assert!(!encoder.advance());
512        assert!(encoder.current_chunk().is_empty());
513    }
514
515    #[test]
516    fn encode_multiple_slices_composition() {
517        // Should encode three slices in sequence, then exhausted.
518        let slice1 = &[TestArray([0xA1]), TestArray([0xA2])];
519        let slice2: &[TestArray<1>] = &[];
520        let slice3 = &[TestArray([0xC1]), TestArray([0xC2]), TestArray([0xC3])];
521
522        let enc1 = SliceEncoder::without_length_prefix(slice1);
523        let enc2 = SliceEncoder::without_length_prefix(slice2);
524        let enc3 = SliceEncoder::without_length_prefix(slice3);
525        let mut encoder = Encoder3::new(enc1, enc2, enc3);
526
527        assert_eq!(encoder.current_chunk(), &[0xA1][..]);
528        assert!(encoder.advance());
529        assert_eq!(encoder.current_chunk(), &[0xA2][..]);
530
531        // Skip the empty slice
532        assert!(encoder.advance());
533
534        assert!(encoder.advance());
535        assert_eq!(encoder.current_chunk(), &[0xC1][..]);
536        assert!(encoder.advance());
537        assert_eq!(encoder.current_chunk(), &[0xC2][..]);
538        assert!(encoder.advance());
539        assert_eq!(encoder.current_chunk(), &[0xC3][..]);
540        assert!(!encoder.advance());
541        assert!(encoder.current_chunk().is_empty());
542    }
543
544    #[test]
545    fn encode_complex_nested_structure() {
546        // Should encode header, slice with elements, and footer with prefix, then exhausted.
547        let header = TestBytes(&[0xDE, 0xAD]).encoder();
548        let data_slice = &[TestArray([0x01, 0x02]), TestArray([0x03, 0x04])];
549        let slice_enc = SliceEncoder::without_length_prefix(data_slice);
550        let footer = TestBytes(&[0xBE, 0xEF]).encoder();
551        let mut encoder = Encoder3::new(header, slice_enc, footer);
552
553        assert_eq!(encoder.current_chunk(), &[0xDE, 0xAD][..]);
554        assert!(encoder.advance());
555        assert_eq!(encoder.current_chunk(), &[0x01, 0x02][..]);
556        assert!(encoder.advance());
557        assert_eq!(encoder.current_chunk(), &[0x03, 0x04][..]);
558        assert!(encoder.advance());
559        assert_eq!(encoder.current_chunk(), &[0xBE, 0xEF][..]);
560        assert!(!encoder.advance());
561        assert!(encoder.current_chunk().is_empty());
562    }
563    #[test]
564    fn encode_compact_size() {
565        // 1-byte
566        let mut e = CompactSizeEncoder::new(0x10usize);
567        assert_eq!(e.current_chunk(), &[0x10][..]);
568        assert!(!e.advance());
569        assert!(e.current_chunk().is_empty());
570
571        let mut e = CompactSizeEncoder::new(0xFCusize);
572        assert_eq!(e.current_chunk(), &[0xFC][..]);
573        assert!(!e.advance());
574        assert!(e.current_chunk().is_empty());
575
576        // 0xFD + u16
577        let mut e = CompactSizeEncoder::new(0x00FDusize);
578        assert_eq!(e.current_chunk(), &[0xFD, 0xFD, 0x00][..]);
579        assert!(!e.advance());
580        assert!(e.current_chunk().is_empty());
581
582        let mut e = CompactSizeEncoder::new(0x0FFFusize);
583        assert_eq!(e.current_chunk(), &[0xFD, 0xFF, 0x0F][..]);
584        assert!(!e.advance());
585        assert!(e.current_chunk().is_empty());
586
587        // 0xFE + u32
588        let mut e = CompactSizeEncoder::new(0x0001_0000usize);
589        assert_eq!(e.current_chunk(), &[0xFE, 0x00, 0x00, 0x01, 0x00][..]);
590        assert!(!e.advance());
591        assert!(e.current_chunk().is_empty());
592
593        let mut e = CompactSizeEncoder::new(0x0F0F_0F0Fusize);
594        assert_eq!(e.current_chunk(), &[0xFE, 0x0F, 0x0F, 0x0F, 0x0F][..]);
595        assert!(!e.advance());
596        assert!(e.current_chunk().is_empty());
597
598        // 0xFF + u64
599        // This test only runs on systems with >= 64 bit usize.
600        if core::mem::size_of::<usize>() >= 8 {
601            let mut e = CompactSizeEncoder::new(0x0000_F0F0_F0F0_F0E0u64 as usize);
602            assert_eq!(
603                e.current_chunk(),
604                &[0xFF, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00][..]
605            );
606            assert!(!e.advance());
607            assert!(e.current_chunk().is_empty());
608        }
609
610        // > u64::MAX encodes as u64::MAX.
611        // This test only runs on systems with > 64 bit usize.
612        if core::mem::size_of::<usize>() > 8 {
613            let mut e = CompactSizeEncoder::new((u128::from(u64::MAX) + 5) as usize);
614            assert_eq!(
615                e.current_chunk(),
616                &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF][..]
617            );
618            assert!(!e.advance());
619            assert!(e.current_chunk().is_empty());
620        }
621    }
622
623    #[test]
624    fn iter_encoder() {
625        let test_array = TestArray([1u8, 2, 3, 4]);
626        let mut iter = crate::EncodableByteIter::new(&test_array);
627        let mut byte = iter.next().unwrap();
628        assert_eq!(byte, 1u8);
629        byte = iter.next().unwrap();
630        assert_eq!(byte, 2u8);
631        byte = iter.next().unwrap();
632        assert_eq!(byte, 3u8);
633        byte = iter.next().unwrap();
634        assert_eq!(byte, 4u8);
635        let none = iter.next();
636        assert_eq!(none, None);
637    }
638}