@@ -143,28 +143,37 @@ fn tagged_branch_hash_from_engine(
143143
144144/// [`Iterator`] over a sequence of bytes yielding [`TlvRecord`]s. The input is assumed to be a
145145/// well-formed TLV stream.
146- struct TlvStream < ' a > {
146+ pub ( super ) struct TlvStream < ' a > {
147147 data : io:: Cursor < & ' a [ u8 ] > ,
148148}
149149
150150impl < ' a > TlvStream < ' a > {
151- fn new ( data : & ' a [ u8 ] ) -> Self {
151+ pub fn new ( data : & ' a [ u8 ] ) -> Self {
152152 Self {
153153 data : io:: Cursor :: new ( data) ,
154154 }
155155 }
156156
157+ pub fn range < T > ( self , types : T ) -> impl core:: iter:: Iterator < Item = TlvRecord < ' a > >
158+ where
159+ T : core:: ops:: RangeBounds < u64 > + Clone ,
160+ {
161+ let take_range = types. clone ( ) ;
162+ self . skip_while ( move |record| !types. contains ( & record. r#type ) )
163+ . take_while ( move |record| take_range. contains ( & record. r#type ) )
164+ }
165+
157166 fn skip_signatures ( self ) -> core:: iter:: Filter < TlvStream < ' a > , fn ( & TlvRecord ) -> bool > {
158167 self . filter ( |record| !SIGNATURE_TYPES . contains ( & record. r#type ) )
159168 }
160169}
161170
162171/// A slice into a [`TlvStream`] for a record.
163- struct TlvRecord < ' a > {
164- r#type : u64 ,
172+ pub ( super ) struct TlvRecord < ' a > {
173+ pub ( super ) r#type : u64 ,
165174 type_bytes : & ' a [ u8 ] ,
166175 // The entire TLV record.
167- record_bytes : & ' a [ u8 ] ,
176+ pub ( super ) record_bytes : & ' a [ u8 ] ,
168177}
169178
170179impl < ' a > Iterator for TlvStream < ' a > {
@@ -212,7 +221,7 @@ impl<'a> Writeable for WithoutSignatures<'a> {
212221
213222#[ cfg( test) ]
214223mod tests {
215- use super :: { TlvStream , WithoutSignatures } ;
224+ use super :: { SIGNATURE_TYPES , TlvStream , WithoutSignatures } ;
216225
217226 use bitcoin:: hashes:: { Hash , sha256} ;
218227 use bitcoin:: secp256k1:: { KeyPair , Secp256k1 , SecretKey } ;
@@ -302,6 +311,38 @@ mod tests {
302311 ) ;
303312 }
304313
314+ #[ test]
315+ fn iterates_over_tlv_stream_range ( ) {
316+ let secp_ctx = Secp256k1 :: new ( ) ;
317+ let recipient_pubkey = {
318+ let secret_key = SecretKey :: from_slice ( & [ 41 ; 32 ] ) . unwrap ( ) ;
319+ KeyPair :: from_secret_key ( & secp_ctx, & secret_key) . public_key ( )
320+ } ;
321+ let payer_keys = {
322+ let secret_key = SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ;
323+ KeyPair :: from_secret_key ( & secp_ctx, & secret_key)
324+ } ;
325+
326+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey)
327+ . amount_msats ( 100 )
328+ . build_unchecked ( )
329+ . request_invoice ( vec ! [ 0 ; 8 ] , payer_keys. public_key ( ) ) . unwrap ( )
330+ . build_unchecked ( )
331+ . sign :: < _ , Infallible > ( |digest| Ok ( secp_ctx. sign_schnorr_no_aux_rand ( digest, & payer_keys) ) )
332+ . unwrap ( ) ;
333+
334+ let tlv_stream = TlvStream :: new ( & invoice_request. bytes ) . range ( 0 ..1 )
335+ . chain ( TlvStream :: new ( & invoice_request. bytes ) . range ( 1 ..80 ) )
336+ . chain ( TlvStream :: new ( & invoice_request. bytes ) . range ( 80 ..160 ) )
337+ . chain ( TlvStream :: new ( & invoice_request. bytes ) . range ( 160 ..240 ) )
338+ . chain ( TlvStream :: new ( & invoice_request. bytes ) . range ( SIGNATURE_TYPES ) )
339+ . map ( |r| r. record_bytes . to_vec ( ) )
340+ . flatten ( )
341+ . collect :: < Vec < u8 > > ( ) ;
342+
343+ assert_eq ! ( tlv_stream, invoice_request. bytes) ;
344+ }
345+
305346 impl AsRef < [ u8 ] > for InvoiceRequest {
306347 fn as_ref ( & self ) -> & [ u8 ] {
307348 & self . bytes
0 commit comments