Skip to content

Commit 596f1f7

Browse files
committed
Add encode::ByteIter
Add an iterator adapter that is identical to `encode::CharIter` but yields `u8` byte values instead. This makes encoding cleaner because users do not need to cast `char`s to `u8`.
1 parent ac74415 commit 596f1f7

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

src/primitives/encode.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ where
113113
CharIter::new(self.hrp, witver_iter)
114114
}
115115

116+
/// Returns an iterator that yields the bech32 encoded address as field ASCII characters, as
117+
/// byte values.
118+
#[inline]
119+
pub fn bytes(self) -> ByteIter<'hrp, I, Ck> {
120+
let char_iter = self.chars();
121+
ByteIter::new(char_iter)
122+
}
123+
116124
/// Returns an iterator that yields the field elements that go into the checksum, as well as the checksum at the end.
117125
///
118126
/// Each field element yielded has been input into the checksum algorithm (including the HRP as it is fed into the algorithm).
@@ -237,6 +245,43 @@ where
237245
}
238246
}
239247

248+
/// Iterator adaptor which takes a stream of ASCII field elements (an encoded string) and yields a stream of bytes.
249+
///
250+
/// This is equivalent to using the `CharsIter` and the casting each character to a byte. Doing
251+
/// so is technically sound because we only yield ASCII characters but it makes for ugly code so
252+
/// we provide this iterator also.
253+
pub struct ByteIter<'hrp, I, Ck>
254+
where
255+
I: Iterator<Item = Fe32>,
256+
Ck: Checksum,
257+
{
258+
char_iter: CharIter<'hrp, I, Ck>,
259+
}
260+
261+
impl<'hrp, I, Ck> ByteIter<'hrp, I, Ck>
262+
where
263+
I: Iterator<Item = Fe32>,
264+
Ck: Checksum,
265+
{
266+
/// Adapts the `CharIter` iterator to yield bytes representing the bech32 encoding as ASCII bytes.
267+
#[inline]
268+
pub fn new(char_iter: CharIter<'hrp, I, Ck>) -> Self { Self { char_iter } }
269+
}
270+
271+
impl<'a, I, Ck> Iterator for ByteIter<'a, I, Ck>
272+
where
273+
I: Iterator<Item = Fe32>,
274+
Ck: Checksum,
275+
{
276+
type Item = u8;
277+
278+
#[inline]
279+
fn next(&mut self) -> Option<u8> { self.char_iter.next().map(|c| c as u8) }
280+
281+
#[inline]
282+
fn size_hint(&self) -> (usize, Option<usize>) { self.char_iter.size_hint() }
283+
}
284+
240285
/// Iterator adaptor for a checksummed iterator that inputs the HRP into the checksum algorithm
241286
/// before yielding the HRP as field elements followed by the data then checksum.
242287
pub struct Fe32Iter<'hrp, I, Ck>
@@ -344,4 +389,19 @@ mod tests {
344389
let checksummed_len = 2 + 1 + 1 + char_len + 6; // bc + SEP + Q + chars + checksum
345390
assert_eq!(iter.size_hint().0, checksummed_len);
346391
}
392+
393+
#[test]
394+
#[cfg(feature = "alloc")]
395+
fn hrpstring_iter_bytes() {
396+
let hrp = Hrp::parse_unchecked("bc");
397+
let fes = DATA.iter().copied().bytes_to_fes();
398+
let iter = fes.with_checksum::<Bech32>(&hrp).with_witness_version(Fe32::Q);
399+
400+
let chars = iter.clone().chars();
401+
let bytes = iter.bytes();
402+
403+
for (c, b) in chars.zip(bytes) {
404+
assert_eq!(c as u8, b)
405+
}
406+
}
347407
}

0 commit comments

Comments
 (0)