@@ -143,28 +143,37 @@ fn tagged_branch_hash_from_engine(
143
143
144
144
/// [`Iterator`] over a sequence of bytes yielding [`TlvRecord`]s. The input is assumed to be a
145
145
/// well-formed TLV stream.
146
- struct TlvStream < ' a > {
146
+ pub ( super ) struct TlvStream < ' a > {
147
147
data : io:: Cursor < & ' a [ u8 ] > ,
148
148
}
149
149
150
150
impl < ' a > TlvStream < ' a > {
151
- fn new ( data : & ' a [ u8 ] ) -> Self {
151
+ pub fn new ( data : & ' a [ u8 ] ) -> Self {
152
152
Self {
153
153
data : io:: Cursor :: new ( data) ,
154
154
}
155
155
}
156
156
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
+
157
166
fn skip_signatures ( self ) -> core:: iter:: Filter < TlvStream < ' a > , fn ( & TlvRecord ) -> bool > {
158
167
self . filter ( |record| !SIGNATURE_TYPES . contains ( & record. r#type ) )
159
168
}
160
169
}
161
170
162
171
/// 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 ,
165
174
type_bytes : & ' a [ u8 ] ,
166
175
// The entire TLV record.
167
- record_bytes : & ' a [ u8 ] ,
176
+ pub ( super ) record_bytes : & ' a [ u8 ] ,
168
177
}
169
178
170
179
impl < ' a > Iterator for TlvStream < ' a > {
@@ -212,7 +221,7 @@ impl<'a> Writeable for WithoutSignatures<'a> {
212
221
213
222
#[ cfg( test) ]
214
223
mod tests {
215
- use super :: { TlvStream , WithoutSignatures } ;
224
+ use super :: { SIGNATURE_TYPES , TlvStream , WithoutSignatures } ;
216
225
217
226
use bitcoin:: hashes:: { Hash , sha256} ;
218
227
use bitcoin:: secp256k1:: { KeyPair , Secp256k1 , SecretKey } ;
@@ -302,6 +311,38 @@ mod tests {
302
311
) ;
303
312
}
304
313
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
+
305
346
impl AsRef < [ u8 ] > for InvoiceRequest {
306
347
fn as_ref ( & self ) -> & [ u8 ] {
307
348
& self . bytes
0 commit comments