From: Matt Corallo Date: Wed, 28 Jul 2021 20:18:10 +0000 (+0000) Subject: Implement `VecReadWrapper` for `MaybeReadable` X-Git-Tag: v0.0.100~2^2~1 X-Git-Url: http://git.bitcoin.ninja/index.cgi?p=rust-lightning;a=commitdiff_plain;h=45490d537edb422c945e8bf20fec21b1878863de Implement `VecReadWrapper` for `MaybeReadable` This makes it much simpler to deal with `MaybeReadable` types in `Vec`s in TLVs as we can transparently deal with them as `vec`, with the wrapper doing the Right Thing. This requires we implement `MaybeReadable` for all `Readable` which has some downstream implications, but nothing too bad. --- diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 7304c698..38e2172e 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -1477,8 +1477,8 @@ impl ChannelMana let mut chacha = ChaCha20::new(&rho, &[0u8; 8]); let mut chacha_stream = ChaChaReader { chacha: &mut chacha, read: Cursor::new(&msg.onion_routing_packet.hop_data[..]) }; - let (next_hop_data, next_hop_hmac) = { - match msgs::OnionHopData::read(&mut chacha_stream) { + let (next_hop_data, next_hop_hmac): (msgs::OnionHopData, _) = { + match ::read(&mut chacha_stream) { Err(err) => { let error_code = match err { msgs::DecodeError::UnknownVersion => 0x4000 | 1, // unknown realm byte diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs index b27cf4b3..a7f69fcf 100644 --- a/lightning/src/util/ser.rs +++ b/lightning/src/util/ser.rs @@ -241,6 +241,13 @@ pub trait MaybeReadable fn read(reader: &mut R) -> Result, DecodeError>; } +impl MaybeReadable for T { + #[inline] + fn read(reader: &mut R) -> Result, DecodeError> { + Ok(Some(Readable::read(reader)?)) + } +} + pub(crate) struct OptionDeserWrapper(pub Option); impl Readable for OptionDeserWrapper { #[inline] @@ -262,15 +269,16 @@ impl<'a, T: Writeable> Writeable for VecWriteWrapper<'a, T> { } /// Wrapper to read elements from a given stream until it reaches the end of the stream. -pub(crate) struct VecReadWrapper(pub Vec); -impl Readable for VecReadWrapper { +pub(crate) struct VecReadWrapper(pub Vec); +impl Readable for VecReadWrapper { #[inline] fn read(mut reader: &mut R) -> Result { let mut values = Vec::new(); loop { let mut track_read = ReadTrackingReader::new(&mut reader); - match Readable::read(&mut track_read) { - Ok(v) => { values.push(v); }, + match MaybeReadable::read(&mut track_read) { + Ok(Some(v)) => { values.push(v); }, + Ok(None) => { }, // If we failed to read any bytes at all, we reached the end of our TLV // stream and have simply exhausted all entries. Err(ref e) if e == &DecodeError::ShortRead && !track_read.have_read => break, @@ -561,7 +569,7 @@ impl Readable for Vec { return Err(DecodeError::BadLengthDescriptor); } let mut ret = Vec::with_capacity(len as usize); - for _ in 0..len { ret.push(Signature::read(r)?); } + for _ in 0..len { ret.push(Readable::read(r)?); } Ok(ret) } } @@ -726,7 +734,8 @@ impl Writeable for Option { impl Readable for Option { fn read(r: &mut R) -> Result { - match BigSize::read(r)?.0 { + let len: BigSize = Readable::read(r)?; + match len.0 { 0 => Ok(None), len => { let mut reader = FixedLengthReader::new(r, len - 1); diff --git a/lightning/src/util/ser_macros.rs b/lightning/src/util/ser_macros.rs index 960fae45..e988ad7e 100644 --- a/lightning/src/util/ser_macros.rs +++ b/lightning/src/util/ser_macros.rs @@ -371,7 +371,7 @@ macro_rules! read_ver_prefix { /// Reads a suffix added by write_tlv_fields. macro_rules! read_tlv_fields { ($stream: expr, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}) => { { - let tlv_len = ::util::ser::BigSize::read($stream)?; + let tlv_len: ::util::ser::BigSize = ::util::ser::Readable::read($stream)?; let mut rd = ::util::ser::FixedLengthReader::new($stream, tlv_len.0); decode_tlv_stream!(&mut rd, {$(($type, $field, $fieldty)),*}); rd.eat_remaining().map_err(|_| ::ln::msgs::DecodeError::ShortRead)?;