X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fser_macros.rs;h=782c0ef27d5de87be4992797a352fb3652c07584;hb=a031ff952bee42aad38edd29ede6aaa05a4cb6cb;hp=5178732c7457e93745d39319fa2f2ecee99a80dd;hpb=b3be420cfbf5eccfeebdd813a4c64a9e2e563711;p=rust-lightning diff --git a/lightning/src/util/ser_macros.rs b/lightning/src/util/ser_macros.rs index 5178732c..782c0ef2 100644 --- a/lightning/src/util/ser_macros.rs +++ b/lightning/src/util/ser_macros.rs @@ -99,7 +99,7 @@ macro_rules! check_tlv_order { #[allow(unused_comparisons)] // Note that $type may be 0 making the second comparison always true let invalid_order = ($last_seen_type.is_none() || $last_seen_type.unwrap() < $type) && $typ.0 > $type; if invalid_order { - $field = $default; + $field = $default.into(); } }}; ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, required) => {{ @@ -118,6 +118,9 @@ macro_rules! check_tlv_order { ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, ignorable) => {{ // no-op }}; + ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, (option: $trait: ident $(, $read_arg: expr)?)) => {{ + // no-op + }}; } macro_rules! check_missing_tlv { @@ -125,7 +128,7 @@ macro_rules! check_missing_tlv { #[allow(unused_comparisons)] // Note that $type may be 0 making the second comparison always true let missing_req_type = $last_seen_type.is_none() || $last_seen_type.unwrap() < $type; if missing_req_type { - $field = $default; + $field = $default.into(); } }}; ($last_seen_type: expr, $type: expr, $field: ident, required) => {{ @@ -144,6 +147,9 @@ macro_rules! check_missing_tlv { ($last_seen_type: expr, $type: expr, $field: ident, ignorable) => {{ // no-op }}; + ($last_seen_type: expr, $type: expr, $field: ident, (option: $trait: ident $(, $read_arg: expr)?)) => {{ + // no-op + }}; } macro_rules! decode_tlv { @@ -151,16 +157,20 @@ macro_rules! decode_tlv { decode_tlv!($reader, $field, required) }}; ($reader: expr, $field: ident, required) => {{ - $field = ser::Readable::read(&mut $reader)?; + $field = ::util::ser::Readable::read(&mut $reader)?; }}; ($reader: expr, $field: ident, vec_type) => {{ - $field = Some(ser::Readable::read(&mut $reader)?); + let f: ::util::ser::VecReadWrapper<_> = ::util::ser::Readable::read(&mut $reader)?; + $field = Some(f.0); }}; ($reader: expr, $field: ident, option) => {{ - $field = Some(ser::Readable::read(&mut $reader)?); + $field = Some(::util::ser::Readable::read(&mut $reader)?); }}; ($reader: expr, $field: ident, ignorable) => {{ - $field = ser::MaybeReadable::read(&mut $reader)?; + $field = ::util::ser::MaybeReadable::read(&mut $reader)?; + }}; + ($reader: expr, $field: ident, (option: $trait: ident $(, $read_arg: expr)?)) => {{ + $field = Some($trait::read(&mut $reader $(, $read_arg)*)?); }}; } @@ -230,103 +240,52 @@ macro_rules! decode_tlv_stream { } } } -macro_rules! impl_writeable { - ($st:ident, $len: expr, {$($field:ident),*}) => { +macro_rules! impl_writeable_msg { + ($st:ident, {$($field:ident),* $(,)*}, {$(($type: expr, $tlvfield: ident, $fieldty: tt)),* $(,)*}) => { impl ::util::ser::Writeable for $st { fn write(&self, w: &mut W) -> Result<(), $crate::io::Error> { - if $len != 0 { - w.size_hint($len); - } - #[cfg(any(test, feature = "fuzztarget"))] - { - // In tests, assert that the hard-coded length matches the actual one - if $len != 0 { - let mut len_calc = ::util::ser::LengthCalculatingWriter(0); - $( self.$field.write(&mut len_calc).expect("No in-memory data may fail to serialize"); )* - assert_eq!(len_calc.0, $len); - assert_eq!(self.serialized_length(), $len); - } - } $( self.$field.write(w)?; )* + encode_tlv_stream!(w, {$(($type, self.$tlvfield, $fieldty)),*}); Ok(()) } - - #[inline] - fn serialized_length(&self) -> usize { - if $len == 0 || cfg!(any(test, feature = "fuzztarget")) { - let mut len_calc = 0; - $( len_calc += self.$field.serialized_length(); )* - if $len != 0 { - // In tests, assert that the hard-coded length matches the actual one - assert_eq!(len_calc, $len); - } else { - return len_calc; - } - } - $len - } } - impl ::util::ser::Readable for $st { fn read(r: &mut R) -> Result { + $(let $field = ::util::ser::Readable::read(r)?;)* + $(init_tlv_field_var!($tlvfield, $fieldty);)* + decode_tlv_stream!(r, {$(($type, $tlvfield, $fieldty)),*}); Ok(Self { - $($field: ::util::ser::Readable::read(r)?),* + $($field),*, + $($tlvfield),* }) } } } } -macro_rules! impl_writeable_len_match { - ($struct: ident, $cmp: tt, ($calc_len: expr), {$({$match: pat, $length: expr}),*}, {$($field:ident),*}) => { - impl Writeable for $struct { - fn write(&self, w: &mut W) -> Result<(), $crate::io::Error> { - let len = match *self { - $($match => $length,)* - }; - w.size_hint(len); - #[cfg(any(test, feature = "fuzztarget"))] - { - // In tests, assert that the hard-coded length matches the actual one - let mut len_calc = ::util::ser::LengthCalculatingWriter(0); - $( self.$field.write(&mut len_calc).expect("No in-memory data may fail to serialize"); )* - assert!(len_calc.0 $cmp len); - assert_eq!(len_calc.0, self.serialized_length()); - } + +macro_rules! impl_writeable { + ($st:ident, {$($field:ident),*}) => { + impl ::util::ser::Writeable for $st { + fn write(&self, w: &mut W) -> Result<(), $crate::io::Error> { $( self.$field.write(w)?; )* Ok(()) } #[inline] fn serialized_length(&self) -> usize { - if $calc_len || cfg!(any(test, feature = "fuzztarget")) { - let mut len_calc = 0; - $( len_calc += self.$field.serialized_length(); )* - if !$calc_len { - assert_eq!(len_calc, match *self { - $($match => $length,)* - }); - } - return len_calc - } - match *self { - $($match => $length,)* - } + let mut len_calc = 0; + $( len_calc += self.$field.serialized_length(); )* + return len_calc; } } - impl ::util::ser::Readable for $struct { - fn read(r: &mut R) -> Result { + impl ::util::ser::Readable for $st { + fn read(r: &mut R) -> Result { Ok(Self { - $($field: Readable::read(r)?),* + $($field: ::util::ser::Readable::read(r)?),* }) } } - }; - ($struct: ident, $cmp: tt, {$({$match: pat, $length: expr}),*}, {$($field:ident),*}) => { - impl_writeable_len_match!($struct, $cmp, (true), { $({ $match, $length }),* }, { $($field),* }); - }; - ($struct: ident, {$({$match: pat, $length: expr}),*}, {$($field:ident),*}) => { - impl_writeable_len_match!($struct, ==, (false), { $({ $match, $length }),* }, { $($field),* }); } } @@ -360,7 +319,7 @@ macro_rules! write_ver_prefix { /// correctly. macro_rules! write_tlv_fields { ($stream: expr, {$(($type: expr, $field: expr, $fieldty: tt)),* $(,)*}) => { - encode_varint_length_prefixed_tlv!($stream, {$(($type, $field, $fieldty)),*}); + encode_varint_length_prefixed_tlv!($stream, {$(($type, $field, $fieldty)),*}) } } @@ -390,7 +349,7 @@ macro_rules! read_tlv_fields { macro_rules! init_tlv_based_struct_field { ($field: ident, (default_value, $default: expr)) => { - $field + $field.0.unwrap() }; ($field: ident, option) => { $field @@ -399,19 +358,19 @@ macro_rules! init_tlv_based_struct_field { $field.0.unwrap() }; ($field: ident, vec_type) => { - $field.unwrap().0 + $field.unwrap() }; } macro_rules! init_tlv_field_var { ($field: ident, (default_value, $default: expr)) => { - let mut $field = $default; + let mut $field = ::util::ser::OptionDeserWrapper(None); }; ($field: ident, required) => { let mut $field = ::util::ser::OptionDeserWrapper(None); }; ($field: ident, vec_type) => { - let mut $field = Some(::util::ser::VecReadWrapper(Vec::new())); + let mut $field = Some(Vec::new()); }; ($field: ident, option) => { let mut $field = None; @@ -505,9 +464,12 @@ macro_rules! _impl_writeable_tlv_based_enum_common { 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)),* $(,)*)*) => { _impl_writeable_tlv_based_enum_common!($st, - $(($variant_id, $variant_name) => {$(($type, $field, $fieldty)),*}),*; ); + $(($variant_id, $variant_name) => {$(($type, $field, $fieldty)),*}),*; + $($(($tuple_variant_id, $tuple_variant_name)),*)*); impl ::util::ser::MaybeReadable for $st { fn read(reader: &mut R) -> Result, ::ln::msgs::DecodeError> { @@ -531,6 +493,9 @@ macro_rules! impl_writeable_tlv_based_enum_upgradable { }; f() }),* + $($($tuple_variant_id => { + Ok(Some($st::$tuple_variant_name(Readable::read(reader)?))) + }),*)* _ if id % 2 == 1 => Ok(None), _ => Err(DecodeError::UnknownRequiredFeature), } @@ -598,7 +563,7 @@ mod tests { use io::{self, Cursor}; use prelude::*; use ln::msgs::DecodeError; - use util::ser::{Writeable, HighZeroBytesDroppedVarInt, VecWriter}; + use util::ser::{Writeable, HighZeroBytesDroppedBigSize, VecWriter}; use bitcoin::secp256k1::PublicKey; // The BOLT TLV test cases don't include any tests which use our "required-value" logic since @@ -667,9 +632,9 @@ mod tests { } // BOLT TLV test cases - fn tlv_reader_n1(s: &[u8]) -> Result<(Option>, Option, Option<(PublicKey, u64, u64)>, Option), DecodeError> { + fn tlv_reader_n1(s: &[u8]) -> Result<(Option>, Option, Option<(PublicKey, u64, u64)>, Option), DecodeError> { let mut s = Cursor::new(s); - let mut tlv1: Option> = None; + let mut tlv1: Option> = None; let mut tlv2: Option = None; let mut tlv3: Option<(PublicKey, u64, u64)> = None; let mut tlv4: Option = None; @@ -800,11 +765,11 @@ mod tests { assert_eq!(stream.0, ::hex::decode("06fd00ff02abcd").unwrap()); stream.0.clear(); - encode_varint_length_prefixed_tlv!(&mut stream, {(0, 1u64, required), (42, None::, option), (0xff, HighZeroBytesDroppedVarInt(0u64), required)}); + encode_varint_length_prefixed_tlv!(&mut stream, {(0, 1u64, required), (42, None::, option), (0xff, HighZeroBytesDroppedBigSize(0u64), required)}); assert_eq!(stream.0, ::hex::decode("0e00080000000000000001fd00ff00").unwrap()); stream.0.clear(); - encode_varint_length_prefixed_tlv!(&mut stream, {(0, Some(1u64), option), (0xff, HighZeroBytesDroppedVarInt(0u64), required)}); + encode_varint_length_prefixed_tlv!(&mut stream, {(0, Some(1u64), option), (0xff, HighZeroBytesDroppedBigSize(0u64), required)}); assert_eq!(stream.0, ::hex::decode("0e00080000000000000001fd00ff00").unwrap()); Ok(())