Add an iterator to yield the bytes of an encoded object
What changed, and why it matters
This commit adds a new public helper type, EncodableByteIter, that lets callers read the serialized bytes of any Encodable object one byte at a time. It is a pure feature addition with no bug fixes, no changes to existing behavior, and no security-relevant content in the commit message or diff.
No security action required. Review as a normal API addition if desired.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch introduces EncodableByteIter<’s, T: Encodable> in consensus_encoding/src/encode/mod.rs. It wraps T::Encoder<’s>, tracks a position within the current chunk, and implements Iterator
Changed components
consensus_encoding/src/encode/mod.rsconsensus_encoding/src/lib.rsconsensus_encoding/src/encode/encoders.rs (tests only)api/consensus_encoding/all-features.txtapi/consensus_encoding/alloc-only.txtapi/consensus_encoding/no-features.txtInspect captured patch +82 / −1
diff --git a/api/consensus_encoding/all-features.txt b/api/consensus_encoding/all-features.txt
index 916422ba..d622a70f 100644
--- a/api/consensus_encoding/all-features.txt
+++ b/api/consensus_encoding/all-features.txt
@@ -87,6 +87,14 @@ impl<'e, T> core::marker::Sync for bitcoin_consensus_encoding::SliceEncoder<'e,
impl<'e, T> core::marker::Unpin for bitcoin_consensus_encoding::SliceEncoder<'e, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Unpin
impl<'e, T> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::SliceEncoder<'e, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::panic::unwind_safe::RefUnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe
impl<'e, T> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::SliceEncoder<'e, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::panic::unwind_safe::UnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe
+impl<'s, T: bitcoin_consensus_encoding::Encodable + 's> bitcoin_consensus_encoding::EncodableByteIter<'s, T>
+impl<'s, T: bitcoin_consensus_encoding::Encodable + 's> core::iter::traits::iterator::Iterator for bitcoin_consensus_encoding::EncodableByteIter<'s, T>
+impl<'s, T> core::marker::Freeze for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Freeze
+impl<'s, T> core::marker::Send for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Send
+impl<'s, T> core::marker::Sync for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Sync
+impl<'s, T> core::marker::Unpin for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Unpin
+impl<'s, T> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::panic::unwind_safe::RefUnwindSafe
+impl<'s, T> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::panic::unwind_safe::UnwindSafe
impl<'sl> bitcoin_consensus_encoding::BytesEncoder<'sl>
impl<'sl> core::marker::Freeze for bitcoin_consensus_encoding::BytesEncoder<'sl>
impl<'sl> core::marker::Send for bitcoin_consensus_encoding::BytesEncoder<'sl>
@@ -360,6 +368,8 @@ pub fn bitcoin_consensus_encoding::Decoder::end(self) -> core::result::Result<Se
pub fn bitcoin_consensus_encoding::Decoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result<bool, Self::Error>
pub fn bitcoin_consensus_encoding::Decoder::read_limit(&self) -> usize
pub fn bitcoin_consensus_encoding::Encodable::encoder(&self) -> Self::Encoder
+pub fn bitcoin_consensus_encoding::EncodableByteIter<'s, T>::new(encodable: &'s T) -> Self
+pub fn bitcoin_consensus_encoding::EncodableByteIter<'s, T>::next(&mut self) -> core::option::Option<Self::Item>
pub fn bitcoin_consensus_encoding::Encoder2<A, B>::advance(&mut self) -> bool
pub fn bitcoin_consensus_encoding::Encoder2<A, B>::current_chunk(&self) -> &[u8]
pub fn bitcoin_consensus_encoding::Encoder3<A, B, C>::advance(&mut self) -> bool
@@ -414,6 +424,7 @@ pub struct bitcoin_consensus_encoding::Decoder2<A, B> where A: bitcoin_consensus
pub struct bitcoin_consensus_encoding::Decoder3<A, B, C> where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder
pub struct bitcoin_consensus_encoding::Decoder4<A, B, C, D> where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder
pub struct bitcoin_consensus_encoding::Decoder6<A, B, C, D, E, F> where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder, E: bitcoin_consensus_encoding::Decoder, F: bitcoin_consensus_encoding::Decoder
+pub struct bitcoin_consensus_encoding::EncodableByteIter<'s, T: bitcoin_consensus_encoding::Encodable + 's>
pub struct bitcoin_consensus_encoding::Encoder2<A, B>
pub struct bitcoin_consensus_encoding::Encoder3<A, B, C>
pub struct bitcoin_consensus_encoding::Encoder4<A, B, C, D>
@@ -445,5 +456,6 @@ pub type bitcoin_consensus_encoding::Decoder6<A, B, C, D, E, F>::Output = (<A as
pub type bitcoin_consensus_encoding::Decoder::Error
pub type bitcoin_consensus_encoding::Decoder::Output
pub type bitcoin_consensus_encoding::Encodable::Encoder<'s> where Self: 's: bitcoin_consensus_encoding::Encoder
+pub type bitcoin_consensus_encoding::EncodableByteIter<'s, T>::Item = u8
pub type bitcoin_consensus_encoding::VecDecoder<T>::Error = bitcoin_consensus_encoding::VecDecoderError<<<T as bitcoin_consensus_encoding::Decodable>::Decoder as bitcoin_consensus_encoding::Decoder>::Error>
pub type bitcoin_consensus_encoding::VecDecoder<T>::Output = alloc::vec::Vec<T>
diff --git a/api/consensus_encoding/alloc-only.txt b/api/consensus_encoding/alloc-only.txt
index 418a7742..0f5fc978 100644
--- a/api/consensus_encoding/alloc-only.txt
+++ b/api/consensus_encoding/alloc-only.txt
@@ -83,6 +83,14 @@ impl<'e, T> core::marker::Sync for bitcoin_consensus_encoding::SliceEncoder<'e,
impl<'e, T> core::marker::Unpin for bitcoin_consensus_encoding::SliceEncoder<'e, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Unpin
impl<'e, T> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::SliceEncoder<'e, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::panic::unwind_safe::RefUnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe
impl<'e, T> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::SliceEncoder<'e, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::panic::unwind_safe::UnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe
+impl<'s, T: bitcoin_consensus_encoding::Encodable + 's> bitcoin_consensus_encoding::EncodableByteIter<'s, T>
+impl<'s, T: bitcoin_consensus_encoding::Encodable + 's> core::iter::traits::iterator::Iterator for bitcoin_consensus_encoding::EncodableByteIter<'s, T>
+impl<'s, T> core::marker::Freeze for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Freeze
+impl<'s, T> core::marker::Send for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Send
+impl<'s, T> core::marker::Sync for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Sync
+impl<'s, T> core::marker::Unpin for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Unpin
+impl<'s, T> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::panic::unwind_safe::RefUnwindSafe
+impl<'s, T> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::panic::unwind_safe::UnwindSafe
impl<'sl> bitcoin_consensus_encoding::BytesEncoder<'sl>
impl<'sl> core::marker::Freeze for bitcoin_consensus_encoding::BytesEncoder<'sl>
impl<'sl> core::marker::Send for bitcoin_consensus_encoding::BytesEncoder<'sl>
@@ -333,6 +341,8 @@ pub fn bitcoin_consensus_encoding::Decoder::end(self) -> core::result::Result<Se
pub fn bitcoin_consensus_encoding::Decoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result<bool, Self::Error>
pub fn bitcoin_consensus_encoding::Decoder::read_limit(&self) -> usize
pub fn bitcoin_consensus_encoding::Encodable::encoder(&self) -> Self::Encoder
+pub fn bitcoin_consensus_encoding::EncodableByteIter<'s, T>::new(encodable: &'s T) -> Self
+pub fn bitcoin_consensus_encoding::EncodableByteIter<'s, T>::next(&mut self) -> core::option::Option<Self::Item>
pub fn bitcoin_consensus_encoding::Encoder2<A, B>::advance(&mut self) -> bool
pub fn bitcoin_consensus_encoding::Encoder2<A, B>::current_chunk(&self) -> &[u8]
pub fn bitcoin_consensus_encoding::Encoder3<A, B, C>::advance(&mut self) -> bool
@@ -379,6 +389,7 @@ pub struct bitcoin_consensus_encoding::Decoder2<A, B> where A: bitcoin_consensus
pub struct bitcoin_consensus_encoding::Decoder3<A, B, C> where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder
pub struct bitcoin_consensus_encoding::Decoder4<A, B, C, D> where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder
pub struct bitcoin_consensus_encoding::Decoder6<A, B, C, D, E, F> where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder, E: bitcoin_consensus_encoding::Decoder, F: bitcoin_consensus_encoding::Decoder
+pub struct bitcoin_consensus_encoding::EncodableByteIter<'s, T: bitcoin_consensus_encoding::Encodable + 's>
pub struct bitcoin_consensus_encoding::Encoder2<A, B>
pub struct bitcoin_consensus_encoding::Encoder3<A, B, C>
pub struct bitcoin_consensus_encoding::Encoder4<A, B, C, D>
@@ -410,5 +421,6 @@ pub type bitcoin_consensus_encoding::Decoder6<A, B, C, D, E, F>::Output = (<A as
pub type bitcoin_consensus_encoding::Decoder::Error
pub type bitcoin_consensus_encoding::Decoder::Output
pub type bitcoin_consensus_encoding::Encodable::Encoder<'s> where Self: 's: bitcoin_consensus_encoding::Encoder
+pub type bitcoin_consensus_encoding::EncodableByteIter<'s, T>::Item = u8
pub type bitcoin_consensus_encoding::VecDecoder<T>::Error = bitcoin_consensus_encoding::VecDecoderError<<<T as bitcoin_consensus_encoding::Decodable>::Decoder as bitcoin_consensus_encoding::Decoder>::Error>
pub type bitcoin_consensus_encoding::VecDecoder<T>::Output = alloc::vec::Vec<T>
diff --git a/api/consensus_encoding/no-features.txt b/api/consensus_encoding/no-features.txt
index 1b14319b..ec05cdaf 100644
--- a/api/consensus_encoding/no-features.txt
+++ b/api/consensus_encoding/no-features.txt
@@ -49,6 +49,14 @@ impl<'e, T> core::marker::Sync for bitcoin_consensus_encoding::SliceEncoder<'e,
impl<'e, T> core::marker::Unpin for bitcoin_consensus_encoding::SliceEncoder<'e, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Unpin
impl<'e, T> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::SliceEncoder<'e, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::panic::unwind_safe::RefUnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe
impl<'e, T> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::SliceEncoder<'e, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::panic::unwind_safe::UnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe
+impl<'s, T: bitcoin_consensus_encoding::Encodable + 's> bitcoin_consensus_encoding::EncodableByteIter<'s, T>
+impl<'s, T: bitcoin_consensus_encoding::Encodable + 's> core::iter::traits::iterator::Iterator for bitcoin_consensus_encoding::EncodableByteIter<'s, T>
+impl<'s, T> core::marker::Freeze for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Freeze
+impl<'s, T> core::marker::Send for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Send
+impl<'s, T> core::marker::Sync for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Sync
+impl<'s, T> core::marker::Unpin for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::marker::Unpin
+impl<'s, T> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::panic::unwind_safe::RefUnwindSafe
+impl<'s, T> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where <T as bitcoin_consensus_encoding::Encodable>::Encoder: core::panic::unwind_safe::UnwindSafe
impl<'sl> bitcoin_consensus_encoding::BytesEncoder<'sl>
impl<'sl> core::marker::Freeze for bitcoin_consensus_encoding::BytesEncoder<'sl>
impl<'sl> core::marker::Send for bitcoin_consensus_encoding::BytesEncoder<'sl>
@@ -267,6 +275,8 @@ pub fn bitcoin_consensus_encoding::Decoder::end(self) -> core::result::Result<Se
pub fn bitcoin_consensus_encoding::Decoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result<bool, Self::Error>
pub fn bitcoin_consensus_encoding::Decoder::read_limit(&self) -> usize
pub fn bitcoin_consensus_encoding::Encodable::encoder(&self) -> Self::Encoder
+pub fn bitcoin_consensus_encoding::EncodableByteIter<'s, T>::new(encodable: &'s T) -> Self
+pub fn bitcoin_consensus_encoding::EncodableByteIter<'s, T>::next(&mut self) -> core::option::Option<Self::Item>
pub fn bitcoin_consensus_encoding::Encoder2<A, B>::advance(&mut self) -> bool
pub fn bitcoin_consensus_encoding::Encoder2<A, B>::current_chunk(&self) -> &[u8]
pub fn bitcoin_consensus_encoding::Encoder3<A, B, C>::advance(&mut self) -> bool
@@ -298,6 +308,7 @@ pub struct bitcoin_consensus_encoding::Decoder2<A, B> where A: bitcoin_consensus
pub struct bitcoin_consensus_encoding::Decoder3<A, B, C> where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder
pub struct bitcoin_consensus_encoding::Decoder4<A, B, C, D> where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder
pub struct bitcoin_consensus_encoding::Decoder6<A, B, C, D, E, F> where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder, E: bitcoin_consensus_encoding::Decoder, F: bitcoin_consensus_encoding::Decoder
+pub struct bitcoin_consensus_encoding::EncodableByteIter<'s, T: bitcoin_consensus_encoding::Encodable + 's>
pub struct bitcoin_consensus_encoding::Encoder2<A, B>
pub struct bitcoin_consensus_encoding::Encoder3<A, B, C>
pub struct bitcoin_consensus_encoding::Encoder4<A, B, C, D>
@@ -324,3 +335,4 @@ pub type bitcoin_consensus_encoding::Decoder6<A, B, C, D, E, F>::Output = (<A as
pub type bitcoin_consensus_encoding::Decoder::Error
pub type bitcoin_consensus_encoding::Decoder::Output
pub type bitcoin_consensus_encoding::Encodable::Encoder<'s> where Self: 's: bitcoin_consensus_encoding::Encoder
+pub type bitcoin_consensus_encoding::EncodableByteIter<'s, T>::Item = u8
diff --git a/consensus_encoding/src/encode/encoders.rs b/consensus_encoding/src/encode/encoders.rs
index 0aac982a..dbbb2174 100644
--- a/consensus_encoding/src/encode/encoders.rs
+++ b/consensus_encoding/src/encode/encoders.rs
@@ -592,4 +592,20 @@ mod tests {
assert!(!e.advance());
assert!(e.current_chunk().is_empty());
}
+
+ #[test]
+ fn iter_encoder() {
+ let test_array = TestArray([1u8, 2, 3, 4]);
+ let mut iter = crate::EncodableByteIter::new(&test_array);
+ let mut byte = iter.next().unwrap();
+ assert_eq!(byte, 1u8);
+ byte = iter.next().unwrap();
+ assert_eq!(byte, 2u8);
+ byte = iter.next().unwrap();
+ assert_eq!(byte, 3u8);
+ byte = iter.next().unwrap();
+ assert_eq!(byte, 4u8);
+ let none = iter.next();
+ assert_eq!(none, None);
+ }
}
diff --git a/consensus_encoding/src/encode/mod.rs b/consensus_encoding/src/encode/mod.rs
index fb3518de..aef04e20 100644
--- a/consensus_encoding/src/encode/mod.rs
+++ b/consensus_encoding/src/encode/mod.rs
@@ -64,6 +64,35 @@ macro_rules! encoder_newtype{
}
}
+/// Yields bytes from any [`Encodable`] instance.
+pub struct EncodableByteIter<'s, T: Encodable + 's> {
+ enc: T::Encoder<'s>,
+ position: usize,
+}
+
+impl<'s, T: Encodable + 's> EncodableByteIter<'s, T> {
+ /// Constructs a new byte iterator around a provided encodable.
+ pub fn new(encodable: &'s T) -> Self {
+ Self { enc: encodable.encoder(), position: 0 }
+ }
+}
+
+impl<'s, T: Encodable + 's> Iterator for EncodableByteIter<'s, T> {
+ type Item = u8;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ loop {
+ if let Some(b) = self.enc.current_chunk().get(self.position) {
+ self.position += 1;
+ return Some(*b);
+ } else if !self.enc.advance() {
+ return None;
+ }
+ self.position = 0;
+ }
+ }
+}
+
/// Encodes an object into a vector.
#[cfg(feature = "alloc")]
pub fn encode_to_vec<T>(object: &T) -> Vec<u8>
diff --git a/consensus_encoding/src/lib.rs b/consensus_encoding/src/lib.rs
index 12ee4a4f..965636a8 100644
--- a/consensus_encoding/src/lib.rs
+++ b/consensus_encoding/src/lib.rs
@@ -42,4 +42,4 @@ pub use self::encode::encoders::{
ArrayEncoder, BytesEncoder, CompactSizeEncoder, Encoder2, Encoder3, Encoder4, Encoder6,
SliceEncoder,
};
-pub use self::encode::{Encodable, Encoder};
+pub use self::encode::{Encodable, Encoder, EncodableByteIter};
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.