@@ -325,26 +325,26 @@ macro_rules! read_tlv_fields {
325325// `Self { ,,vecfield: vecfield }` which is obviously incorrect. Instead, we have to match here to
326326// detect at least one empty field set and skip the potentially-extra comma.
327327macro_rules! _init_tlv_based_struct {
328- ( { } , { $( $field: ident) ,* } , { $( $vecfield: ident) ,* } ) => {
329- Ok ( Self {
328+ ( $ ( $type : ident ) :: * , { } , { $( $field: ident) ,* } , { $( $vecfield: ident) ,* } ) => {
329+ Ok ( $ ( $type ) :: * {
330330 $( $field) ,* ,
331331 $( $vecfield: $vecfield. unwrap( ) . 0 ) ,*
332332 } )
333333 } ;
334- ( { $( $reqfield: ident) ,* } , { } , { $( $vecfield: ident) ,* } ) => {
335- Ok ( Self {
334+ ( $ ( $type : ident ) :: * , { $( $reqfield: ident) ,* } , { } , { $( $vecfield: ident) ,* } ) => {
335+ Ok ( $ ( $type ) :: * {
336336 $( $reqfield: $reqfield. 0 . unwrap( ) ) ,* ,
337337 $( $vecfield: $vecfield. unwrap( ) . 0 ) ,*
338338 } )
339339 } ;
340- ( { $( $reqfield: ident) ,* } , { $( $field: ident) ,* } , { } ) => {
341- Ok ( Self {
340+ ( $ ( $type : ident ) :: * , { $( $reqfield: ident) ,* } , { $( $field: ident) ,* } , { } ) => {
341+ Ok ( $ ( $type ) :: * {
342342 $( $reqfield: $reqfield. 0 . unwrap( ) ) ,* ,
343343 $( $field) ,*
344344 } )
345345 } ;
346- ( { $( $reqfield: ident) ,* } , { $( $field: ident) ,* } , { $( $vecfield: ident) ,* } ) => {
347- Ok ( Self {
346+ ( $ ( $type : ident ) :: * , { $( $reqfield: ident) ,* } , { $( $field: ident) ,* } , { $( $vecfield: ident) ,* } ) => {
347+ Ok ( $ ( $type ) :: * {
348348 $( $reqfield: $reqfield. 0 . unwrap( ) ) ,* ,
349349 $( $field) ,* ,
350350 $( $vecfield: $vecfield. unwrap( ) . 0 ) ,*
@@ -433,7 +433,88 @@ macro_rules! impl_writeable_tlv_based {
433433 } , {
434434 $( ( $vectype, $vecfield) ) ,*
435435 } ) ;
436- _init_tlv_based_struct!( { $( $reqfield) ,* } , { $( $field) ,* } , { $( $vecfield) ,* } )
436+ _init_tlv_based_struct!( $st, { $( $reqfield) ,* } , { $( $field) ,* } , { $( $vecfield) ,* } )
437+ }
438+ }
439+ }
440+ }
441+
442+ /// Implement Readable and Writeable for an enum, with struct variants stored as TLVs and tuple
443+ /// variants stored directly.
444+ /// The format is, for example
445+ /// impl_writeable_tlv_based_enum!(EnumName,
446+ /// (0, StructVariantA) => {(0, variant_field)}, {(1, variant_optional_field)}, {},
447+ /// (1, StructVariantB) => {(0, variant_field_a), (1, variant_field_b)}, {}, {(2, variant_vec_field)};
448+ /// (2, TupleVariantA), (3, TupleVariantB),
449+ /// );
450+ /// The type is written as a single byte, followed by any variant data.
451+ /// Attempts to read an unknown type byte result in DecodeError::UnknownRequiredFeature.
452+ macro_rules! impl_writeable_tlv_based_enum {
453+ ( $st: ident, $( ( $variant_id: expr, $variant_name: ident) =>
454+ { $( ( $reqtype: expr, $reqfield: ident) ) ,* $( , ) * } ,
455+ { $( ( $type: expr, $field: ident) ) ,* $( , ) * } ,
456+ { $( ( $vectype: expr, $vecfield: ident) ) ,* $( , ) * }
457+ ) ,* $( , ) * ;
458+ $( ( $tuple_variant_id: expr, $tuple_variant_name: ident) ) ,* $( , ) * ) => {
459+ impl :: util:: ser:: Writeable for $st {
460+ fn write<W : :: util:: ser:: Writer >( & self , writer: & mut W ) -> Result <( ) , :: std:: io:: Error > {
461+ match self {
462+ $( $st:: $variant_name { $( ref $reqfield) ,* $( ref $field) ,* , $( ref $vecfield) ,* } => {
463+ let id: u8 = $variant_id;
464+ id. write( writer) ?;
465+ _write_tlv_fields!( writer, {
466+ $( ( $reqtype, $reqfield) ) ,*
467+ } , {
468+ $( ( $type, $field) ) ,*
469+ } , {
470+ $( ( $vectype, Some ( :: util:: ser:: VecWriteWrapper ( & $vecfield) ) ) ) ,*
471+ } ) ;
472+ } ) ,*
473+ $( $st:: $tuple_variant_name ( ref field) => {
474+ let id: u8 = $tuple_variant_id;
475+ id. write( writer) ?;
476+ field. write( writer) ?;
477+ } ) ,*
478+ }
479+ Ok ( ( ) )
480+ }
481+ }
482+
483+ impl :: util:: ser:: Readable for $st {
484+ fn read<R : :: std:: io:: Read >( reader: & mut R ) -> Result <Self , :: ln:: msgs:: DecodeError > {
485+ let id: u8 = :: util:: ser:: Readable :: read( reader) ?;
486+ match id {
487+ $( $variant_id => {
488+ // Because read_tlv_fields creates a labeled loop, we cannot call it twice
489+ // in the same function body. Instead, we define a closure and call it.
490+ let f = || {
491+ $(
492+ let mut $reqfield = :: util:: ser:: OptionDeserWrapper ( None ) ;
493+ ) *
494+ $(
495+ let mut $field = None ;
496+ ) *
497+ $(
498+ let mut $vecfield = Some ( :: util:: ser:: VecReadWrapper ( Vec :: new( ) ) ) ;
499+ ) *
500+ _read_tlv_fields!( reader, {
501+ $( ( $reqtype, $reqfield) ) ,*
502+ } , {
503+ $( ( $type, $field) ) ,*
504+ } , {
505+ $( ( $vectype, $vecfield) ) ,*
506+ } ) ;
507+ _init_tlv_based_struct!( $st:: $variant_name, { $( $reqfield) ,* } , { $( $field) ,* } , { $( $vecfield) ,* } )
508+ } ;
509+ f( )
510+ } ) ,*
511+ $( $tuple_variant_id => {
512+ Ok ( $st:: $tuple_variant_name( Readable :: read( reader) ?) )
513+ } ) ,*
514+ _ => {
515+ Err ( DecodeError :: UnknownRequiredFeature ) ?
516+ } ,
517+ }
437518 }
438519 }
439520 }
0 commit comments