@@ -45,7 +45,7 @@ macro_rules! _encode_tlv {
4545 field. write( $stream) ?;
4646 }
4747 } ;
48- ( $stream: expr, $optional_type: expr, $optional_field: expr, ( legacy, $fieldty: ty, $write: expr) $( , $self: ident) ?) => { {
48+ ( $stream: expr, $optional_type: expr, $optional_field: expr, ( legacy, $fieldty: ty, $read : expr , $ write: expr) $( , $self: ident) ?) => { {
4949 let value: Option <_> = $write( $( $self) ?) ;
5050 #[ cfg( debug_assertions) ]
5151 {
@@ -63,6 +63,9 @@ macro_rules! _encode_tlv {
6363 }
6464 $crate:: _encode_tlv!( $stream, $optional_type, value, option) ;
6565 } } ;
66+ ( $stream: expr, $optional_type: expr, $optional_field: expr, ( custom, $fieldty: ty, $read: expr, $write: expr) $( , $self: ident) ?) => { {
67+ $crate:: _encode_tlv!( $stream, $optional_type, $optional_field, ( legacy, $fieldty, $read, $write) $( , $self) ?) ;
68+ } } ;
6669 ( $stream: expr, $type: expr, $field: expr, optional_vec $( , $self: ident) ?) => {
6770 if !$field. is_empty( ) {
6871 $crate:: _encode_tlv!( $stream, $type, $field, required_vec) ;
@@ -229,9 +232,12 @@ macro_rules! _get_varint_length_prefixed_tlv_length {
229232 $len. 0 += field_len;
230233 }
231234 } ;
232- ( $len: expr, $optional_type: expr, $optional_field: expr, ( legacy, $fieldty: ty, $write: expr) $( , $self: ident) ?) => {
235+ ( $len: expr, $optional_type: expr, $optional_field: expr, ( legacy, $fieldty: ty, $read : expr , $ write: expr) $( , $self: ident) ?) => {
233236 $crate:: _get_varint_length_prefixed_tlv_length!( $len, $optional_type, $write( $( $self) ?) , option) ;
234237 } ;
238+ ( $len: expr, $optional_type: expr, $optional_field: expr, ( custom, $fieldty: ty, $read: expr, $write: expr) $( , $self: ident) ?) => {
239+ $crate:: _get_varint_length_prefixed_tlv_length!( $len, $optional_type, $optional_field, ( legacy, $fieldty, $read, $write) $( , $self) ?) ;
240+ } ;
235241 ( $len: expr, $type: expr, $field: expr, optional_vec $( , $self: ident) ?) => {
236242 if !$field. is_empty( ) {
237243 $crate:: _get_varint_length_prefixed_tlv_length!( $len, $type, $field, required_vec) ;
@@ -314,9 +320,19 @@ macro_rules! _check_decoded_tlv_order {
314320 ( $last_seen_type: expr, $typ: expr, $type: expr, $field: ident, ( option, explicit_type: $fieldty: ty) ) => { {
315321 // no-op
316322 } } ;
317- ( $last_seen_type: expr, $typ: expr, $type: expr, $field: ident, ( legacy, $fieldty: ty, $write: expr) ) => { {
323+ ( $last_seen_type: expr, $typ: expr, $type: expr, $field: ident, ( legacy, $fieldty: ty, $read : expr , $ write: expr) ) => { {
318324 // no-op
319325 } } ;
326+ ( $last_seen_type: expr, $typ: expr, $type: expr, $field: ident, ( custom, $fieldty: ty, $read: expr, $write: expr) $( , $self: ident) ?) => { {
327+ // Note that $type may be 0 making the second comparison always false
328+ #[ allow( unused_comparisons) ]
329+ let invalid_order =
330+ ( $last_seen_type. is_none( ) || $last_seen_type. unwrap( ) < $type) && $typ. 0 > $type;
331+ if invalid_order {
332+ let read_result: Result <_, DecodeError > = $read( None ) ;
333+ $field = read_result?. into( ) ;
334+ }
335+ } } ;
320336 ( $last_seen_type: expr, $typ: expr, $type: expr, $field: ident, ( required, explicit_type: $fieldty: ty) ) => { {
321337 _check_decoded_tlv_order!( $last_seen_type, $typ, $type, $field, required) ;
322338 } } ;
@@ -382,8 +398,19 @@ macro_rules! _check_missing_tlv {
382398 ( $last_seen_type: expr, $type: expr, $field: ident, ( option, explicit_type: $fieldty: ty) ) => { {
383399 // no-op
384400 } } ;
385- ( $last_seen_type: expr, $type: expr, $field: ident, ( legacy, $fieldty: ty, $write: expr) ) => { {
386- // no-op
401+ ( $last_seen_type: expr, $type: expr, $field: ident, ( legacy, $fieldty: ty, $read: expr, $write: expr) ) => { {
402+ use $crate:: ln:: msgs:: DecodeError ;
403+ let read_result: Result <( ) , DecodeError > = $read( $field. as_ref( ) ) ;
404+ read_result?;
405+ } } ;
406+ ( $last_seen_type: expr, $type: expr, $field: ident, ( custom, $fieldty: ty, $read: expr, $write: expr) ) => { {
407+ // Note that $type may be 0 making the second comparison always false
408+ #[ allow( unused_comparisons) ]
409+ let missing_req_type = $last_seen_type. is_none( ) || $last_seen_type. unwrap( ) < $type;
410+ if missing_req_type {
411+ let read_result: Result <_, DecodeError > = $read( None ) ;
412+ $field = read_result?. into( ) ;
413+ }
387414 } } ;
388415 ( $last_seen_type: expr, $type: expr, $field: ident, ( required, explicit_type: $fieldty: ty) ) => { {
389416 _check_missing_tlv!( $last_seen_type, $type, $field, required) ;
@@ -438,9 +465,15 @@ macro_rules! _decode_tlv {
438465 let _field: & Option <$fieldty> = & $field;
439466 $crate:: _decode_tlv!( $outer_reader, $reader, $field, option) ;
440467 } } ;
441- ( $outer_reader: expr, $reader: expr, $field: ident, ( legacy, $fieldty: ty, $write: expr) ) => { {
468+ ( $outer_reader: expr, $reader: expr, $field: ident, ( legacy, $fieldty: ty, $read : expr , $ write: expr) ) => { {
442469 $crate:: _decode_tlv!( $outer_reader, $reader, $field, ( option, explicit_type: $fieldty) ) ;
443470 } } ;
471+ ( $outer_reader: expr, $reader: expr, $field: ident, ( custom, $fieldty: ty, $read: expr, $write: expr) ) => { {
472+ let read_field: $fieldty;
473+ $crate:: _decode_tlv!( $outer_reader, $reader, read_field, required) ;
474+ let read_result: Result <_, DecodeError > = $read( Some ( read_field) ) ;
475+ $field = read_result?. into( ) ;
476+ } } ;
444477 ( $outer_reader: expr, $reader: expr, $field: ident, ( required, explicit_type: $fieldty: ty) ) => { {
445478 let _field: & $fieldty = & $field;
446479 _decode_tlv!( $outer_reader, $reader, $field, required) ;
@@ -827,9 +860,12 @@ macro_rules! _init_tlv_based_struct_field {
827860 ( $field: ident, option) => {
828861 $field
829862 } ;
830- ( $field: ident, ( legacy, $fieldty: ty, $write: expr) ) => {
863+ ( $field: ident, ( legacy, $fieldty: ty, $read : expr , $ write: expr) ) => {
831864 $crate:: _init_tlv_based_struct_field!( $field, option)
832865 } ;
866+ ( $field: ident, ( custom, $fieldty: ty, $read: expr, $write: expr) ) => {
867+ $crate:: _init_tlv_based_struct_field!( $field, required)
868+ } ;
833869 ( $field: ident, ( option: $trait: ident $( , $read_arg: expr) ?) ) => {
834870 $crate:: _init_tlv_based_struct_field!( $field, option)
835871 } ;
@@ -893,9 +929,12 @@ macro_rules! _init_tlv_field_var {
893929 ( $field: ident, ( option, explicit_type: $fieldty: ty) ) => {
894930 let mut $field: Option <$fieldty> = None ;
895931 } ;
896- ( $field: ident, ( legacy, $fieldty: ty, $write: expr) ) => {
932+ ( $field: ident, ( legacy, $fieldty: ty, $read : expr , $ write: expr) ) => {
897933 $crate:: _init_tlv_field_var!( $field, ( option, explicit_type: $fieldty) ) ;
898934 } ;
935+ ( $field: ident, ( custom, $fieldty: ty, $read: expr, $write: expr) ) => {
936+ $crate:: _init_tlv_field_var!( $field, required) ;
937+ } ;
899938 ( $field: ident, ( required, explicit_type: $fieldty: ty) ) => {
900939 let mut $field = $crate:: util:: ser:: RequiredWrapper :: <$fieldty>( None ) ;
901940 } ;
@@ -975,10 +1014,18 @@ macro_rules! _decode_and_build {
9751014/// [`MaybeReadable`], requiring the TLV to be present.
9761015/// If `$fieldty` is `optional_vec`, then `$field` is a [`Vec`], which needs to have its individual elements serialized.
9771016/// Note that for `optional_vec` no bytes are written if the vec is empty
978- /// If `$fieldty` is `(legacy, $ty, $write)` then, when writing, the function $write will be
1017+ /// If `$fieldty` is `(legacy, $ty, $read, $ write)` then, when writing, the function $write will be
9791018/// called with the object being serialized and a returned `Option` and is written as a TLV if
980- /// `Some`. When reading, an optional field of type `$ty` is read (which can be used in later
981- /// `default_value` or `static_value` fields by referring to the value by name).
1019+ /// `Some`. When reading, an optional field of type `$ty` is read, and after all TLV fields are
1020+ /// read, the `$read` closure is called with the `Option<&$ty>` value. The `$read` closure should
1021+ /// return a `Result<(), DecodeError>`. Legacy field values can be used in later
1022+ /// `default_value` or `static_value` fields by referring to the value by name.
1023+ /// If `$fieldty` is `(custom, $ty, $read, $write)` then, when writing, the same behavior as
1024+ /// `legacy`, above is used. When reading, if a TLV is present, it is read as `$ty` and the
1025+ /// `$read` method is called with `Some(decoded_$ty_object)`. If no TLV is present, the field
1026+ /// will be initialized by calling `$read(None)`. `$read` should return a
1027+ /// `Result<field type, DecodeError>` (note that the processed field type may differ from `$ty`;
1028+ /// `$ty` is the type as de/serialized, not necessarily the actual field type).
9821029///
9831030/// For example,
9841031/// ```
@@ -996,7 +1043,7 @@ macro_rules! _decode_and_build {
9961043/// (1, tlv_default_integer, (default_value, 7)),
9971044/// (2, tlv_optional_integer, option),
9981045/// (3, tlv_vec_type_integer, optional_vec),
999- /// (4, unwritten_type, (legacy, u32, |us: &LightningMessage| Some(us.tlv_integer))),
1046+ /// (4, unwritten_type, (legacy, u32, |_| Ok(()), | us: &LightningMessage| Some(us.tlv_integer))),
10001047/// (_unused, tlv_upgraded_integer, (static_value, unwritten_type.unwrap_or(0) * 2))
10011048/// });
10021049/// ```
@@ -1888,7 +1935,7 @@ mod tests {
18881935 new_field : ( u8 , u8 ) ,
18891936 }
18901937 impl_writeable_tlv_based ! ( ExpandedField , {
1891- ( 0 , old_field, ( legacy, u8 , |us: & ExpandedField | Some ( us. new_field. 0 ) ) ) ,
1938+ ( 0 , old_field, ( legacy, u8 , |_| Ok ( ( ) ) , | us: & ExpandedField | Some ( us. new_field. 0 ) ) ) ,
18921939 ( 1 , new_field, ( default_value, ( old_field. ok_or( DecodeError :: InvalidValue ) ?, 0 ) ) ) ,
18931940 } ) ;
18941941
0 commit comments