@@ -26,6 +26,12 @@ macro_rules! encode_tlv {
26
26
field. write( $stream) ?;
27
27
}
28
28
} ;
29
+ ( $stream: expr, $type: expr, $field: expr, ( option, encoding: ( $fieldty: ty, $encoding: ident) ) ) => {
30
+ encode_tlv!( $stream, $type, $field. map( |f| $encoding( f) ) , option) ;
31
+ } ;
32
+ ( $stream: expr, $type: expr, $field: expr, ( option, encoding: $fieldty: ty) ) => {
33
+ encode_tlv!( $stream, $type, $field, option) ;
34
+ } ;
29
35
}
30
36
31
37
macro_rules! encode_tlv_stream {
@@ -121,6 +127,9 @@ macro_rules! check_tlv_order {
121
127
( $last_seen_type: expr, $typ: expr, $type: expr, $field: ident, ( option: $trait: ident $( , $read_arg: expr) ?) ) => { {
122
128
// no-op
123
129
} } ;
130
+ ( $last_seen_type: expr, $typ: expr, $type: expr, $field: ident, ( option, encoding: $encoding: tt) ) => { {
131
+ // no-op
132
+ } } ;
124
133
}
125
134
126
135
macro_rules! check_missing_tlv {
@@ -150,6 +159,9 @@ macro_rules! check_missing_tlv {
150
159
( $last_seen_type: expr, $type: expr, $field: ident, ( option: $trait: ident $( , $read_arg: expr) ?) ) => { {
151
160
// no-op
152
161
} } ;
162
+ ( $last_seen_type: expr, $type: expr, $field: ident, ( option, encoding: $encoding: tt) ) => { {
163
+ // no-op
164
+ } } ;
153
165
}
154
166
155
167
macro_rules! decode_tlv {
@@ -172,6 +184,15 @@ macro_rules! decode_tlv {
172
184
( $reader: expr, $field: ident, ( option: $trait: ident $( , $read_arg: expr) ?) ) => { {
173
185
$field = Some ( $trait:: read( & mut $reader $( , $read_arg) * ) ?) ;
174
186
} } ;
187
+ ( $reader: expr, $field: ident, ( option, encoding: ( $fieldty: ty, $encoding: ident) ) ) => { {
188
+ $field = {
189
+ let field: $encoding<$fieldty> = ser:: Readable :: read( & mut $reader) ?;
190
+ Some ( field. 0 )
191
+ } ;
192
+ } } ;
193
+ ( $reader: expr, $field: ident, ( option, encoding: $fieldty: ty) ) => { {
194
+ decode_tlv!( $reader, $field, option) ;
195
+ } } ;
175
196
}
176
197
177
198
// `$decode_custom_tlv` is a closure that may be optionally provided to handle custom message types.
@@ -441,6 +462,75 @@ macro_rules! impl_writeable_tlv_based {
441
462
}
442
463
}
443
464
465
+ /// Defines a struct for a TLV stream and a similar struct using references for non-primitive types,
466
+ /// implementing [`Readable`] for the former and [`Writeable`] for the latter. Useful as an
467
+ /// intermediary format when reading or writing a type encoded as a TLV stream. Note that each field
468
+ /// representing a TLV record has its type wrapped with an [`Option`]. A tuple consisting of a type
469
+ /// and a serialization wrapper may be given in place of a type when custom serialization is
470
+ /// required.
471
+ ///
472
+ /// [`Readable`]: crate::util::ser::Readable
473
+ /// [`Writeable`]: crate::util::ser::Writeable
474
+ macro_rules! tlv_stream {
475
+ ( $name: ident, $nameref: ident, {
476
+ $( ( $type: expr, $field: ident : $fieldty: tt) ) ,* $( , ) *
477
+ } ) => {
478
+ #[ derive( Debug ) ]
479
+ struct $name {
480
+ $(
481
+ $field: Option <tlv_record_type!( $fieldty) >,
482
+ ) *
483
+ }
484
+
485
+ pub ( crate ) struct $nameref<' a> {
486
+ $(
487
+ pub ( crate ) $field: Option <tlv_record_ref_type!( $fieldty) >,
488
+ ) *
489
+ }
490
+
491
+ impl <' a> $crate:: util:: ser:: Writeable for $nameref<' a> {
492
+ fn write<W : $crate:: util:: ser:: Writer >( & self , writer: & mut W ) -> Result <( ) , $crate:: io:: Error > {
493
+ encode_tlv_stream!( writer, {
494
+ $( ( $type, self . $field, ( option, encoding: $fieldty) ) ) ,*
495
+ } ) ;
496
+ Ok ( ( ) )
497
+ }
498
+ }
499
+
500
+ impl $crate:: util:: ser:: Readable for $name {
501
+ fn read<R : $crate:: io:: Read >( reader: & mut R ) -> Result <Self , $crate:: ln:: msgs:: DecodeError > {
502
+ $(
503
+ init_tlv_field_var!( $field, option) ;
504
+ ) *
505
+ decode_tlv_stream!( reader, {
506
+ $( ( $type, $field, ( option, encoding: $fieldty) ) ) ,*
507
+ } ) ;
508
+
509
+ Ok ( Self {
510
+ $(
511
+ $field: $field
512
+ ) ,*
513
+ } )
514
+ }
515
+ }
516
+ }
517
+ }
518
+
519
+ macro_rules! tlv_record_type {
520
+ ( ( $type: ty, $wrapper: ident) ) => { $type } ;
521
+ ( $type: ty) => { $type } ;
522
+ }
523
+
524
+ macro_rules! tlv_record_ref_type {
525
+ ( char ) => { char } ;
526
+ ( u8 ) => { u8 } ;
527
+ ( ( u16 , $wrapper: ident) ) => { u16 } ;
528
+ ( ( u32 , $wrapper: ident) ) => { u32 } ;
529
+ ( ( u64 , $wrapper: ident) ) => { u64 } ;
530
+ ( ( $type: ty, $wrapper: ident) ) => { & ' a $type } ;
531
+ ( $type: ty) => { & ' a $type } ;
532
+ }
533
+
444
534
macro_rules! _impl_writeable_tlv_based_enum_common {
445
535
( $st: ident, $( ( $variant_id: expr, $variant_name: ident) =>
446
536
{ $( ( $type: expr, $field: ident, $fieldty: tt) ) ,* $( , ) * }
0 commit comments