// `Ok(false)` if the message type is unknown, and `Err(DecodeError)` if parsing fails.
macro_rules! decode_tlv_stream {
($stream: expr, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}
+ $(, $decode_custom_tlv: expr)?) => { {
+ let rewind = |_, _| { unreachable!() };
+ use core::ops::RangeBounds;
+ decode_tlv_stream_range!(
+ $stream, .., rewind, {$(($type, $field, $fieldty)),*} $(, $decode_custom_tlv)?
+ );
+ } }
+}
+
+macro_rules! decode_tlv_stream_range {
+ ($stream: expr, $range: expr, $rewind: ident, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}
$(, $decode_custom_tlv: expr)?) => { {
use $crate::ln::msgs::DecodeError;
let mut last_seen_type: Option<u64> = None;
// UnexpectedEof. This should in every case be largely cosmetic, but its nice to
// pass the TLV test vectors exactly, which requre this distinction.
let mut tracking_reader = ser::ReadTrackingReader::new(&mut stream_ref);
- match $crate::util::ser::Readable::read(&mut tracking_reader) {
+ match <$crate::util::ser::BigSize as $crate::util::ser::Readable>::read(&mut tracking_reader) {
Err(DecodeError::ShortRead) => {
if !tracking_reader.have_read {
break 'tlv_read;
}
},
Err(e) => return Err(e),
- Ok(t) => t,
+ Ok(t) => if $range.contains(&t.0) { t } else {
+ drop(tracking_reader);
+
+ // Assumes the type id is minimally encoded, which is enforced on read.
+ use $crate::util::ser::Writeable;
+ let bytes_read = t.serialized_length();
+ $rewind(stream_ref, bytes_read);
+ break 'tlv_read;
+ },
}
};
};
}
+macro_rules! init_and_read_tlv_fields {
+ ($reader: ident, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}) => {
+ $(
+ init_tlv_field_var!($field, $fieldty);
+ )*
+
+ read_tlv_fields!($reader, {
+ $(($type, $field, $fieldty)),*
+ });
+ }
+}
+
/// Implements Readable/Writeable for a struct storing it as a set of TLVs
/// If $fieldty is `required`, then $field is a required field that is not an Option nor a Vec.
/// If $fieldty is `option`, then $field is optional field.
impl $crate::util::ser::Readable for $st {
fn read<R: $crate::io::Read>(reader: &mut R) -> Result<Self, $crate::ln::msgs::DecodeError> {
- $(
- init_tlv_field_var!($field, $fieldty);
- )*
- read_tlv_fields!(reader, {
+ init_and_read_tlv_fields!(reader, {
$(($type, $field, $fieldty)),*
});
Ok(Self {
/// [`Readable`]: crate::util::ser::Readable
/// [`Writeable`]: crate::util::ser::Writeable
macro_rules! tlv_stream {
- ($name:ident, $nameref:ident, {
+ ($name:ident, $nameref:ident, $range:expr, {
$(($type:expr, $field:ident : $fieldty:tt)),* $(,)*
}) => {
#[derive(Debug)]
}
}
- impl $crate::util::ser::Readable for $name {
- fn read<R: $crate::io::Read>(reader: &mut R) -> Result<Self, $crate::ln::msgs::DecodeError> {
+ impl $crate::util::ser::SeekReadable for $name {
+ fn read<R: $crate::io::Read + $crate::io::Seek>(reader: &mut R) -> Result<Self, $crate::ln::msgs::DecodeError> {
$(
init_tlv_field_var!($field, option);
)*
- decode_tlv_stream!(reader, {
+ let rewind = |cursor: &mut R, offset: usize| {
+ cursor.seek($crate::io::SeekFrom::Current(-(offset as i64))).expect("");
+ };
+ decode_tlv_stream_range!(reader, $range, rewind, {
$(($type, $field, (option, encoding: $fieldty))),*
});
// Because read_tlv_fields creates a labeled loop, we cannot call it twice
// in the same function body. Instead, we define a closure and call it.
let f = || {
- $(
- init_tlv_field_var!($field, $fieldty);
- )*
- read_tlv_fields!(reader, {
+ init_and_read_tlv_fields!(reader, {
$(($type, $field, $fieldty)),*
});
Ok(Some($st::$variant_name {
// Because read_tlv_fields creates a labeled loop, we cannot call it twice
// in the same function body. Instead, we define a closure and call it.
let f = || {
- $(
- init_tlv_field_var!($field, $fieldty);
- )*
- read_tlv_fields!(reader, {
+ init_and_read_tlv_fields!(reader, {
$(($type, $field, $fieldty)),*
});
Ok($st::$variant_name {