+/// Implement [`MaybeReadable`] and [`Writeable`] for an enum, with struct variants stored as TLVs and
+/// tuple variants stored directly.
+///
+/// This is largely identical to [`impl_writeable_tlv_based_enum`], except that odd variants will
+/// return `Ok(None)` instead of `Err(`[`DecodeError::UnknownRequiredFeature`]`)`. It should generally be preferred
+/// when [`MaybeReadable`] is practical instead of just [`Readable`] as it provides an upgrade path for
+/// new variants to be added which are simply ignored by existing clients.
+///
+/// [`MaybeReadable`]: crate::util::ser::MaybeReadable
+/// [`Writeable`]: crate::util::ser::Writeable
+/// [`DecodeError::UnknownRequiredFeature`]: crate::ln::msgs::DecodeError::UnknownRequiredFeature
+/// [`Readable`]: crate::util::ser::Readable
+#[macro_export]
+macro_rules! impl_writeable_tlv_based_enum_upgradable {
+ ($st: ident, $(($variant_id: expr, $variant_name: ident) =>
+ {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}
+ ),* $(,)*
+ $(;
+ $(($tuple_variant_id: expr, $tuple_variant_name: ident)),* $(,)*)*) => {
+ $crate::_impl_writeable_tlv_based_enum_common!($st,
+ $(($variant_id, $variant_name) => {$(($type, $field, $fieldty)),*}),*;
+ $($(($tuple_variant_id, $tuple_variant_name)),*)*);
+
+ impl $crate::util::ser::MaybeReadable for $st {
+ fn read<R: $crate::io::Read>(reader: &mut R) -> Result<Option<Self>, $crate::ln::msgs::DecodeError> {
+ let id: u8 = $crate::util::ser::Readable::read(reader)?;
+ match id {
+ $($variant_id => {
+ // Because read_tlv_fields creates a labeled loop, we cannot call it twice
+ // in the same function body. Instead, we define a closure and call it.
+ let f = || {
+ $crate::_init_and_read_tlv_fields!(reader, {
+ $(($type, $field, $fieldty)),*
+ });
+ Ok(Some($st::$variant_name {
+ $(
+ $field: $crate::_init_tlv_based_struct_field!($field, $fieldty)
+ ),*
+ }))
+ };
+ f()
+ }),*
+ $($($tuple_variant_id => {
+ Ok(Some($st::$tuple_variant_name(Readable::read(reader)?)))
+ }),*)*
+ _ if id % 2 == 1 => Ok(None),
+ _ => Err($crate::ln::msgs::DecodeError::UnknownRequiredFeature),
+ }
+ }
+ }
+ }
+}
+