+
+ #[inline]
+ fn serialized_length(&self) -> usize {
+ let mut len_calc = 0;
+ $( len_calc += self.$field.serialized_length(); )*
+ return len_calc;
+ }
+ }
+
+ impl $crate::util::ser::Readable for $st {
+ fn read<R: $crate::io::Read>(r: &mut R) -> Result<Self, $crate::ln::msgs::DecodeError> {
+ Ok(Self {
+ $($field: $crate::util::ser::Readable::read(r)?),*
+ })
+ }
+ }
+ }
+}
+
+/// Write out two bytes to indicate the version of an object.
+///
+/// $this_version represents a unique version of a type. Incremented whenever the type's
+/// serialization format has changed or has a new interpretation. Used by a type's reader to
+/// determine how to interpret fields or if it can understand a serialized object.
+///
+/// $min_version_that_can_read_this is the minimum reader version which can understand this
+/// serialized object. Previous versions will simply err with a [`DecodeError::UnknownVersion`].
+///
+/// Updates to either `$this_version` or `$min_version_that_can_read_this` should be included in
+/// release notes.
+///
+/// Both version fields can be specific to this type of object.
+///
+/// [`DecodeError::UnknownVersion`]: crate::ln::msgs::DecodeError::UnknownVersion
+macro_rules! write_ver_prefix {
+ ($stream: expr, $this_version: expr, $min_version_that_can_read_this: expr) => {
+ $stream.write_all(&[$this_version; 1])?;
+ $stream.write_all(&[$min_version_that_can_read_this; 1])?;
+ }
+}
+
+/// Writes out a suffix to an object as a length-prefixed TLV stream which contains potentially
+/// backwards-compatible, optional fields which old nodes can happily ignore.
+///
+/// It is written out in TLV format and, as with all TLV fields, unknown even fields cause a
+/// [`DecodeError::UnknownRequiredFeature`] error, with unknown odd fields ignored.
+///
+/// This is the preferred method of adding new fields that old nodes can ignore and still function
+/// correctly.
+///
+/// [`DecodeError::UnknownRequiredFeature`]: crate::ln::msgs::DecodeError::UnknownRequiredFeature
+#[macro_export]
+macro_rules! write_tlv_fields {
+ ($stream: expr, {$(($type: expr, $field: expr, $fieldty: tt)),* $(,)*}) => {
+ $crate::_encode_varint_length_prefixed_tlv!($stream, {$(($type, $field, $fieldty)),*})
+ }
+}
+
+/// Reads a prefix added by [`write_ver_prefix`], above. Takes the current version of the
+/// serialization logic for this object. This is compared against the
+/// `$min_version_that_can_read_this` added by [`write_ver_prefix`].
+macro_rules! read_ver_prefix {
+ ($stream: expr, $this_version: expr) => { {
+ let ver: u8 = Readable::read($stream)?;
+ let min_ver: u8 = Readable::read($stream)?;
+ if min_ver > $this_version {
+ return Err(DecodeError::UnknownVersion);
+ }
+ ver
+ } }
+}
+
+/// Reads a suffix added by [`write_tlv_fields`].
+///
+/// [`write_tlv_fields`]: crate::write_tlv_fields
+#[macro_export]
+macro_rules! read_tlv_fields {
+ ($stream: expr, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}) => { {
+ let tlv_len: $crate::util::ser::BigSize = $crate::util::ser::Readable::read($stream)?;
+ let mut rd = $crate::util::ser::FixedLengthReader::new($stream, tlv_len.0);
+ $crate::decode_tlv_stream!(&mut rd, {$(($type, $field, $fieldty)),*});
+ rd.eat_remaining().map_err(|_| $crate::ln::msgs::DecodeError::ShortRead)?;
+ } }
+}
+
+/// Initializes the struct fields.
+///
+/// This is exported for use by other exported macros, do not use directly.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! _init_tlv_based_struct_field {
+ ($field: ident, (default_value, $default: expr)) => {
+ $field.0.unwrap()
+ };
+ ($field: ident, (static_value, $value: expr)) => {
+ $field
+ };
+ ($field: ident, option) => {
+ $field
+ };
+ ($field: ident, ignorable) => {
+ if $field.is_none() { return Ok(None); } else { $field.unwrap() }
+ };
+ ($field: ident, required) => {
+ $field.0.unwrap()
+ };
+ ($field: ident, vec_type) => {
+ $field.unwrap()
+ };
+}
+
+/// Initializes the variable we are going to read the TLV into.
+///
+/// This is exported for use by other exported macros, do not use directly.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! _init_tlv_field_var {
+ ($field: ident, (default_value, $default: expr)) => {
+ let mut $field = $crate::util::ser::OptionDeserWrapper(None);
+ };
+ ($field: ident, (static_value, $value: expr)) => {
+ let $field;
+ };
+ ($field: ident, required) => {
+ let mut $field = $crate::util::ser::OptionDeserWrapper(None);
+ };
+ ($field: ident, vec_type) => {
+ let mut $field = Some(Vec::new());
+ };
+ ($field: ident, option) => {
+ let mut $field = None;
+ };
+ ($field: ident, ignorable) => {
+ let mut $field = None;
+ };
+}
+
+/// Equivalent to running [`_init_tlv_field_var`] then [`read_tlv_fields`].
+///
+/// This is exported for use by other exported macros, do not use directly.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! _init_and_read_tlv_fields {
+ ($reader: ident, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}) => {
+ $(
+ $crate::_init_tlv_field_var!($field, $fieldty);
+ )*
+
+ $crate::read_tlv_fields!($reader, {
+ $(($type, $field, $fieldty)),*
+ });
+ }
+}
+
+/// Implements [`Readable`]/[`Writeable`] for a struct storing it as a set of TLVs
+/// If `$fieldty` is `required`, then `$field` is a required field that is not an Option nor a Vec.
+/// If `$fieldty` is `(default_value, $default)`, then `$field` will be set to `$default` if not present.
+/// If `$fieldty` is `option`, then `$field` is optional field.
+/// If `$fieldty` is `vec_type`, then `$field` is a Vec, which needs to have its individual elements serialized.
+///
+/// For example,
+/// ```
+/// # use lightning::impl_writeable_tlv_based;
+/// struct LightningMessage {
+/// tlv_integer: u32,
+/// tlv_default_integer: u32,
+/// tlv_optional_integer: Option<u32>,
+/// tlv_vec_type_integer: Vec<u32>,
+/// }
+///
+/// impl_writeable_tlv_based!(LightningMessage, {
+/// (0, tlv_integer, required),
+/// (1, tlv_default_integer, (default_value, 7)),
+/// (2, tlv_optional_integer, option),
+/// (3, tlv_vec_type_integer, vec_type),
+/// });
+/// ```
+///
+/// [`Readable`]: crate::util::ser::Readable
+/// [`Writeable`]: crate::util::ser::Writeable
+#[macro_export]
+macro_rules! impl_writeable_tlv_based {
+ ($st: ident, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}) => {
+ impl $crate::util::ser::Writeable for $st {
+ fn write<W: $crate::util::ser::Writer>(&self, writer: &mut W) -> Result<(), $crate::io::Error> {
+ $crate::write_tlv_fields!(writer, {
+ $(($type, self.$field, $fieldty)),*
+ });
+ Ok(())
+ }
+
+ #[inline]
+ fn serialized_length(&self) -> usize {
+ use $crate::util::ser::BigSize;
+ let len = {
+ #[allow(unused_mut)]
+ let mut len = $crate::util::ser::LengthCalculatingWriter(0);
+ $(
+ $crate::_get_varint_length_prefixed_tlv_length!(len, $type, self.$field, $fieldty);
+ )*
+ len.0
+ };
+ let mut len_calc = $crate::util::ser::LengthCalculatingWriter(0);
+ BigSize(len as u64).write(&mut len_calc).expect("No in-memory data may fail to serialize");
+ len + len_calc.0
+ }