@@ -325,26 +325,26 @@ macro_rules! read_tlv_fields {
325
325
// `Self { ,,vecfield: vecfield }` which is obviously incorrect. Instead, we have to match here to
326
326
// detect at least one empty field set and skip the potentially-extra comma.
327
327
macro_rules! _init_tlv_based_struct {
328
- ( { } , { $( $field: ident) ,* } , { $( $vecfield: ident) ,* } ) => {
329
- Ok ( Self {
328
+ ( $ ( $type : ident ) :: * , { } , { $( $field: ident) ,* } , { $( $vecfield: ident) ,* } ) => {
329
+ Ok ( $ ( $type ) :: * {
330
330
$( $field) ,* ,
331
331
$( $vecfield: $vecfield. unwrap( ) . 0 ) ,*
332
332
} )
333
333
} ;
334
- ( { $( $reqfield: ident) ,* } , { } , { $( $vecfield: ident) ,* } ) => {
335
- Ok ( Self {
334
+ ( $ ( $type : ident ) :: * , { $( $reqfield: ident) ,* } , { } , { $( $vecfield: ident) ,* } ) => {
335
+ Ok ( $ ( $type ) :: * {
336
336
$( $reqfield: $reqfield. 0 . unwrap( ) ) ,* ,
337
337
$( $vecfield: $vecfield. unwrap( ) . 0 ) ,*
338
338
} )
339
339
} ;
340
- ( { $( $reqfield: ident) ,* } , { $( $field: ident) ,* } , { } ) => {
341
- Ok ( Self {
340
+ ( $ ( $type : ident ) :: * , { $( $reqfield: ident) ,* } , { $( $field: ident) ,* } , { } ) => {
341
+ Ok ( $ ( $type ) :: * {
342
342
$( $reqfield: $reqfield. 0 . unwrap( ) ) ,* ,
343
343
$( $field) ,*
344
344
} )
345
345
} ;
346
- ( { $( $reqfield: ident) ,* } , { $( $field: ident) ,* } , { $( $vecfield: ident) ,* } ) => {
347
- Ok ( Self {
346
+ ( $ ( $type : ident ) :: * , { $( $reqfield: ident) ,* } , { $( $field: ident) ,* } , { $( $vecfield: ident) ,* } ) => {
347
+ Ok ( $ ( $type ) :: * {
348
348
$( $reqfield: $reqfield. 0 . unwrap( ) ) ,* ,
349
349
$( $field) ,* ,
350
350
$( $vecfield: $vecfield. unwrap( ) . 0 ) ,*
@@ -433,7 +433,88 @@ macro_rules! impl_writeable_tlv_based {
433
433
} , {
434
434
$( ( $vectype, $vecfield) ) ,*
435
435
} ) ;
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
+ }
437
518
}
438
519
}
439
520
}
0 commit comments