+ ($stream: expr, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}) => {
+ let rewind = |_, _| { unreachable!() };
+ $crate::_decode_tlv_stream_range!($stream, .., rewind, {$(($type, $field, $fieldty)),*});
+ }
+}
+
+/// Similar to [`decode_tlv_stream`] with a custom TLV decoding capabilities.
+///
+/// `$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.
+///
+/// [`FixedLengthReader`]: crate::util::ser::FixedLengthReader
+/// [`DecodeError`]: crate::ln::msgs::DecodeError
+macro_rules! decode_tlv_stream_with_custom_tlv_decode {
+ ($stream: expr, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}
+ $(, $decode_custom_tlv: expr)?) => { {
+ let rewind = |_, _| { unreachable!() };
+ _decode_tlv_stream_range!(
+ $stream, .., rewind, {$(($type, $field, $fieldty)),*} $(, $decode_custom_tlv)?
+ );
+ } }
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! _decode_tlv_stream_range {
+ ($stream: expr, $range: expr, $rewind: ident, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}
+ $(, $decode_custom_tlv: expr)?) => { {
+ use core::ops::RangeBounds;
+ use $crate::ln::msgs::DecodeError;