Merge pull request #2015 from TheBlueMatt/2023-02-no-dumb-redundant-fields
[rust-lightning] / lightning / src / util / ser.rs
index 84d1a2e084feb65e1472969875a586c81ccd08e5..14c25775174b19dc50f4dabe5ecb434ce0ea259b 100644 (file)
@@ -289,18 +289,36 @@ impl<T: Readable> MaybeReadable for T {
 }
 
 /// Wrapper to read a required (non-optional) TLV record.
-pub struct OptionDeserWrapper<T: Readable>(pub Option<T>);
-impl<T: Readable> Readable for OptionDeserWrapper<T> {
+pub struct RequiredWrapper<T>(pub Option<T>);
+impl<T: Readable> Readable for RequiredWrapper<T> {
        #[inline]
        fn read<R: Read>(reader: &mut R) -> Result<Self, DecodeError> {
                Ok(Self(Some(Readable::read(reader)?)))
        }
 }
+impl<A, T: ReadableArgs<A>> ReadableArgs<A> for RequiredWrapper<T> {
+       #[inline]
+       fn read<R: Read>(reader: &mut R, args: A) -> Result<Self, DecodeError> {
+               Ok(Self(Some(ReadableArgs::read(reader, args)?)))
+       }
+}
 /// When handling `default_values`, we want to map the default-value T directly
-/// to a `OptionDeserWrapper<T>` in a way that works for `field: T = t;` as
+/// to a `RequiredWrapper<T>` in a way that works for `field: T = t;` as
 /// well. Thus, we assume `Into<T> for T` does nothing and use that.
-impl<T: Readable> From<T> for OptionDeserWrapper<T> {
-       fn from(t: T) -> OptionDeserWrapper<T> { OptionDeserWrapper(Some(t)) }
+impl<T> From<T> for RequiredWrapper<T> {
+       fn from(t: T) -> RequiredWrapper<T> { RequiredWrapper(Some(t)) }
+}
+
+/// Wrapper to read a required (non-optional) TLV record that may have been upgraded without
+/// backwards compat.
+pub struct UpgradableRequired<T: MaybeReadable>(pub Option<T>);
+impl<T: MaybeReadable> MaybeReadable for UpgradableRequired<T> {
+       #[inline]
+       fn read<R: Read>(reader: &mut R) -> Result<Option<Self>, DecodeError> {
+               let tlv = MaybeReadable::read(reader)?;
+               if let Some(tlv) = tlv { return Ok(Some(Self(Some(tlv)))) }
+               Ok(None)
+       }
 }
 
 pub(crate) struct U48(pub u64);
@@ -624,6 +642,26 @@ impl<'a, T> From<&'a Vec<T>> for WithoutLength<&'a Vec<T>> {
        fn from(v: &'a Vec<T>) -> Self { Self(v) }
 }
 
+#[derive(Debug)]
+pub(crate) struct Iterable<'a, I: Iterator<Item = &'a T> + Clone, T: 'a>(pub I);
+
+impl<'a, I: Iterator<Item = &'a T> + Clone, T: 'a + Writeable> Writeable for Iterable<'a, I, T> {
+       #[inline]
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+               for ref v in self.0.clone() {
+                       v.write(writer)?;
+               }
+               Ok(())
+       }
+}
+
+#[cfg(test)]
+impl<'a, I: Iterator<Item = &'a T> + Clone, T: 'a + PartialEq> PartialEq for Iterable<'a, I, T> {
+       fn eq(&self, other: &Self) -> bool {
+               self.0.clone().collect::<Vec<_>>() == other.0.clone().collect::<Vec<_>>()
+       }
+}
+
 macro_rules! impl_for_map {
        ($ty: ident, $keybound: ident, $constr: expr) => {
                impl<K, V> Writeable for $ty<K, V>
@@ -750,6 +788,7 @@ impl Readable for Vec<u8> {
 }
 
 impl_for_vec!(ecdsa::Signature);
+impl_for_vec!(crate::ln::channelmanager::MonitorUpdateCompletionAction);
 impl_for_vec!((A, B), A, B);
 
 impl Writeable for Script {
@@ -1065,6 +1104,24 @@ impl<A: Writeable, B: Writeable, C: Writeable> Writeable for (A, B, C) {
        }
 }
 
+impl<A: Readable, B: Readable, C: Readable, D: Readable> Readable for (A, B, C, D) {
+       fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+               let a: A = Readable::read(r)?;
+               let b: B = Readable::read(r)?;
+               let c: C = Readable::read(r)?;
+               let d: D = Readable::read(r)?;
+               Ok((a, b, c, d))
+       }
+}
+impl<A: Writeable, B: Writeable, C: Writeable, D: Writeable> Writeable for (A, B, C, D) {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+               self.0.write(w)?;
+               self.1.write(w)?;
+               self.2.write(w)?;
+               self.3.write(w)
+       }
+}
+
 impl Writeable for () {
        fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> {
                Ok(())