+ ($reader: expr, $field: ident, (default_value, $default: expr)) => {{
+ decode_tlv!($reader, $field, required)
+ }};
+ ($reader: expr, $field: ident, (static_value, $value: expr)) => {{
+ }};
+ ($reader: expr, $field: ident, required) => {{
+ $field = $crate::util::ser::Readable::read(&mut $reader)?;
+ }};
+ ($reader: expr, $field: ident, vec_type) => {{
+ let f: $crate::util::ser::WithoutLength<Vec<_>> = $crate::util::ser::Readable::read(&mut $reader)?;
+ $field = Some(f.0);
+ }};
+ ($reader: expr, $field: ident, option) => {{
+ $field = Some($crate::util::ser::Readable::read(&mut $reader)?);
+ }};
+ ($reader: expr, $field: ident, ignorable) => {{
+ $field = $crate::util::ser::MaybeReadable::read(&mut $reader)?;
+ }};
+ ($reader: expr, $field: ident, (option: $trait: ident $(, $read_arg: expr)?)) => {{
+ $field = Some($trait::read(&mut $reader $(, $read_arg)*)?);
+ }};
+ ($reader: expr, $field: ident, (option, encoding: ($fieldty: ty, $encoding: ident))) => {{
+ $field = {
+ let field: $encoding<$fieldty> = ser::Readable::read(&mut $reader)?;
+ Some(field.0)
+ };
+ }};
+ ($reader: expr, $field: ident, (option, encoding: $fieldty: ty)) => {{
+ decode_tlv!($reader, $field, option);
+ }};
+}
+
+macro_rules! _decode_tlv_stream_match_check {
+ ($val: ident, $type: expr, (static_value, $value: expr)) => { false };
+ ($val: ident, $type: expr, $fieldty: tt) => { $val == $type }
+}
+
+// `$decode_custom_tlv` is a closure that may be optionally provided to handle custom message types.
+// If it is provided, it will be called with the custom type and the `FixedLengthReader` containing
+// the message contents. It should return `Ok(true)` if the custom message is successfully parsed,
+// `Ok(false)` if the message type is unknown, and `Err(DecodeError)` if parsing fails.
+macro_rules! decode_tlv_stream {
+ ($stream: expr, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}
+ $(, $decode_custom_tlv: expr)?) => { {
+ let rewind = |_, _| { unreachable!() };
+ use core::ops::RangeBounds;
+ decode_tlv_stream_range!(
+ $stream, .., rewind, {$(($type, $field, $fieldty)),*} $(, $decode_custom_tlv)?
+ );
+ } }
+}
+
+macro_rules! decode_tlv_stream_range {
+ ($stream: expr, $range: expr, $rewind: ident, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}
+ $(, $decode_custom_tlv: expr)?) => { {
+ use $crate::ln::msgs::DecodeError;