Skip to content

Expose impl_writeable_msg #1976

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 35 additions & 5 deletions lightning/src/util/ser_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,20 +457,50 @@ macro_rules! _decode_tlv_stream_range {
} }
}

/// Implements [`Readable`]/[`Writeable`] for a message struct that may include non-TLV and
/// TLV-encoded parts.
///
/// This is useful to implement a [`CustomMessageReader`].
///
/// Currently `$fieldty` may only be `option`, i.e., `$tlvfield` is optional field.
///
/// For example,
/// ```
/// # use lightning::impl_writeable_msg;
/// struct MyCustomMessage {
/// pub field_1: u32,
/// pub field_2: bool,
/// pub field_3: String,
/// pub tlv_optional_integer: Option<u32>,
/// }
///
/// impl_writeable_msg!(MyCustomMessage, {
/// field_1,
/// field_2,
/// field_3
/// }, {
/// (1, tlv_optional_integer, option),
/// });
/// ```
///
/// [`Readable`]: crate::util::ser::Readable
/// [`Writeable`]: crate::util::ser::Writeable
/// [`CustomMessageReader`]: crate::ln::wire::CustomMessageReader
#[macro_export]
macro_rules! impl_writeable_msg {
($st:ident, {$($field:ident),* $(,)*}, {$(($type: expr, $tlvfield: ident, $fieldty: tt)),* $(,)*}) => {
impl $crate::util::ser::Writeable for $st {
fn write<W: $crate::util::ser::Writer>(&self, w: &mut W) -> Result<(), $crate::io::Error> {
$( self.$field.write(w)?; )*
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires a use $crate::util::ser::Writeable, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, doesn't seem so for the doctest, and also seems to work in a trivial freestanding example?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, in your example you have an explicit use lightning::util::ser::Writeable;, my point was that if there isn't one in the file in question it needs to be in the macro.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure. a) the example builds fine without the import, it is only needed for the my_custom_msg.write call. Initial version with just the impl works just fine b) If I add the use statement to the macro it's immediately marked as unused. 🤷‍♂️

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, that's...very surprising to me. Whatever, then.

encode_tlv_stream!(w, {$(($type, self.$tlvfield, $fieldty)),*});
$crate::encode_tlv_stream!(w, {$(($type, self.$tlvfield, $fieldty)),*});
Ok(())
}
}
impl $crate::util::ser::Readable for $st {
fn read<R: $crate::io::Read>(r: &mut R) -> Result<Self, $crate::ln::msgs::DecodeError> {
$(let $field = $crate::util::ser::Readable::read(r)?;)*
$(_init_tlv_field_var!($tlvfield, $fieldty);)*
decode_tlv_stream!(r, {$(($type, $tlvfield, $fieldty)),*});
$($crate::_init_tlv_field_var!($tlvfield, $fieldty);)*
$crate::decode_tlv_stream!(r, {$(($type, $tlvfield, $fieldty)),*});
Ok(Self {
$($field),*,
$($tlvfield),*
Expand Down Expand Up @@ -642,10 +672,10 @@ macro_rules! _init_and_read_tlv_fields {
}

/// 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 `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.
/// If `$fieldty` is `vec_type`, then `$field` is a [`Vec`], which needs to have its individual elements serialized.
///
/// For example,
/// ```
Expand Down