1- use alloc:: boxed:: Box ;
21use core:: fmt;
32use core:: fmt:: { Display , Formatter } ;
43use core:: { array, iter} ;
@@ -13,14 +12,28 @@ use super::{
1312 SignedRawBolt11Invoice , TaggedField ,
1413} ;
1514
15+ macro_rules! define_iterator_enum {
16+ ( $name: ident, $( $n: ident) ,* ) => {
17+ enum $name<$( $n: Iterator <Item = Fe32 >, ) * > {
18+ $( $n( $n) , ) *
19+ }
20+ impl <$( $n: Iterator <Item = Fe32 >, ) * > Iterator for $name<$( $n, ) * > {
21+ type Item = Fe32 ;
22+ fn next( & mut self ) -> Option <Fe32 > {
23+ match self {
24+ $( Self :: $n( iter) => iter. next( ) , ) *
25+ }
26+ }
27+ }
28+ }
29+ }
30+
1631/// Objects that can be encoded to base32 (bech32).
1732///
18- /// Private to this crate to avoid polluting the API.
33+ /// Private to this crate (except in fuzzing) to avoid polluting the API.
1934pub trait Base32Iterable {
20- /// apoelstra: In future we want to replace this Box<dyn Iterator> with an explicit
21- /// associated type, to avoid the allocation. But we cannot do this until
22- /// Rust 1.65 and GATs since the iterator may contain a reference to self.
23- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > ;
35+ /// Serialize this object, returning an iterator over bech32 field elements.
36+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s ;
2437}
2538
2639/// Interface to calculate the length of the base32 representation before actually serializing
@@ -32,7 +45,7 @@ pub(crate) trait Base32Len: Base32Iterable {
3245// Base32Iterable & Base32Len implementations are here, because the traits are in this module.
3346
3447impl < const N : usize > Base32Iterable for [ u8 ; N ] {
35- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
48+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
3649 self [ ..] . fe_iter ( )
3750 }
3851}
@@ -45,8 +58,8 @@ impl<const N: usize> Base32Len for [u8; N] {
4558}
4659
4760impl Base32Iterable for [ u8 ] {
48- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
49- Box :: new ( self . iter ( ) . copied ( ) . bytes_to_fes ( ) )
61+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
62+ self . iter ( ) . copied ( ) . bytes_to_fes ( )
5063 }
5164}
5265
@@ -58,8 +71,8 @@ impl Base32Len for [u8] {
5871}
5972
6073impl Base32Iterable for Vec < u8 > {
61- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
62- Box :: new ( self . iter ( ) . copied ( ) . bytes_to_fes ( ) )
74+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
75+ self . iter ( ) . copied ( ) . bytes_to_fes ( )
6376 }
6477}
6578
@@ -71,8 +84,8 @@ impl Base32Len for Vec<u8> {
7184}
7285
7386impl Base32Iterable for PaymentSecret {
74- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
75- Box :: new ( self . 0 [ ..] . fe_iter ( ) )
87+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
88+ self . 0 [ ..] . fe_iter ( )
7689 }
7790}
7891
@@ -88,7 +101,7 @@ impl Base32Iterable for Bolt11InvoiceFeatures {
88101 /// starting from the rightmost bit,
89102 /// and taking the resulting 5-bit values in reverse (left-to-right),
90103 /// with the leading 0's skipped.
91- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
104+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
92105 // Fe32 conversion cannot be used, because this packs from right, right-to-left
93106 let mut input_iter = self . le_flags ( ) . iter ( ) ;
94107 // Carry bits, 0..7 bits
@@ -126,7 +139,7 @@ impl Base32Iterable for Bolt11InvoiceFeatures {
126139 output. push ( Fe32 :: try_from ( next_out8 & 31u8 ) . expect ( "<32" ) )
127140 }
128141 // Take result in reverse order, and skip leading 0s
129- Box :: new ( output. into_iter ( ) . rev ( ) . skip_while ( |e| * e == Fe32 :: Q ) )
142+ output. into_iter ( ) . rev ( ) . skip_while ( |e| * e == Fe32 :: Q )
130143 }
131144}
132145
@@ -241,36 +254,35 @@ fn encoded_int_be_base32_size(int: u64) -> usize {
241254}
242255
243256impl Base32Iterable for RawDataPart {
244- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
257+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
245258 let ts_iter = self . timestamp . fe_iter ( ) ;
246259 let fields_iter = self . tagged_fields . iter ( ) . map ( RawTaggedField :: fe_iter) . flatten ( ) ;
247- Box :: new ( ts_iter. chain ( fields_iter) )
260+ ts_iter. chain ( fields_iter)
248261 }
249262}
250263
251264impl Base32Iterable for PositiveTimestamp {
252- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
265+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
253266 let fes = encode_int_be_base32 ( self . as_unix_timestamp ( ) ) ;
254267 debug_assert ! ( fes. len( ) <= 7 , "Invalid timestamp length" ) ;
255268 let to_pad = 7 - fes. len ( ) ;
256- Box :: new ( core:: iter:: repeat ( Fe32 :: Q ) . take ( to_pad) . chain ( fes) )
269+ core:: iter:: repeat ( Fe32 :: Q ) . take ( to_pad) . chain ( fes)
257270 }
258271}
259272
260273impl Base32Iterable for RawTaggedField {
261- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
262- // Annoyingly, when we move to explicit types, we will need an
263- // explicit enum holding the two iterator variants.
274+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
275+ define_iterator_enum ! ( TwoIters , A , B ) ;
264276 match * self {
265- RawTaggedField :: UnknownSemantics ( ref content) => Box :: new ( content. iter ( ) . copied ( ) ) ,
266- RawTaggedField :: KnownSemantics ( ref tagged_field) => tagged_field. fe_iter ( ) ,
277+ RawTaggedField :: UnknownSemantics ( ref content) => TwoIters :: A ( content. iter ( ) . copied ( ) ) ,
278+ RawTaggedField :: KnownSemantics ( ref tagged_field) => TwoIters :: B ( tagged_field. fe_iter ( ) ) ,
267279 }
268280 }
269281}
270282
271283impl Base32Iterable for Sha256 {
272- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
273- Box :: new ( self . 0 [ ..] . fe_iter ( ) )
284+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
285+ self . 0 [ ..] . fe_iter ( )
274286 }
275287}
276288
@@ -281,8 +293,8 @@ impl Base32Len for Sha256 {
281293}
282294
283295impl Base32Iterable for Description {
284- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
285- Box :: new ( self . 0 . 0 . as_bytes ( ) . fe_iter ( ) )
296+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
297+ self . 0 . 0 . as_bytes ( ) . fe_iter ( )
286298 }
287299}
288300
@@ -293,8 +305,8 @@ impl Base32Len for Description {
293305}
294306
295307impl Base32Iterable for PayeePubKey {
296- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
297- Box :: new ( self . serialize ( ) . into_iter ( ) . bytes_to_fes ( ) )
308+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
309+ self . serialize ( ) . into_iter ( ) . bytes_to_fes ( )
298310 }
299311}
300312
@@ -305,8 +317,8 @@ impl Base32Len for PayeePubKey {
305317}
306318
307319impl Base32Iterable for ExpiryTime {
308- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
309- Box :: new ( encode_int_be_base32 ( self . as_seconds ( ) ) )
320+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
321+ encode_int_be_base32 ( self . as_seconds ( ) )
310322 }
311323}
312324
@@ -317,8 +329,8 @@ impl Base32Len for ExpiryTime {
317329}
318330
319331impl Base32Iterable for MinFinalCltvExpiryDelta {
320- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
321- Box :: new ( encode_int_be_base32 ( self . 0 ) )
332+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
333+ encode_int_be_base32 ( self . 0 )
322334 }
323335}
324336
@@ -329,8 +341,8 @@ impl Base32Len for MinFinalCltvExpiryDelta {
329341}
330342
331343impl Base32Iterable for Fallback {
332- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
333- Box :: new ( match * self {
344+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
345+ match * self {
334346 Fallback :: SegWitProgram { version : v, program : ref p } => {
335347 let v = Fe32 :: try_from ( v. to_num ( ) ) . expect ( "valid version" ) ;
336348 core:: iter:: once ( v) . chain ( p[ ..] . fe_iter ( ) )
@@ -343,7 +355,7 @@ impl Base32Iterable for Fallback {
343355 // 18 'J'
344356 core:: iter:: once ( Fe32 :: J ) . chain ( hash[ ..] . fe_iter ( ) )
345357 } ,
346- } )
358+ }
347359 }
348360}
349361
@@ -371,7 +383,7 @@ type RouteHintHopIter = iter::Chain<
371383> ;
372384
373385impl Base32Iterable for PrivateRoute {
374- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
386+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
375387 fn serialize_to_iter ( hop : & RouteHintHop ) -> RouteHintHopIter {
376388 let i1 = hop. src_node_id . serialize ( ) . into_iter ( ) ;
377389 let i2 = u64:: to_be_bytes ( hop. short_channel_id ) . into_iter ( ) ;
@@ -381,7 +393,7 @@ impl Base32Iterable for PrivateRoute {
381393 i1. chain ( i2) . chain ( i3) . chain ( i4) . chain ( i5)
382394 }
383395
384- Box :: new ( self . 0 . 0 . iter ( ) . map ( serialize_to_iter) . flatten ( ) . bytes_to_fes ( ) )
396+ self . 0 . 0 . iter ( ) . map ( serialize_to_iter) . flatten ( ) . bytes_to_fes ( )
385397 }
386398}
387399
@@ -391,16 +403,11 @@ impl Base32Len for PrivateRoute {
391403 }
392404}
393405
394- // Shorthand type
395- type TaggedFieldIter < I > = core:: iter:: Chain < core:: array:: IntoIter < Fe32 , 3 > , I > ;
396-
397406impl Base32Iterable for TaggedField {
398- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
407+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
399408 /// Writes a tagged field: tag, length and data. `tag` should be in `0..32` otherwise the
400409 /// function will panic.
401- fn write_tagged_field < ' s , P > (
402- tag : u8 , payload : & ' s P ,
403- ) -> TaggedFieldIter < Box < dyn Iterator < Item = Fe32 > + ' s > >
410+ fn write_tagged_field < ' s , P > ( tag : u8 , payload : & ' s P ) -> impl Iterator < Item = Fe32 > + ' s
404411 where
405412 P : Base32Iterable + Base32Len + ?Sized ,
406413 {
@@ -416,54 +423,49 @@ impl Base32Iterable for TaggedField {
416423 . chain ( payload. fe_iter ( ) )
417424 }
418425
419- // we will also need a giant enum for this
420- Box :: new ( match * self {
426+ define_iterator_enum ! ( ManyIters , A , B , C , D , E , F , G , H , I , J , K ) ;
427+ match * self {
421428 TaggedField :: PaymentHash ( ref hash) => {
422- write_tagged_field ( constants:: TAG_PAYMENT_HASH , hash)
429+ ManyIters :: A ( write_tagged_field ( constants:: TAG_PAYMENT_HASH , hash) )
423430 } ,
424431 TaggedField :: Description ( ref description) => {
425- write_tagged_field ( constants:: TAG_DESCRIPTION , description)
432+ ManyIters :: B ( write_tagged_field ( constants:: TAG_DESCRIPTION , description) )
426433 } ,
427434 TaggedField :: PayeePubKey ( ref pub_key) => {
428- write_tagged_field ( constants:: TAG_PAYEE_PUB_KEY , pub_key)
435+ ManyIters :: C ( write_tagged_field ( constants:: TAG_PAYEE_PUB_KEY , pub_key) )
429436 } ,
430437 TaggedField :: DescriptionHash ( ref hash) => {
431- write_tagged_field ( constants:: TAG_DESCRIPTION_HASH , hash)
438+ ManyIters :: D ( write_tagged_field ( constants:: TAG_DESCRIPTION_HASH , hash) )
432439 } ,
433440 TaggedField :: ExpiryTime ( ref duration) => {
434- write_tagged_field ( constants:: TAG_EXPIRY_TIME , duration)
441+ ManyIters :: E ( write_tagged_field ( constants:: TAG_EXPIRY_TIME , duration) )
435442 } ,
436443 TaggedField :: MinFinalCltvExpiryDelta ( ref expiry) => {
437- write_tagged_field ( constants:: TAG_MIN_FINAL_CLTV_EXPIRY_DELTA , expiry)
444+ ManyIters :: F ( write_tagged_field ( constants:: TAG_MIN_FINAL_CLTV_EXPIRY_DELTA , expiry) )
438445 } ,
439446 TaggedField :: Fallback ( ref fallback_address) => {
440- write_tagged_field ( constants:: TAG_FALLBACK , fallback_address)
447+ ManyIters :: G ( write_tagged_field ( constants:: TAG_FALLBACK , fallback_address) )
441448 } ,
442449 TaggedField :: PrivateRoute ( ref route_hops) => {
443- write_tagged_field ( constants:: TAG_PRIVATE_ROUTE , route_hops)
450+ ManyIters :: H ( write_tagged_field ( constants:: TAG_PRIVATE_ROUTE , route_hops) )
444451 } ,
445452 TaggedField :: PaymentSecret ( ref payment_secret) => {
446- write_tagged_field ( constants:: TAG_PAYMENT_SECRET , payment_secret)
453+ ManyIters :: I ( write_tagged_field ( constants:: TAG_PAYMENT_SECRET , payment_secret) )
447454 } ,
448455 TaggedField :: PaymentMetadata ( ref payment_metadata) => {
449- write_tagged_field ( constants:: TAG_PAYMENT_METADATA , payment_metadata)
456+ ManyIters :: J ( write_tagged_field ( constants:: TAG_PAYMENT_METADATA , payment_metadata) )
450457 } ,
451458 TaggedField :: Features ( ref features) => {
452- write_tagged_field ( constants:: TAG_FEATURES , features)
459+ ManyIters :: K ( write_tagged_field ( constants:: TAG_FEATURES , features) )
453460 } ,
454- } )
461+ }
455462 }
456463}
457464
458465impl Base32Iterable for Bolt11InvoiceSignature {
459- fn fe_iter < ' s > ( & ' s self ) -> Box < dyn Iterator < Item = Fe32 > + ' s > {
466+ fn fe_iter < ' s > ( & ' s self ) -> impl Iterator < Item = Fe32 > + ' s {
460467 let ( recovery_id, signature) = self . 0 . serialize_compact ( ) ;
461- Box :: new (
462- signature
463- . into_iter ( )
464- . chain ( core:: iter:: once ( recovery_id. to_i32 ( ) as u8 ) )
465- . bytes_to_fes ( ) ,
466- )
468+ signature. into_iter ( ) . chain ( core:: iter:: once ( recovery_id. to_i32 ( ) as u8 ) ) . bytes_to_fes ( )
467469 }
468470}
469471
0 commit comments