X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fser.rs;h=de12d8506f8d2da87becade08ac82514e30dc6d0;hb=c47acd76e8e60b65335a1bd1b9bbb53ddd43e496;hp=73f3b4dca521affe9439a3b2e4110000c1c03678;hpb=07b674ecb1b92028ba830e8de056d669e50f3752;p=rust-lightning diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs index 73f3b4dc..de12d850 100644 --- a/lightning/src/util/ser.rs +++ b/lightning/src/util/ser.rs @@ -27,6 +27,7 @@ use bitcoin::consensus::Encodable; use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hash_types::{Txid, BlockHash}; use core::marker::Sized; +use core::time::Duration; use ln::msgs::DecodeError; use ln::{PaymentPreimage, PaymentHash, PaymentSecret}; @@ -173,6 +174,7 @@ pub trait Writeable { } /// Writes self out to a Vec + #[cfg(test)] fn encode_with_len(&self) -> Vec { let mut msg = VecWriter(Vec::new()); 0u16.write(&mut msg).unwrap(); @@ -474,10 +476,9 @@ macro_rules! impl_array { ); } -//TODO: performance issue with [u8; size] with impl_array!() impl_array!(3); // for rgb impl_array!(4); // for IPv4 -impl_array!(10); // for OnionV2 +impl_array!(12); // for OnionV2 impl_array!(16); // for IPv6 impl_array!(32); // for channel id & hmac impl_array!(PUBLIC_KEY_SIZE); // for PublicKey @@ -502,14 +503,50 @@ impl Writeable for HashMap impl Readable for HashMap where K: Readable + Eq + Hash, - V: Readable + V: MaybeReadable { #[inline] fn read(r: &mut R) -> Result { let len: u16 = Readable::read(r)?; let mut ret = HashMap::with_capacity(len as usize); for _ in 0..len { - ret.insert(K::read(r)?, V::read(r)?); + let k = K::read(r)?; + let v_opt = V::read(r)?; + if let Some(v) = v_opt { + if ret.insert(k, v).is_some() { + return Err(DecodeError::InvalidValue); + } + } + } + Ok(ret) + } +} + +// HashSet +impl Writeable for HashSet +where T: Writeable + Eq + Hash +{ + #[inline] + fn write(&self, w: &mut W) -> Result<(), io::Error> { + (self.len() as u16).write(w)?; + for item in self.iter() { + item.write(w)?; + } + Ok(()) + } +} + +impl Readable for HashSet +where T: Readable + Eq + Hash +{ + #[inline] + fn read(r: &mut R) -> Result { + let len: u16 = Readable::read(r)?; + let mut ret = HashSet::with_capacity(len as usize); + for _ in 0..len { + if !ret.insert(T::read(r)?) { + return Err(DecodeError::InvalidValue) + } } Ok(ret) } @@ -849,8 +886,45 @@ impl Writeable for (A, B, C) { } } +impl Writeable for () { + fn write(&self, _: &mut W) -> Result<(), io::Error> { + Ok(()) + } +} impl Readable for () { fn read(_r: &mut R) -> Result { Ok(()) } } + +impl Writeable for String { + #[inline] + fn write(&self, w: &mut W) -> Result<(), io::Error> { + (self.len() as u16).write(w)?; + w.write_all(self.as_bytes()) + } +} +impl Readable for String { + #[inline] + fn read(r: &mut R) -> Result { + let v: Vec = Readable::read(r)?; + let ret = String::from_utf8(v).map_err(|_| DecodeError::InvalidValue)?; + Ok(ret) + } +} + +impl Writeable for Duration { + #[inline] + fn write(&self, w: &mut W) -> Result<(), io::Error> { + self.as_secs().write(w)?; + self.subsec_nanos().write(w) + } +} +impl Readable for Duration { + #[inline] + fn read(r: &mut R) -> Result { + let secs = Readable::read(r)?; + let nanos = Readable::read(r)?; + Ok(Duration::new(secs, nanos)) + } +}