{
/// Reads a Self in from the given Read
fn read<R: Read>(reader: &mut R) -> Result<Self, DecodeError>;
+
+ const FIXED_LEN: Option<usize> = None;
+ ///a
+ fn fixed_len_read(&self) -> Option<usize> { Self::FIXED_LEN }
+}
+pub(crate) trait Lulz {
+ fn lulz_len_read(&self) -> Option<usize>;
+}
+impl<T: Readable> Lulz for Option<T> {
+ #[inline]
+ fn lulz_len_read(&self) -> Option<usize> {
+ T::FIXED_LEN
+ }
}
/// A trait that various higher-level rust-lightning types implement allowing them to be read in
fn read<R: Read>(reader: &mut R) -> Result<Self, DecodeError> {
Ok(Self(Some(Readable::read(reader)?)))
}
+ const FIXED_LEN: Option<usize> = T::FIXED_LEN;
}
pub(crate) struct U8Wrapper(pub u8);
reader.read_exact(&mut buf)?;
Ok(<$val_type>::from_be_bytes(buf))
}
+ const FIXED_LEN: Option<usize> = Some($len);
}
impl Readable for HighZeroBytesDroppedVarInt<$val_type> {
#[inline]
reader.read_exact(&mut buf)?;
Ok(buf[0])
}
+ const FIXED_LEN: Option<usize> = Some(1);
}
impl Writeable for bool {
}
Ok(buf[0] == 1)
}
+ const FIXED_LEN: Option<usize> = Some(1);
}
// u8 arrays
r.read_exact(&mut buf)?;
Ok(buf)
}
+ const FIXED_LEN: Option<usize> = Some($size);
}
);
}
Err(_) => return Err(DecodeError::InvalidValue),
}
}
+ const FIXED_LEN: Option<usize> = Some(PUBLIC_KEY_SIZE);
}
impl Writeable for SecretKey {
Err(_) => return Err(DecodeError::InvalidValue),
}
}
+ const FIXED_LEN: Option<usize> = Some(32);
}
impl Writeable for Sha256dHash {
let buf: [u8; 32] = Readable::read(r)?;
Ok(Sha256dHash::from_slice(&buf[..]).unwrap())
}
+ const FIXED_LEN: Option<usize> = Some(32);
}
impl Writeable for Signature {
Err(_) => return Err(DecodeError::InvalidValue),
}
}
+ const FIXED_LEN: Option<usize> = Some(COMPACT_SIGNATURE_SIZE);
}
impl Writeable for PaymentPreimage {
let buf: [u8; 32] = Readable::read(r)?;
Ok(PaymentPreimage(buf))
}
+ const FIXED_LEN: Option<usize> = Some(32);
}
impl Writeable for PaymentHash {
let buf: [u8; 32] = Readable::read(r)?;
Ok(PaymentHash(buf))
}
+ const FIXED_LEN: Option<usize> = Some(32);
}
impl Writeable for PaymentSecret {
let buf: [u8; 32] = Readable::read(r)?;
Ok(PaymentSecret(buf))
}
+ const FIXED_LEN: Option<usize> = Some(32);
}
impl<T: Writeable> Writeable for Option<T> {
let buf: [u8; 32] = Readable::read(r)?;
Ok(Txid::from_slice(&buf[..]).unwrap())
}
+ const FIXED_LEN: Option<usize> = Some(32);
}
impl Writeable for BlockHash {
let buf: [u8; 32] = Readable::read(r)?;
Ok(BlockHash::from_slice(&buf[..]).unwrap())
}
+ const FIXED_LEN: Option<usize> = Some(32);
}
impl Writeable for OutPoint {
};
($name_ty: path, $stream: expr, {$(($reqtype: expr, $reqfield: ident)),*}, {$(($type: expr, $field: ident)),*}) => { {
use ln::msgs::DecodeError;
+ #[allow(unused_imports)]
+ use std::io::Read;
+ #[allow(unused_imports)]
+ use util::ser::Lulz;
let mut last_seen_type = None;
'tlv_read: loop {
use util::ser;
last_seen_type = Some(typ.0);
// Finally, read the length and value itself:
- let length: ser::BigSize = Readable::read($stream)?;
- let mut s = ser::FixedLengthReader::new($stream, length.0);
match typ.0 {
$($reqtype => {
- $reqfield = ser::Readable::read(&mut s)?;
- if s.bytes_remain() {
- s.eat_remaining()?; // Return ShortRead if there's actually not enough bytes
- Err(DecodeError::InvalidValue)?
+ match $reqfield.fixed_len_read() {
+ Some(len) if len != 0 => {
+ let mut v = [0u8; 9];
+ let bslen = {
+ let mut w = &mut v[..];
+ ser::BigSize(len as u64).write(&mut w).unwrap();
+ 9 - w.len()
+ };
+ assert!(bslen < 9);
+ let mut r = [0; 9];
+ $stream.read_exact(&mut r[0..bslen])?;
+ if r[..bslen] != v[..bslen] {
+ Err(DecodeError::InvalidValue)?
+ }
+ $reqfield = ser::Readable::read($stream)?;
+ },
+ _ => {
+ let length: ser::BigSize = Readable::read($stream)?;
+ let mut s = ser::FixedLengthReader::new($stream, length.0);
+ $reqfield = ser::Readable::read(&mut s)?;
+ if s.bytes_remain() {
+ s.eat_remaining()?; // Return ShortRead if there's actually not enough bytes
+ Err(DecodeError::InvalidValue)?
+ }
+ }
}
},)*
$($type => {
- $field = Some(ser::Readable::read(&mut s)?);
- if s.bytes_remain() {
- s.eat_remaining()?; // Return ShortRead if there's actually not enough bytes
- Err(DecodeError::InvalidValue)?
+ match $field.lulz_len_read() {
+ Some(len) if len != 0 => {
+ let mut v = [0u8; 9];
+ let bslen = {
+ let mut w = &mut v[..];
+ ser::BigSize(len as u64).write(&mut w).unwrap();
+ 9 - w.len()
+ };
+ assert!(bslen < 9);
+ let mut r = [0; 9];
+ $stream.read_exact(&mut r[0..bslen])?;
+ if r[..bslen] != v[..bslen] {
+ Err(DecodeError::InvalidValue)?
+ }
+ $field = Some(ser::Readable::read($stream)?);
+ },
+ _ => {
+ let length: ser::BigSize = Readable::read($stream)?;
+ let mut s = ser::FixedLengthReader::new($stream, length.0);
+ $field = Some(ser::Readable::read(&mut s)?);
+ if s.bytes_remain() {
+ s.eat_remaining()?; // Return ShortRead if there's actually not enough bytes
+ Err(DecodeError::InvalidValue)?
+ }
+ }
}
},)*
x if x % 2 == 0 => {
Err(DecodeError::UnknownRequiredFeature)?
},
- _ => {},
+ _ => {
+ let length: ser::BigSize = Readable::read($stream)?;
+ let mut s = ser::FixedLengthReader::new($stream, length.0);
+ s.eat_remaining()?;
+ },
}
- s.eat_remaining()?;
}
// Make sure we got to each required type after we've read every TLV:
$({
$($field: ::util::ser::Readable::read(r)?),*
})
}
+ const FIXED_LEN: Option<usize> = Some($len);
}
}
}