@@ -26,6 +26,12 @@ macro_rules! encode_tlv {
2626 field. write( $stream) ?;
2727 }
2828 } ;
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+ } ;
2935}
3036
3137macro_rules! encode_tlv_stream {
@@ -121,6 +127,9 @@ macro_rules! check_tlv_order {
121127 ( $last_seen_type: expr, $typ: expr, $type: expr, $field: ident, ( option: $trait: ident $( , $read_arg: expr) ?) ) => { {
122128 // no-op
123129 } } ;
130+ ( $last_seen_type: expr, $typ: expr, $type: expr, $field: ident, ( option, encoding: $encoding: tt) ) => { {
131+ // no-op
132+ } } ;
124133}
125134
126135macro_rules! check_missing_tlv {
@@ -150,6 +159,9 @@ macro_rules! check_missing_tlv {
150159 ( $last_seen_type: expr, $type: expr, $field: ident, ( option: $trait: ident $( , $read_arg: expr) ?) ) => { {
151160 // no-op
152161 } } ;
162+ ( $last_seen_type: expr, $type: expr, $field: ident, ( option, encoding: $encoding: tt) ) => { {
163+ // no-op
164+ } } ;
153165}
154166
155167macro_rules! decode_tlv {
@@ -172,6 +184,15 @@ macro_rules! decode_tlv {
172184 ( $reader: expr, $field: ident, ( option: $trait: ident $( , $read_arg: expr) ?) ) => { {
173185 $field = Some ( $trait:: read( & mut $reader $( , $read_arg) * ) ?) ;
174186 } } ;
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+ } } ;
175196}
176197
177198// `$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 {
441462 }
442463}
443464
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+
444534macro_rules! _impl_writeable_tlv_based_enum_common {
445535 ( $st: ident, $( ( $variant_id: expr, $variant_name: ident) =>
446536 { $( ( $type: expr, $field: ident, $fieldty: tt) ) ,* $( , ) * }
0 commit comments