consensus_encoding: move encoders inline tests to integration
What changed, and why it matters
This commit simply moves existing unit tests from inside the source file to a separate integration test file. No production code behavior was changed, and nothing about how the library works in real use was modified. It is a routine test reorganization with no security relevance.
No security action needed; this is a non-functional test relocation.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff removes the mod tests block from consensus_encoding/src/encode/encoders.rs and adds the same tests (with minor import adjustments and a renamed local helper type to avoid a name clash) into consensus_encoding/tests/encode.rs. The production encoder implementations are untouched. This is a pure refactoring of test location.
Changed components
consensus_encoding/src/encode/encoders.rsconsensus_encoding/tests/encode.rsInspect captured patch +460 / −459
diff --git a/consensus_encoding/src/encode/encoders.rs b/consensus_encoding/src/encode/encoders.rs
index 59a68418..3bc42887 100644
--- a/consensus_encoding/src/encode/encoders.rs
+++ b/consensus_encoding/src/encode/encoders.rs
@@ -328,437 +328,6 @@ impl ExactSizeEncoder for CompactSizeEncoder {
mod tests {
use super::*;
- struct TestBytes<'a>(&'a [u8]);
-
- impl Encodable for TestBytes<'_> {
- type Encoder<'e>
- = BytesEncoder<'e>
- where
- Self: 'e;
-
- fn encoder(&self) -> Self::Encoder<'_> { BytesEncoder::without_length_prefix(self.0) }
- }
-
- struct TestArray<const N: usize>([u8; N]);
-
- impl<const N: usize> Encodable for TestArray<N> {
- type Encoder<'e>
- = ArrayEncoder<N>
- where
- Self: 'e;
-
- fn encoder(&self) -> Self::Encoder<'_> { ArrayEncoder::without_length_prefix(self.0) }
- }
-
- #[test]
- fn encode_array_with_data() {
- // Should have one chunk with the array data, then exhausted.
- let test_array = TestArray([1u8, 2, 3, 4]);
- let mut encoder = test_array.encoder();
- assert_eq!(encoder.len(), 4);
- assert!(!encoder.is_empty());
- assert_eq!(encoder.current_chunk(), &[1u8, 2, 3, 4][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_empty_array() {
- // Empty array should have one empty chunk, then exhausted.
- let test_array = TestArray([]);
- let mut encoder = test_array.encoder();
- assert_eq!(encoder.len(), 0);
- assert!(encoder.is_empty());
- assert!(encoder.current_chunk().is_empty());
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_array_ref_with_data() {
- // Should have one chunk with the array data, then exhausted.
- let data = [1u8, 2, 3, 4];
- let mut encoder = ArrayRefEncoder::without_length_prefix(&data);
- assert_eq!(encoder.len(), 4);
- assert!(!encoder.is_empty());
- assert_eq!(encoder.current_chunk(), &[1u8, 2, 3, 4][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- assert_eq!(encoder.len(), 0);
- }
-
- #[test]
- fn encode_empty_array_ref() {
- // Empty array should have one empty chunk, then exhausted.
- let data = [];
- let mut encoder = ArrayRefEncoder::without_length_prefix(&data);
- assert_eq!(encoder.len(), 0);
- assert!(encoder.is_empty());
- assert!(encoder.current_chunk().is_empty());
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_byte_slice_without_prefix() {
- // Should have one chunk with the byte data, then exhausted.
- let obj = [1u8, 2, 3];
- let test_bytes = TestBytes(&obj);
- let mut encoder = test_bytes.encoder();
-
- assert_eq!(encoder.len(), 3);
- assert!(!encoder.is_empty());
-
- assert_eq!(encoder.current_chunk(), &[1u8, 2, 3][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_empty_byte_slice_without_prefix() {
- // Should have one empty chunk, then exhausted.
- let obj = [];
- let test_bytes = TestBytes(&obj);
- let mut encoder = test_bytes.encoder();
-
- assert_eq!(encoder.len(), 0);
- assert!(encoder.is_empty());
-
- assert!(encoder.current_chunk().is_empty());
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_slice_with_elements() {
- // Should have the element chunks, then exhausted.
- let slice = &[TestArray([0x34, 0x12, 0x00, 0x00]), TestArray([0x78, 0x56, 0x00, 0x00])];
- let mut encoder = SliceEncoder::without_length_prefix(slice);
-
- assert_eq!(encoder.current_chunk(), &[0x34, 0x12, 0x00, 0x00][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x78, 0x56, 0x00, 0x00][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_empty_slice() {
- // Should immediately be exhausted.
- let slice: &[TestArray<4>] = &[];
- let mut encoder = SliceEncoder::without_length_prefix(slice);
-
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_slice_with_zero_sized_arrays() {
- // Should have empty array chunks, then exhausted.
- let slice = &[TestArray([]), TestArray([])];
- let mut encoder = SliceEncoder::without_length_prefix(slice);
-
- assert!(encoder.current_chunk().is_empty());
- // The slice advanced is optimized to skip over empty chunks.
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_two_arrays() {
- // Should encode first array, then second array, then exhausted.
- let enc1 = TestArray([1u8, 2]).encoder();
- let enc2 = TestArray([3u8, 4]).encoder();
- let mut encoder = Encoder2::new(enc1, enc2);
-
- assert_eq!(encoder.len(), 4);
- assert!(!encoder.is_empty());
-
- assert_eq!(encoder.current_chunk(), &[1u8, 2][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[3u8, 4][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_two_empty_arrays() {
- // Should encode first empty array, then second empty array, then exhausted.
- let enc1 = TestArray([]).encoder();
- let enc2 = TestArray([]).encoder();
- let mut encoder = Encoder2::new(enc1, enc2);
-
- assert_eq!(encoder.len(), 0);
- assert!(encoder.is_empty());
-
- assert!(encoder.current_chunk().is_empty());
- assert!(encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_three_arrays() {
- // Should encode three arrays in sequence, then exhausted.
- let enc1 = TestArray([1u8]).encoder();
- let enc2 = TestArray([2u8, 3u8]).encoder();
- let enc3 = TestArray([4u8, 5u8, 6u8]).encoder();
- let mut encoder = Encoder3::new(enc1, enc2, enc3);
-
- assert_eq!(encoder.len(), 6);
- assert!(!encoder.is_empty());
-
- assert_eq!(encoder.current_chunk(), &[1u8][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[2u8, 3u8][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[4u8, 5u8, 6u8][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_four_arrays() {
- // Should encode four arrays in sequence, then exhausted.
- let enc1 = TestArray([0x10]).encoder();
- let enc2 = TestArray([0x20]).encoder();
- let enc3 = TestArray([0x30]).encoder();
- let enc4 = TestArray([0x40]).encoder();
- let mut encoder = Encoder4::new(enc1, enc2, enc3, enc4);
-
- assert_eq!(encoder.len(), 4);
- assert!(!encoder.is_empty());
-
- assert_eq!(encoder.current_chunk(), &[0x10][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x20][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x30][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x40][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_six_arrays() {
- // Should encode six arrays in sequence, then exhausted.
- let enc1 = TestArray([0x01]).encoder();
- let enc2 = TestArray([0x02]).encoder();
- let enc3 = TestArray([0x03]).encoder();
- let enc4 = TestArray([0x04]).encoder();
- let enc5 = TestArray([0x05]).encoder();
- let enc6 = TestArray([0x06]).encoder();
- let mut encoder = Encoder6::new(enc1, enc2, enc3, enc4, enc5, enc6);
-
- assert_eq!(encoder.len(), 6);
- assert!(!encoder.is_empty());
-
- assert_eq!(encoder.current_chunk(), &[0x01][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x02][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x03][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x04][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x05][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x06][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_mixed_composition_with_byte_slices() {
- // Should encode byte slice, then array, then exhausted.
- let enc1 = TestBytes(&[0xFF, 0xEE]).encoder();
- let enc2 = TestArray([0xDD, 0xCC]).encoder();
- let mut encoder = Encoder2::new(enc1, enc2);
-
- assert_eq!(encoder.len(), 4);
- assert!(!encoder.is_empty());
-
- assert_eq!(encoder.current_chunk(), &[0xFF, 0xEE][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0xDD, 0xCC][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_nested_composition() {
- // Should encode empty array, single byte array, then three byte array, then exhausted.
- let enc1 = TestArray([]).encoder();
- let enc2 = TestArray([0x42]).encoder();
- let enc3 = TestArray([0x43, 0x44, 0x45]).encoder();
- let mut encoder = Encoder3::new(enc1, enc2, enc3);
-
- assert_eq!(encoder.len(), 4);
- assert!(!encoder.is_empty());
-
- assert!(encoder.current_chunk().is_empty());
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x42][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x43, 0x44, 0x45][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_slice_with_array_composition() {
- // Should encode slice elements, then array, then exhausted.
- let slice = &[TestArray([0x10, 0x11]), TestArray([0x12, 0x13])];
- let slice_enc = SliceEncoder::without_length_prefix(slice);
- let array_enc = TestArray([0x20, 0x21]).encoder();
- let mut encoder = Encoder2::new(slice_enc, array_enc);
-
- assert_eq!(encoder.current_chunk(), &[0x10, 0x11][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x12, 0x13][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x20, 0x21][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_array_with_slice_composition() {
- // Should encode header array, then slice elements, then exhausted.
- let header = TestArray([0xFF, 0xFE]).encoder();
- let slice = &[TestArray([0x01]), TestArray([0x02]), TestArray([0x03])];
- let slice_enc = SliceEncoder::without_length_prefix(slice);
- let mut encoder = Encoder2::new(header, slice_enc);
-
- assert_eq!(encoder.current_chunk(), &[0xFF, 0xFE][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x01][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x02][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x03][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_multiple_slices_composition() {
- // Should encode three slices in sequence, then exhausted.
- let slice1 = &[TestArray([0xA1]), TestArray([0xA2])];
- let slice2: &[TestArray<1>] = &[];
- let slice3 = &[TestArray([0xC1]), TestArray([0xC2]), TestArray([0xC3])];
-
- let enc1 = SliceEncoder::without_length_prefix(slice1);
- let enc2 = SliceEncoder::without_length_prefix(slice2);
- let enc3 = SliceEncoder::without_length_prefix(slice3);
- let mut encoder = Encoder3::new(enc1, enc2, enc3);
-
- assert_eq!(encoder.current_chunk(), &[0xA1][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0xA2][..]);
-
- // Skip the empty slice
- assert!(encoder.advance());
-
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0xC1][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0xC2][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0xC3][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
-
- #[test]
- fn encode_complex_nested_structure() {
- // Should encode header, slice with elements, and footer with prefix, then exhausted.
- let header = TestBytes(&[0xDE, 0xAD]).encoder();
- let data_slice = &[TestArray([0x01, 0x02]), TestArray([0x03, 0x04])];
- let slice_enc = SliceEncoder::without_length_prefix(data_slice);
- let footer = TestBytes(&[0xBE, 0xEF]).encoder();
- let mut encoder = Encoder3::new(header, slice_enc, footer);
-
- assert_eq!(encoder.current_chunk(), &[0xDE, 0xAD][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x01, 0x02][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0x03, 0x04][..]);
- assert!(encoder.advance());
- assert_eq!(encoder.current_chunk(), &[0xBE, 0xEF][..]);
- assert!(!encoder.advance());
- assert!(encoder.current_chunk().is_empty());
- }
- #[test]
- fn encode_compact_size() {
- // 1-byte
- let mut e = CompactSizeEncoder::new(0x10usize);
- assert_eq!(e.current_chunk(), &[0x10][..]);
- assert_eq!(e.len(), 1);
- assert!(!e.advance());
- assert!(e.current_chunk().is_empty());
-
- let mut e = CompactSizeEncoder::new(0xFCusize);
- assert_eq!(e.current_chunk(), &[0xFC][..]);
- assert_eq!(e.len(), 1);
- assert!(!e.advance());
- assert!(e.current_chunk().is_empty());
-
- // 0xFD + u16
- let mut e = CompactSizeEncoder::new(0x00FDusize);
- assert_eq!(e.current_chunk(), &[0xFD, 0xFD, 0x00][..]);
- assert_eq!(e.len(), 3);
- assert!(!e.advance());
- assert!(e.current_chunk().is_empty());
-
- let mut e = CompactSizeEncoder::new(0x0FFFusize);
- assert_eq!(e.current_chunk(), &[0xFD, 0xFF, 0x0F][..]);
- assert_eq!(e.len(), 3);
- assert!(!e.advance());
- assert!(e.current_chunk().is_empty());
-
- // 0xFE + u32
- let mut e = CompactSizeEncoder::new(0x0001_0000usize);
- assert_eq!(e.current_chunk(), &[0xFE, 0x00, 0x00, 0x01, 0x00][..]);
- assert_eq!(e.len(), 5);
- assert!(!e.advance());
- assert!(e.current_chunk().is_empty());
-
- let mut e = CompactSizeEncoder::new(0x0F0F_0F0Fusize);
- assert_eq!(e.current_chunk(), &[0xFE, 0x0F, 0x0F, 0x0F, 0x0F][..]);
- assert_eq!(e.len(), 5);
- assert!(!e.advance());
- assert!(e.current_chunk().is_empty());
-
- // 0xFF + u64
- // This test only runs on systems with >= 64 bit usize.
- if core::mem::size_of::<usize>() >= 8 {
- let mut e = CompactSizeEncoder::new(0x0000_F0F0_F0F0_F0E0u64 as usize);
- assert_eq!(
- e.current_chunk(),
- &[0xFF, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00][..]
- );
- assert_eq!(e.len(), 9);
- assert!(!e.advance());
- assert!(e.current_chunk().is_empty());
- }
-
- // > u64::MAX encodes as u64::MAX.
- // This test only runs on systems with > 64 bit usize.
- if core::mem::size_of::<usize>() > 8 {
- let mut e = CompactSizeEncoder::new((u128::from(u64::MAX) + 5) as usize);
- assert_eq!(
- e.current_chunk(),
- &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF][..]
- );
- assert_eq!(e.len(), 9);
- assert!(!e.advance());
- assert!(e.current_chunk().is_empty());
- }
- }
-
#[test]
fn encoded_value_1_byte() {
// Check lower bound, upper bound (and implicitly endian-ness).
@@ -807,22 +376,4 @@ mod tests {
encoded_value_9_byte_endianness, 9, 0x0123_4567_89AB_CDEF, [0xFF, 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01];
encoded_value_9_byte_upper_bound, 9, u64::MAX, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
}
-
- #[test]
- fn iter_encoder() {
- let test_array = TestArray([1u8, 2, 3, 4]);
- let mut iter = crate::EncodableByteIter::new(&test_array);
-
- assert_eq!(iter.len(), 4);
-
- assert_eq!(iter.next().unwrap(), 1);
- assert_eq!(iter.len(), 3);
- assert_eq!(iter.next().unwrap(), 2);
- assert_eq!(iter.len(), 2);
- assert_eq!(iter.next().unwrap(), 3);
- assert_eq!(iter.len(), 1);
- assert_eq!(iter.next().unwrap(), 4);
- assert_eq!(iter.len(), 0);
- assert!(iter.next().is_none());
- }
}
diff --git a/consensus_encoding/tests/encode.rs b/consensus_encoding/tests/encode.rs
index 3d531b55..75e0bdcb 100644
--- a/consensus_encoding/tests/encode.rs
+++ b/consensus_encoding/tests/encode.rs
@@ -6,10 +6,31 @@
use std::io::{Cursor, Write};
use bitcoin_consensus_encoding::{
- ArrayEncoder, BytesEncoder, CompactSizeEncoder, Encoder, Encoder2,
+ ArrayEncoder, ArrayRefEncoder, BytesEncoder, CompactSizeEncoder, Encodable, EncodableByteIter,
+ Encoder, Encoder2, Encoder3, Encoder4, Encoder6, ExactSizeEncoder, SliceEncoder,
};
-#[cfg(feature = "alloc")]
-use bitcoin_consensus_encoding::{Encodable, SliceEncoder};
+
+struct TestBytes<'a>(&'a [u8]);
+
+impl Encodable for TestBytes<'_> {
+ type Encoder<'e>
+ = BytesEncoder<'e>
+ where
+ Self: 'e;
+
+ fn encoder(&self) -> Self::Encoder<'_> { BytesEncoder::without_length_prefix(self.0) }
+}
+
+struct TestArray<const N: usize>([u8; N]);
+
+impl<const N: usize> Encodable for TestArray<N> {
+ type Encoder<'e>
+ = ArrayEncoder<N>
+ where
+ Self: 'e;
+
+ fn encoder(&self) -> Self::Encoder<'_> { ArrayEncoder::without_length_prefix(self.0) }
+}
// Simple test type that implements Encodable.
#[cfg(feature = "alloc")]
@@ -127,9 +148,9 @@ fn encode_newtype_lifetime_flexibility() {
#[test]
fn encode_slice_encoder_mixed_empty_and_data() {
// Test SliceEncoder behavior with mixed empty and non-empty elements.
- struct TestBytes(Vec<u8>);
+ struct TestBytesVec(Vec<u8>);
- impl Encodable for TestBytes {
+ impl Encodable for TestBytesVec {
type Encoder<'e>
= BytesEncoder<'e>
where
@@ -138,7 +159,12 @@ fn encode_slice_encoder_mixed_empty_and_data() {
fn encoder(&self) -> Self::Encoder<'_> { BytesEncoder::without_length_prefix(&self.0) }
}
- let slice = &[TestBytes(vec![]), TestBytes(vec![1, 2]), TestBytes(vec![]), TestBytes(vec![3])];
+ let slice = &[
+ TestBytesVec(vec![]),
+ TestBytesVec(vec![1, 2]),
+ TestBytesVec(vec![]),
+ TestBytesVec(vec![3]),
+ ];
let mut encoder = SliceEncoder::without_length_prefix(slice);
@@ -202,8 +228,6 @@ fn encode_encoder_advance_multiple_times_when_exhausted() {
#[test]
fn encode_option_encoder_some() {
- use bitcoin_consensus_encoding::Encoder;
-
let mut encoder = Some(ArrayEncoder::<3>::without_length_prefix([1, 2, 3]));
assert_eq!(encoder.current_chunk(), &[1, 2, 3]);
assert!(!encoder.advance());
@@ -212,10 +236,436 @@ fn encode_option_encoder_some() {
#[test]
fn encode_option_encoder_none() {
- use bitcoin_consensus_encoding::Encoder;
-
let mut encoder: Option<ArrayEncoder<3>> = None;
assert!(encoder.current_chunk().is_empty());
assert!(!encoder.advance());
assert!(encoder.current_chunk().is_empty());
}
+
+#[test]
+fn encode_array_with_data() {
+ // Should have one chunk with the array data, then exhausted.
+ let test_array = TestArray([1u8, 2, 3, 4]);
+ let mut encoder = test_array.encoder();
+ assert_eq!(encoder.len(), 4);
+ assert!(!encoder.is_empty());
+ assert_eq!(encoder.current_chunk(), &[1u8, 2, 3, 4][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_empty_array() {
+ // Empty array should have one empty chunk, then exhausted.
+ let test_array = TestArray([]);
+ let mut encoder = test_array.encoder();
+ assert_eq!(encoder.len(), 0);
+ assert!(encoder.is_empty());
+ assert!(encoder.current_chunk().is_empty());
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_array_ref_with_data() {
+ // Should have one chunk with the array data, then exhausted.
+ let data = [1u8, 2, 3, 4];
+ let mut encoder = ArrayRefEncoder::without_length_prefix(&data);
+ assert_eq!(encoder.len(), 4);
+ assert!(!encoder.is_empty());
+ assert_eq!(encoder.current_chunk(), &[1u8, 2, 3, 4][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+ assert_eq!(encoder.len(), 0);
+}
+
+#[test]
+fn encode_empty_array_ref() {
+ // Empty array should have one empty chunk, then exhausted.
+ let data = [];
+ let mut encoder = ArrayRefEncoder::without_length_prefix(&data);
+ assert_eq!(encoder.len(), 0);
+ assert!(encoder.is_empty());
+ assert!(encoder.current_chunk().is_empty());
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_byte_slice_without_prefix() {
+ // Should have one chunk with the byte data, then exhausted.
+ let obj = [1u8, 2, 3];
+ let test_bytes = TestBytes(&obj);
+ let mut encoder = test_bytes.encoder();
+
+ assert_eq!(encoder.len(), 3);
+ assert!(!encoder.is_empty());
+
+ assert_eq!(encoder.current_chunk(), &[1u8, 2, 3][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_empty_byte_slice_without_prefix() {
+ // Should have one empty chunk, then exhausted.
+ let obj = [];
+ let test_bytes = TestBytes(&obj);
+ let mut encoder = test_bytes.encoder();
+
+ assert_eq!(encoder.len(), 0);
+ assert!(encoder.is_empty());
+
+ assert!(encoder.current_chunk().is_empty());
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_slice_with_elements() {
+ // Should have the element chunks, then exhausted.
+ let slice = &[TestArray([0x34, 0x12, 0x00, 0x00]), TestArray([0x78, 0x56, 0x00, 0x00])];
+ let mut encoder = SliceEncoder::without_length_prefix(slice);
+
+ assert_eq!(encoder.current_chunk(), &[0x34, 0x12, 0x00, 0x00][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x78, 0x56, 0x00, 0x00][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_empty_slice() {
+ // Should immediately be exhausted.
+ let slice: &[TestArray<4>] = &[];
+ let mut encoder = SliceEncoder::without_length_prefix(slice);
+
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_slice_with_zero_sized_arrays() {
+ // Should have empty array chunks, then exhausted.
+ let slice = &[TestArray([]), TestArray([])];
+ let mut encoder = SliceEncoder::without_length_prefix(slice);
+
+ assert!(encoder.current_chunk().is_empty());
+ // The slice advanced is optimized to skip over empty chunks.
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_two_arrays() {
+ // Should encode first array, then second array, then exhausted.
+ let enc1 = TestArray([1u8, 2]).encoder();
+ let enc2 = TestArray([3u8, 4]).encoder();
+ let mut encoder = Encoder2::new(enc1, enc2);
+
+ assert_eq!(encoder.len(), 4);
+ assert!(!encoder.is_empty());
+
+ assert_eq!(encoder.current_chunk(), &[1u8, 2][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[3u8, 4][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_two_empty_arrays() {
+ // Should encode first empty array, then second empty array, then exhausted.
+ let enc1 = TestArray([]).encoder();
+ let enc2 = TestArray([]).encoder();
+ let mut encoder = Encoder2::new(enc1, enc2);
+
+ assert_eq!(encoder.len(), 0);
+ assert!(encoder.is_empty());
+
+ assert!(encoder.current_chunk().is_empty());
+ assert!(encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_three_arrays() {
+ // Should encode three arrays in sequence, then exhausted.
+ let enc1 = TestArray([1u8]).encoder();
+ let enc2 = TestArray([2u8, 3u8]).encoder();
+ let enc3 = TestArray([4u8, 5u8, 6u8]).encoder();
+ let mut encoder = Encoder3::new(enc1, enc2, enc3);
+
+ assert_eq!(encoder.len(), 6);
+ assert!(!encoder.is_empty());
+
+ assert_eq!(encoder.current_chunk(), &[1u8][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[2u8, 3u8][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[4u8, 5u8, 6u8][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_four_arrays() {
+ // Should encode four arrays in sequence, then exhausted.
+ let enc1 = TestArray([0x10]).encoder();
+ let enc2 = TestArray([0x20]).encoder();
+ let enc3 = TestArray([0x30]).encoder();
+ let enc4 = TestArray([0x40]).encoder();
+ let mut encoder = Encoder4::new(enc1, enc2, enc3, enc4);
+
+ assert_eq!(encoder.len(), 4);
+ assert!(!encoder.is_empty());
+
+ assert_eq!(encoder.current_chunk(), &[0x10][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x20][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x30][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x40][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_six_arrays() {
+ // Should encode six arrays in sequence, then exhausted.
+ let enc1 = TestArray([0x01]).encoder();
+ let enc2 = TestArray([0x02]).encoder();
+ let enc3 = TestArray([0x03]).encoder();
+ let enc4 = TestArray([0x04]).encoder();
+ let enc5 = TestArray([0x05]).encoder();
+ let enc6 = TestArray([0x06]).encoder();
+ let mut encoder = Encoder6::new(enc1, enc2, enc3, enc4, enc5, enc6);
+
+ assert_eq!(encoder.len(), 6);
+ assert!(!encoder.is_empty());
+
+ assert_eq!(encoder.current_chunk(), &[0x01][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x02][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x03][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x04][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x05][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x06][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_mixed_composition_with_byte_slices() {
+ // Should encode byte slice, then array, then exhausted.
+ let enc1 = TestBytes(&[0xFF, 0xEE]).encoder();
+ let enc2 = TestArray([0xDD, 0xCC]).encoder();
+ let mut encoder = Encoder2::new(enc1, enc2);
+
+ assert_eq!(encoder.len(), 4);
+ assert!(!encoder.is_empty());
+
+ assert_eq!(encoder.current_chunk(), &[0xFF, 0xEE][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0xDD, 0xCC][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_nested_composition() {
+ // Should encode empty array, single byte array, then three byte array, then exhausted.
+ let enc1 = TestArray([]).encoder();
+ let enc2 = TestArray([0x42]).encoder();
+ let enc3 = TestArray([0x43, 0x44, 0x45]).encoder();
+ let mut encoder = Encoder3::new(enc1, enc2, enc3);
+
+ assert_eq!(encoder.len(), 4);
+ assert!(!encoder.is_empty());
+
+ assert!(encoder.current_chunk().is_empty());
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x42][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x43, 0x44, 0x45][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_slice_with_array_composition() {
+ // Should encode slice elements, then array, then exhausted.
+ let slice = &[TestArray([0x10, 0x11]), TestArray([0x12, 0x13])];
+ let slice_enc = SliceEncoder::without_length_prefix(slice);
+ let array_enc = TestArray([0x20, 0x21]).encoder();
+ let mut encoder = Encoder2::new(slice_enc, array_enc);
+
+ assert_eq!(encoder.current_chunk(), &[0x10, 0x11][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x12, 0x13][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x20, 0x21][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_array_with_slice_composition() {
+ // Should encode header array, then slice elements, then exhausted.
+ let header = TestArray([0xFF, 0xFE]).encoder();
+ let slice = &[TestArray([0x01]), TestArray([0x02]), TestArray([0x03])];
+ let slice_enc = SliceEncoder::without_length_prefix(slice);
+ let mut encoder = Encoder2::new(header, slice_enc);
+
+ assert_eq!(encoder.current_chunk(), &[0xFF, 0xFE][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x01][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x02][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x03][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_multiple_slices_composition() {
+ // Should encode three slices in sequence, then exhausted.
+ let slice1 = &[TestArray([0xA1]), TestArray([0xA2])];
+ let slice2: &[TestArray<1>] = &[];
+ let slice3 = &[TestArray([0xC1]), TestArray([0xC2]), TestArray([0xC3])];
+
+ let enc1 = SliceEncoder::without_length_prefix(slice1);
+ let enc2 = SliceEncoder::without_length_prefix(slice2);
+ let enc3 = SliceEncoder::without_length_prefix(slice3);
+ let mut encoder = Encoder3::new(enc1, enc2, enc3);
+
+ assert_eq!(encoder.current_chunk(), &[0xA1][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0xA2][..]);
+
+ // Skip the empty slice
+ assert!(encoder.advance());
+
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0xC1][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0xC2][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0xC3][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_complex_nested_structure() {
+ // Should encode header, slice with elements, and footer with prefix, then exhausted.
+ let header = TestBytes(&[0xDE, 0xAD]).encoder();
+ let data_slice = &[TestArray([0x01, 0x02]), TestArray([0x03, 0x04])];
+ let slice_enc = SliceEncoder::without_length_prefix(data_slice);
+ let footer = TestBytes(&[0xBE, 0xEF]).encoder();
+ let mut encoder = Encoder3::new(header, slice_enc, footer);
+
+ assert_eq!(encoder.current_chunk(), &[0xDE, 0xAD][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x01, 0x02][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0x03, 0x04][..]);
+ assert!(encoder.advance());
+ assert_eq!(encoder.current_chunk(), &[0xBE, 0xEF][..]);
+ assert!(!encoder.advance());
+ assert!(encoder.current_chunk().is_empty());
+}
+
+#[test]
+fn encode_compact_size() {
+ // 1-byte
+ let mut e = CompactSizeEncoder::new(0x10usize);
+ assert_eq!(e.current_chunk(), &[0x10][..]);
+ assert_eq!(e.len(), 1);
+ assert!(!e.advance());
+ assert!(e.current_chunk().is_empty());
+
+ let mut e = CompactSizeEncoder::new(0xFCusize);
+ assert_eq!(e.current_chunk(), &[0xFC][..]);
+ assert_eq!(e.len(), 1);
+ assert!(!e.advance());
+ assert!(e.current_chunk().is_empty());
+
+ // 0xFD + u16
+ let mut e = CompactSizeEncoder::new(0x00FDusize);
+ assert_eq!(e.current_chunk(), &[0xFD, 0xFD, 0x00][..]);
+ assert_eq!(e.len(), 3);
+ assert!(!e.advance());
+ assert!(e.current_chunk().is_empty());
+
+ let mut e = CompactSizeEncoder::new(0x0FFFusize);
+ assert_eq!(e.current_chunk(), &[0xFD, 0xFF, 0x0F][..]);
+ assert_eq!(e.len(), 3);
+ assert!(!e.advance());
+ assert!(e.current_chunk().is_empty());
+
+ // 0xFE + u32
+ let mut e = CompactSizeEncoder::new(0x0001_0000usize);
+ assert_eq!(e.current_chunk(), &[0xFE, 0x00, 0x00, 0x01, 0x00][..]);
+ assert_eq!(e.len(), 5);
+ assert!(!e.advance());
+ assert!(e.current_chunk().is_empty());
+
+ let mut e = CompactSizeEncoder::new(0x0F0F_0F0Fusize);
+ assert_eq!(e.current_chunk(), &[0xFE, 0x0F, 0x0F, 0x0F, 0x0F][..]);
+ assert_eq!(e.len(), 5);
+ assert!(!e.advance());
+ assert!(e.current_chunk().is_empty());
+
+ // 0xFF + u64
+ // This test only runs on systems with >= 64 bit usize.
+ if core::mem::size_of::<usize>() >= 8 {
+ let mut e = CompactSizeEncoder::new(0x0000_F0F0_F0F0_F0E0u64 as usize);
+ assert_eq!(
+ e.current_chunk(),
+ &[0xFF, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00][..]
+ );
+ assert_eq!(e.len(), 9);
+ assert!(!e.advance());
+ assert!(e.current_chunk().is_empty());
+ }
+
+ // > u64::MAX encodes as u64::MAX.
+ // This test only runs on systems with > 64 bit usize.
+ if core::mem::size_of::<usize>() > 8 {
+ let mut e = CompactSizeEncoder::new((u128::from(u64::MAX) + 5) as usize);
+ assert_eq!(
+ e.current_chunk(),
+ &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF][..]
+ );
+ assert_eq!(e.len(), 9);
+ assert!(!e.advance());
+ assert!(e.current_chunk().is_empty());
+ }
+}
+
+#[test]
+fn iter_encoder() {
+ let test_array = TestArray([1u8, 2, 3, 4]);
+ let mut iter = EncodableByteIter::new(&test_array);
+
+ assert_eq!(iter.len(), 4);
+
+ assert_eq!(iter.next().unwrap(), 1);
+ assert_eq!(iter.len(), 3);
+ assert_eq!(iter.next().unwrap(), 2);
+ assert_eq!(iter.len(), 2);
+ assert_eq!(iter.next().unwrap(), 3);
+ assert_eq!(iter.len(), 1);
+ assert_eq!(iter.next().unwrap(), 4);
+ assert_eq!(iter.len(), 0);
+ assert!(iter.next().is_none());
+}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.