Add macros for building TLV (de)serializers.
[rust-lightning] / lightning / src / util / ser.rs
index a2ef16b5e2462c51dd22f7c4444cd0cf7b22460a..fd82330c85b1a7cfea29da454b80e288e1155e75 100644 (file)
@@ -5,6 +5,8 @@ use std::result::Result;
 use std::io::{Read, Write};
 use std::collections::HashMap;
 use std::hash::Hash;
+use std::sync::Mutex;
+use std::cmp;
 
 use secp256k1::Signature;
 use secp256k1::key::{PublicKey, SecretKey};
@@ -66,6 +68,46 @@ impl Writer for VecWriter {
        }
 }
 
+pub(crate) struct LengthCalculatingWriter(pub usize);
+impl Writer for LengthCalculatingWriter {
+       #[inline]
+       fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> {
+               self.0 += buf.len();
+               Ok(())
+       }
+       #[inline]
+       fn size_hint(&mut self, _size: usize) {}
+}
+
+/// Essentially std::io::Take but a bit simpler and exposing the amount read at the end, cause we
+/// may need to skip ahead that much at the end.
+pub(crate) struct FixedLengthReader<R: Read> {
+       pub read: R,
+       pub read_len: u64,
+       pub max_len: u64,
+}
+impl<R: Read> FixedLengthReader<R> {
+       pub fn eat_remaining(&mut self) -> Result<(), ::std::io::Error> {
+               while self.read_len != self.max_len {
+                       debug_assert!(self.read_len < self.max_len);
+                       let mut buf = [0; 1024];
+                       let readsz = cmp::min(1024, self.max_len - self.read_len) as usize;
+                       self.read_exact(&mut buf[0..readsz])?;
+               }
+               Ok(())
+       }
+}
+impl<R: Read> Read for FixedLengthReader<R> {
+       fn read(&mut self, dest: &mut [u8]) -> Result<usize, ::std::io::Error> {
+               if dest.len() as u64 > self.max_len - self.read_len {
+                       Ok(0)
+               } else {
+                       self.read_len += dest.len() as u64;
+                       self.read.read(dest)
+               }
+       }
+}
+
 /// A trait that various rust-lightning types implement allowing them to be written out to a Writer
 pub trait Writeable {
        /// Writes self out to the given Writer
@@ -442,3 +484,29 @@ impl<R: Read> Readable<R> for OutPoint {
                })
        }
 }
+
+impl<R: Read, T: Readable<R>> Readable<R> for Mutex<T> {
+       fn read(r: &mut R) -> Result<Self, DecodeError> {
+               let t: T = Readable::read(r)?;
+               Ok(Mutex::new(t))
+       }
+}
+impl<T: Writeable> Writeable for Mutex<T> {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+               self.lock().unwrap().write(w)
+       }
+}
+
+impl<R: Read, A: Readable<R>, B: Readable<R>> Readable<R> for (A, B) {
+       fn read(r: &mut R) -> Result<Self, DecodeError> {
+               let a: A = Readable::read(r)?;
+               let b: B = Readable::read(r)?;
+               Ok((a, b))
+       }
+}
+impl<A: Writeable, B: Writeable> Writeable for (A, B) {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+               self.0.write(w)?;
+               self.1.write(w)
+       }
+}