@@ -26,6 +26,14 @@ macro_rules! encode_tlv {
26
26
field. write( $stream) ?;
27
27
}
28
28
} ;
29
+ ( $stream: expr, $type: expr, $field: expr, ( tlv_record, $fieldty: ident$( <$gen: ident>) ?) ) => {
30
+ if let Some ( field) = $field {
31
+ let field: encoded_tlv_record_ref_type!( $fieldty$( <$gen>) ?) = From :: from( field) ;
32
+ BigSize ( $type) . write( $stream) ?;
33
+ BigSize ( field. serialized_length( ) as u64 ) . write( $stream) ?;
34
+ field. write( $stream) ?;
35
+ }
36
+ } ;
29
37
}
30
38
31
39
macro_rules! encode_tlv_stream {
@@ -121,6 +129,9 @@ macro_rules! check_tlv_order {
121
129
( $last_seen_type: expr, $typ: expr, $type: expr, $field: ident, ( option: $trait: ident $( , $read_arg: expr) ?) ) => { {
122
130
// no-op
123
131
} } ;
132
+ ( $last_seen_type: expr, $typ: expr, $type: expr, $field: ident, ( tlv_record, $fieldty: ident$( <$gen: ident>) ?) ) => { {
133
+ // no-op
134
+ } } ;
124
135
}
125
136
126
137
macro_rules! check_missing_tlv {
@@ -150,6 +161,9 @@ macro_rules! check_missing_tlv {
150
161
( $last_seen_type: expr, $type: expr, $field: ident, ( option: $trait: ident $( , $read_arg: expr) ?) ) => { {
151
162
// no-op
152
163
} } ;
164
+ ( $last_seen_type: expr, $type: expr, $field: ident, ( tlv_record, $fieldty: ident$( <$gen: ident>) ?) ) => { {
165
+ // no-op
166
+ } } ;
153
167
}
154
168
155
169
macro_rules! decode_tlv {
@@ -172,6 +186,13 @@ macro_rules! decode_tlv {
172
186
( $reader: expr, $field: ident, ( option: $trait: ident $( , $read_arg: expr) ?) ) => { {
173
187
$field = Some ( $trait:: read( & mut $reader $( , $read_arg) * ) ?) ;
174
188
} } ;
189
+ ( $reader: expr, $field: ident, ( tlv_record, $fieldty: ident$( <$gen: ident>) ?) ) => { {
190
+ $field = {
191
+ let field: encoded_tlv_record_type!( $fieldty$( <$gen>) ?) =
192
+ ser:: Readable :: read( & mut $reader) ?;
193
+ Some ( field. into( ) )
194
+ } ;
195
+ } } ;
175
196
}
176
197
177
198
macro_rules! decode_tlv_stream {
@@ -360,6 +381,9 @@ macro_rules! init_tlv_based_struct_field {
360
381
( $field: ident, vec_type) => {
361
382
$field. unwrap( )
362
383
} ;
384
+ ( $field: ident, tlv_record) => {
385
+ $field
386
+ } ;
363
387
}
364
388
365
389
macro_rules! init_tlv_field_var {
@@ -375,6 +399,9 @@ macro_rules! init_tlv_field_var {
375
399
( $field: ident, option) => {
376
400
let mut $field = None ;
377
401
} ;
402
+ ( $field: ident, tlv_record) => {
403
+ let mut $field = None ;
404
+ } ;
378
405
}
379
406
380
407
/// Implements Readable/Writeable for a struct storing it as a set of TLVs
@@ -427,6 +454,139 @@ macro_rules! impl_writeable_tlv_based {
427
454
}
428
455
}
429
456
457
+ /// Defines a struct for a TLV stream and a similar struct using references for non-primitive types,
458
+ /// implementing [`Readable`] for the former and [`Writeable`] for the latter. Useful as an
459
+ /// intermediary format when reading or writing a type encoded as a TLV stream. Note that each field
460
+ /// representing a TLV record has its type wrapped with an [`Option`].
461
+ ///
462
+ /// [`Readable`]: crate::util::ser::Readable
463
+ /// [`Writeable`]: crate::util::ser::Writeable
464
+ macro_rules! tlv_stream {
465
+ ( $name: ident, $nameref: ident, {
466
+ $( ( $type: expr, $field: ident : $fieldty: ident$( <$gen: ident>) ?) ) ,* $( , ) *
467
+ } ) => {
468
+ #[ derive( Debug ) ]
469
+ struct $name {
470
+ $(
471
+ $field: Option <$fieldty$( <$gen>) ?>,
472
+ ) *
473
+ }
474
+
475
+ pub ( crate ) struct $nameref<' a> {
476
+ $(
477
+ pub ( crate ) $field: Option <tlv_record_ref_type!( $fieldty$( <$gen>) ?) >,
478
+ ) *
479
+ }
480
+
481
+ impl <' a> :: util:: ser:: Writeable for $nameref<' a> {
482
+ fn write<W : :: util:: ser:: Writer >( & self , writer: & mut W ) -> Result <( ) , $crate:: io:: Error > {
483
+ encode_tlv_stream!( writer, {
484
+ $( ( $type, self . $field, ( tlv_record, $fieldty$( <$gen>) ?) ) ) ,*
485
+ } ) ;
486
+ Ok ( ( ) )
487
+ }
488
+ }
489
+
490
+ impl :: util:: ser:: Readable for $name {
491
+ fn read<R : $crate:: io:: Read >( reader: & mut R ) -> Result <Self , :: ln:: msgs:: DecodeError > {
492
+ $(
493
+ init_tlv_field_var!( $field, tlv_record) ;
494
+ ) *
495
+ decode_tlv_stream!( reader, {
496
+ $( ( $type, $field, ( tlv_record, $fieldty$( <$gen>) ?) ) ) ,*
497
+ } ) ;
498
+
499
+ Ok ( Self {
500
+ $(
501
+ $field: init_tlv_based_struct_field!( $field, tlv_record)
502
+ ) ,*
503
+ } )
504
+ }
505
+ }
506
+ }
507
+ }
508
+
509
+ macro_rules! tlv_record_ref_type {
510
+ ( u8 ) => {
511
+ u8
512
+ } ;
513
+ ( u16 ) => {
514
+ u16
515
+ } ;
516
+ ( u32 ) => {
517
+ u32
518
+ } ;
519
+ ( u64 ) => {
520
+ u64
521
+ } ;
522
+ ( char ) => {
523
+ char
524
+ } ;
525
+ ( String ) => {
526
+ & ' a crate :: prelude:: String
527
+ } ;
528
+ ( Vec <$type: ty>) => {
529
+ & ' a crate :: prelude:: Vec <$type>
530
+ } ;
531
+ ( $type: ident$( <$gen: ident>) ?) => {
532
+ & ' a $type$( <$gen>) ?
533
+ } ;
534
+ }
535
+
536
+ macro_rules! encoded_tlv_record_type {
537
+ ( u8 ) => {
538
+ u8
539
+ } ;
540
+ ( u16 ) => {
541
+ :: util:: ser:: HighZeroBytesDroppedBigSize <u16 >
542
+ } ;
543
+ ( u32 ) => {
544
+ :: util:: ser:: HighZeroBytesDroppedBigSize <u32 >
545
+ } ;
546
+ ( u64 ) => {
547
+ :: util:: ser:: HighZeroBytesDroppedBigSize <u64 >
548
+ } ;
549
+ ( char ) => {
550
+ char
551
+ } ;
552
+ ( String ) => {
553
+ :: util:: ser:: WithoutLength <crate :: prelude:: String >
554
+ } ;
555
+ ( Vec <$type: ty>) => {
556
+ :: util:: ser:: WithoutLength <crate :: prelude:: Vec <$type>>
557
+ } ;
558
+ ( $type: ident$( <$gen: ident>) ?) => {
559
+ $type$( <$gen>) ?
560
+ } ;
561
+ }
562
+
563
+ macro_rules! encoded_tlv_record_ref_type {
564
+ ( u8 ) => {
565
+ u8
566
+ } ;
567
+ ( u16 ) => {
568
+ :: util:: ser:: HighZeroBytesDroppedBigSize <u16 >
569
+ } ;
570
+ ( u32 ) => {
571
+ :: util:: ser:: HighZeroBytesDroppedBigSize <u32 >
572
+ } ;
573
+ ( u64 ) => {
574
+ :: util:: ser:: HighZeroBytesDroppedBigSize <u64 >
575
+ } ;
576
+ ( char ) => {
577
+ char
578
+ } ;
579
+ ( String ) => {
580
+ :: util:: ser:: WithoutLength <& crate :: prelude:: String >
581
+ } ;
582
+ ( Vec <$type: ty>) => {
583
+ :: util:: ser:: WithoutLength <& crate :: prelude:: Vec <$type>>
584
+ } ;
585
+ ( $type: ident$( <$gen: ident>) ?) => {
586
+ & $type$( <$gen>) ?
587
+ } ;
588
+ }
589
+
430
590
macro_rules! _impl_writeable_tlv_based_enum_common {
431
591
( $st: ident, $( ( $variant_id: expr, $variant_name: ident) =>
432
592
{ $( ( $type: expr, $field: ident, $fieldty: tt) ) ,* $( , ) * }
0 commit comments