Support `ReadableArgs` types across in the TLV struct serialization
authorMatt Corallo <git@bluematt.me>
Mon, 6 Feb 2023 21:56:39 +0000 (21:56 +0000)
committerMatt Corallo <git@bluematt.me>
Mon, 27 Feb 2023 22:31:11 +0000 (22:31 +0000)
This adds `required` support for trait-wrapped reading (e.g. for
objects read via `ReadableArgs`) as well as support for the
trait-wrapped reading syntax across the TLV struct/enum
serialization macros.

lightning/src/util/ser.rs
lightning/src/util/ser_macros.rs

index 5adf5758131bb65e9929042a267162e3665c58e2..14c25775174b19dc50f4dabe5ecb434ce0ea259b 100644 (file)
@@ -289,17 +289,23 @@ impl<T: Readable> MaybeReadable for T {
 }
 
 /// Wrapper to read a required (non-optional) TLV record.
-pub struct RequiredWrapper<T: Readable>(pub Option<T>);
+pub struct RequiredWrapper<T>(pub Option<T>);
 impl<T: Readable> Readable for RequiredWrapper<T> {
        #[inline]
        fn read<R: Read>(reader: &mut R) -> Result<Self, DecodeError> {
                Ok(Self(Some(Readable::read(reader)?)))
        }
 }
+impl<A, T: ReadableArgs<A>> ReadableArgs<A> for RequiredWrapper<T> {
+       #[inline]
+       fn read<R: Read>(reader: &mut R, args: A) -> Result<Self, DecodeError> {
+               Ok(Self(Some(ReadableArgs::read(reader, args)?)))
+       }
+}
 /// When handling `default_values`, we want to map the default-value T directly
 /// to a `RequiredWrapper<T>` in a way that works for `field: T = t;` as
 /// well. Thus, we assume `Into<T> for T` does nothing and use that.
-impl<T: Readable> From<T> for RequiredWrapper<T> {
+impl<T> From<T> for RequiredWrapper<T> {
        fn from(t: T) -> RequiredWrapper<T> { RequiredWrapper(Some(t)) }
 }
 
index 5e55ab1d3b8182baf80f87e0e1a929d90380057c..59402f6acc8e0eab43810eb896a678186e2e9efc 100644 (file)
@@ -51,6 +51,10 @@ macro_rules! _encode_tlv {
        ($stream: expr, $type: expr, $field: expr, (option, encoding: $fieldty: ty)) => {
                $crate::_encode_tlv!($stream, $type, $field, option);
        };
+       ($stream: expr, $type: expr, $field: expr, (option: $trait: ident $(, $read_arg: expr)?)) => {
+               // Just a read-mapped type
+               $crate::_encode_tlv!($stream, $type, $field, option);
+       };
 }
 
 /// Panics if the last seen TLV type is not numerically less than the TLV type currently being checked.
@@ -161,6 +165,9 @@ macro_rules! _get_varint_length_prefixed_tlv_length {
                        $len.0 += field_len;
                }
        };
+       ($len: expr, $type: expr, $field: expr, (option: $trait: ident $(, $read_arg: expr)?)) => {
+               $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, option);
+       };
        ($len: expr, $type: expr, $field: expr, upgradable_required) => {
                $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, required);
        };
@@ -210,6 +217,9 @@ macro_rules! _check_decoded_tlv_order {
                        return Err(DecodeError::InvalidValue);
                }
        }};
+       ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, (required: $trait: ident $(, $read_arg: expr)?)) => {{
+               $crate::_check_decoded_tlv_order!($last_seen_type, $typ, $type, $field, required);
+       }};
        ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, option) => {{
                // no-op
        }};
@@ -252,6 +262,9 @@ macro_rules! _check_missing_tlv {
                        return Err(DecodeError::InvalidValue);
                }
        }};
+       ($last_seen_type: expr, $type: expr, $field: ident, (required: $trait: ident $(, $read_arg: expr)?)) => {{
+               $crate::_check_missing_tlv!($last_seen_type, $type, $field, required);
+       }};
        ($last_seen_type: expr, $type: expr, $field: ident, vec_type) => {{
                // no-op
        }};
@@ -285,6 +298,9 @@ macro_rules! _decode_tlv {
        ($reader: expr, $field: ident, required) => {{
                $field = $crate::util::ser::Readable::read(&mut $reader)?;
        }};
+       ($reader: expr, $field: ident, (required: $trait: ident $(, $read_arg: expr)?)) => {{
+               $field = $trait::read(&mut $reader $(, $read_arg)*)?;
+       }};
        ($reader: expr, $field: ident, vec_type) => {{
                let f: $crate::util::ser::WithoutLength<Vec<_>> = $crate::util::ser::Readable::read(&mut $reader)?;
                $field = Some(f.0);
@@ -644,6 +660,9 @@ macro_rules! _init_tlv_based_struct_field {
        ($field: ident, option) => {
                $field
        };
+       ($field: ident, (option: $trait: ident $(, $read_arg: expr)?)) => {
+               $crate::_init_tlv_based_struct_field!($field, option)
+       };
        ($field: ident, upgradable_required) => {
                $field.0.unwrap()
        };
@@ -673,12 +692,18 @@ macro_rules! _init_tlv_field_var {
        ($field: ident, required) => {
                let mut $field = $crate::util::ser::RequiredWrapper(None);
        };
+       ($field: ident, (required: $trait: ident $(, $read_arg: expr)?)) => {
+               $crate::_init_tlv_field_var!($field, required);
+       };
        ($field: ident, vec_type) => {
                let mut $field = Some(Vec::new());
        };
        ($field: ident, option) => {
                let mut $field = None;
        };
+       ($field: ident, (option: $trait: ident $(, $read_arg: expr)?)) => {
+               $crate::_init_tlv_field_var!($field, option);
+       };
        ($field: ident, upgradable_required) => {
                let mut $field = $crate::util::ser::UpgradableRequired(None);
        };