X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fser_macros.rs;h=1744b923d5e92589eee665c5a1ef1e263b6cfd8b;hb=e404c129a5914531861608f1d266a4f0b6e48d97;hp=055554073765d258547decb3cc4aba042808d8c7;hpb=85b573ddad70f3c5ee36e0992d587842af507a8d;p=rust-lightning diff --git a/lightning/src/util/ser_macros.rs b/lightning/src/util/ser_macros.rs index 05555407..1744b923 100644 --- a/lightning/src/util/ser_macros.rs +++ b/lightning/src/util/ser_macros.rs @@ -13,6 +13,21 @@ //! [`Readable`]: crate::util::ser::Readable //! [`Writeable`]: crate::util::ser::Writeable +// There are quite a few TLV serialization "types" which behave differently. We currently only +// publicly document the `optional` and `required` types, not supporting anything else publicly and +// changing them at will. +// +// Some of the other types include: +// * (default_value, $default) - reads optionally, reading $default if no TLV is present +// * (static_value, $value) - ignores any TLVs, always using $value +// * required_vec - reads into a Vec without a length prefix, failing if no TLV is present. +// * optional_vec - reads into an Option without a length prefix, continuing if no TLV is +// present. Writes from a Vec directly, only if any elements are present. Note +// that the struct deserialization macros return a Vec, not an Option. +// * upgradable_option - reads via MaybeReadable. +// * upgradable_required - reads via MaybeReadable, requiring a TLV be present but may return None +// if MaybeReadable::read() returns None. + /// Implements serialization for a single TLV record. /// This is exported for use by other exported macros, do not use directly. #[doc(hidden)] @@ -29,7 +44,7 @@ macro_rules! _encode_tlv { BigSize($field.serialized_length() as u64).write($stream)?; $field.write($stream)?; }; - ($stream: expr, $type: expr, $field: expr, vec_type) => { + ($stream: expr, $type: expr, $field: expr, required_vec) => { $crate::_encode_tlv!($stream, $type, $crate::util::ser::WithoutLength(&$field), required); }; ($stream: expr, $optional_type: expr, $optional_field: expr, option) => { @@ -41,7 +56,7 @@ macro_rules! _encode_tlv { }; ($stream: expr, $type: expr, $field: expr, optional_vec) => { if !$field.is_empty() { - $crate::_encode_tlv!($stream, $type, $field, vec_type); + $crate::_encode_tlv!($stream, $type, $field, required_vec); } }; ($stream: expr, $type: expr, $field: expr, upgradable_required) => { @@ -159,7 +174,7 @@ macro_rules! _get_varint_length_prefixed_tlv_length { BigSize(field_len as u64).write(&mut $len).expect("No in-memory data may fail to serialize"); $len.0 += field_len; }; - ($len: expr, $type: expr, $field: expr, vec_type) => { + ($len: expr, $type: expr, $field: expr, required_vec) => { $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $crate::util::ser::WithoutLength(&$field), required); }; ($len: expr, $optional_type: expr, $optional_field: expr, option) => { @@ -172,12 +187,15 @@ macro_rules! _get_varint_length_prefixed_tlv_length { }; ($len: expr, $type: expr, $field: expr, optional_vec) => { if !$field.is_empty() { - $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, vec_type); + $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, required_vec); } }; ($len: expr, $type: expr, $field: expr, (option: $trait: ident $(, $read_arg: expr)?)) => { $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, option); }; + ($len: expr, $type: expr, $field: expr, (option, encoding: ($fieldty: ty, $encoding: ident))) => { + $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field.map(|f| $encoding(f)), option); + }; ($len: expr, $type: expr, $field: expr, upgradable_required) => { $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, required); }; @@ -233,8 +251,8 @@ macro_rules! _check_decoded_tlv_order { ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, option) => {{ // no-op }}; - ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, vec_type) => {{ - // no-op + ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, required_vec) => {{ + $crate::_check_decoded_tlv_order!($last_seen_type, $typ, $type, $field, required); }}; ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, optional_vec) => {{ // no-op @@ -278,8 +296,8 @@ macro_rules! _check_missing_tlv { ($last_seen_type: expr, $type: expr, $field: ident, (required: $trait: ident $(, $read_arg: expr)?)) => {{ $crate::_check_missing_tlv!($last_seen_type, $type, $field, required); }}; - ($last_seen_type: expr, $type: expr, $field: ident, vec_type) => {{ - // no-op + ($last_seen_type: expr, $type: expr, $field: ident, required_vec) => {{ + $crate::_check_missing_tlv!($last_seen_type, $type, $field, required); }}; ($last_seen_type: expr, $type: expr, $field: ident, option) => {{ // no-op @@ -317,15 +335,16 @@ macro_rules! _decode_tlv { ($reader: expr, $field: ident, (required: $trait: ident $(, $read_arg: expr)?)) => {{ $field = $trait::read(&mut $reader $(, $read_arg)*)?; }}; - ($reader: expr, $field: ident, vec_type) => {{ + ($reader: expr, $field: ident, required_vec) => {{ let f: $crate::util::ser::WithoutLength> = $crate::util::ser::Readable::read(&mut $reader)?; - $field = Some(f.0); + $field = f.0; }}; ($reader: expr, $field: ident, option) => {{ $field = Some($crate::util::ser::Readable::read(&mut $reader)?); }}; ($reader: expr, $field: ident, optional_vec) => {{ - $crate::_decode_tlv!($reader, $field, vec_type); + let f: $crate::util::ser::WithoutLength> = $crate::util::ser::Readable::read(&mut $reader)?; + $field = Some(f.0); }}; // `upgradable_required` indicates we're reading a required TLV that may have been upgraded // without backwards compat. We'll error if the field is missing, and return `Ok(None)` if the @@ -554,7 +573,7 @@ macro_rules! impl_writeable_msg { impl $crate::util::ser::Writeable for $st { fn write(&self, w: &mut W) -> Result<(), $crate::io::Error> { $( self.$field.write(w)?; )* - $crate::encode_tlv_stream!(w, {$(($type, self.$tlvfield, $fieldty)),*}); + $crate::encode_tlv_stream!(w, {$(($type, self.$tlvfield.as_ref(), $fieldty)),*}); Ok(()) } } @@ -691,8 +710,8 @@ macro_rules! _init_tlv_based_struct_field { ($field: ident, required) => { $field.0.unwrap() }; - ($field: ident, vec_type) => { - $field.unwrap() + ($field: ident, required_vec) => { + $field }; ($field: ident, optional_vec) => { $field.unwrap() @@ -717,8 +736,8 @@ macro_rules! _init_tlv_field_var { ($field: ident, (required: $trait: ident $(, $read_arg: expr)?)) => { $crate::_init_tlv_field_var!($field, required); }; - ($field: ident, vec_type) => { - let mut $field = Some(Vec::new()); + ($field: ident, required_vec) => { + let mut $field = Vec::new(); }; ($field: ident, option) => { let mut $field = None; @@ -726,6 +745,9 @@ macro_rules! _init_tlv_field_var { ($field: ident, optional_vec) => { let mut $field = Some(Vec::new()); }; + ($field: ident, (option, encoding: ($fieldty: ty, $encoding: ident))) => { + $crate::_init_tlv_field_var!($field, option); + }; ($field: ident, (option: $trait: ident $(, $read_arg: expr)?)) => { $crate::_init_tlv_field_var!($field, option); }; @@ -900,6 +922,8 @@ macro_rules! tlv_record_ref_type { ($type:ty) => { &'a $type }; } +#[doc(hidden)] +#[macro_export] macro_rules! _impl_writeable_tlv_based_enum_common { ($st: ident, $(($variant_id: expr, $variant_name: ident) => {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*} @@ -911,7 +935,7 @@ macro_rules! _impl_writeable_tlv_based_enum_common { $($st::$variant_name { $(ref $field),* } => { let id: u8 = $variant_id; id.write(writer)?; - write_tlv_fields!(writer, { + $crate::write_tlv_fields!(writer, { $(($type, *$field, $fieldty)),* }); }),* @@ -949,7 +973,7 @@ macro_rules! impl_writeable_tlv_based_enum { {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*} ),* $(,)*; $(($tuple_variant_id: expr, $tuple_variant_name: ident)),* $(,)*) => { - _impl_writeable_tlv_based_enum_common!($st, + $crate::_impl_writeable_tlv_based_enum_common!($st, $(($variant_id, $variant_name) => {$(($type, $field, $fieldty)),*}),*; $(($tuple_variant_id, $tuple_variant_name)),*); @@ -961,19 +985,19 @@ macro_rules! impl_writeable_tlv_based_enum { // 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 = || { - _init_and_read_tlv_fields!(reader, { + $crate::_init_and_read_tlv_fields!(reader, { $(($type, $field, $fieldty)),* }); Ok($st::$variant_name { $( - $field: _init_tlv_based_struct_field!($field, $fieldty) + $field: $crate::_init_tlv_based_struct_field!($field, $fieldty) ),* }) }; f() }),* $($tuple_variant_id => { - Ok($st::$tuple_variant_name(Readable::read(reader)?)) + Ok($st::$tuple_variant_name($crate::util::ser::Readable::read(reader)?)) }),* _ => { Err($crate::ln::msgs::DecodeError::UnknownRequiredFeature) @@ -1003,7 +1027,7 @@ macro_rules! impl_writeable_tlv_based_enum_upgradable { ),* $(,)* $(; $(($tuple_variant_id: expr, $tuple_variant_name: ident)),* $(,)*)*) => { - _impl_writeable_tlv_based_enum_common!($st, + $crate::_impl_writeable_tlv_based_enum_common!($st, $(($variant_id, $variant_name) => {$(($type, $field, $fieldty)),*}),*; $($(($tuple_variant_id, $tuple_variant_name)),*)*); @@ -1015,12 +1039,12 @@ macro_rules! impl_writeable_tlv_based_enum_upgradable { // 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 = || { - _init_and_read_tlv_fields!(reader, { + $crate::_init_and_read_tlv_fields!(reader, { $(($type, $field, $fieldty)),* }); Ok(Some($st::$variant_name { $( - $field: _init_tlv_based_struct_field!($field, $fieldty) + $field: $crate::_init_tlv_based_struct_field!($field, $fieldty) ),* })) };