Skip to content

Commit 4c63583

Browse files
committed
Add an optional_vec TLV format which makes sense, unlike vec_type
`vec_type` is confusing - it is happy to have a missing entry, "reading" an empty `Vec` instead, but always writes something, making a serialization round-trip different. This is a problem for writing a new `Vec` which is backwards-incompatible, but only if filled in. In that case we'd really like the same read behavior, but not write anything if the `Vec` is empty. Here we introduce such semantics via a new `optional_vec` TLV format.
1 parent 23c1b46 commit 4c63583

File tree

1 file changed

+29
-3
lines changed

1 file changed

+29
-3
lines changed

lightning/src/util/ser_macros.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ macro_rules! _encode_tlv {
3939
field.write($stream)?;
4040
}
4141
};
42+
($stream: expr, $type: expr, $field: expr, optional_vec) => {
43+
if !$field.is_empty() {
44+
$crate::_encode_tlv!($stream, $type, vec_type);
45+
}
46+
};
4247
($stream: expr, $type: expr, $field: expr, upgradable_required) => {
4348
$crate::_encode_tlv!($stream, $type, $field, required);
4449
};
@@ -165,6 +170,11 @@ macro_rules! _get_varint_length_prefixed_tlv_length {
165170
$len.0 += field_len;
166171
}
167172
};
173+
($len: expr, $type: expr, $field: expr, optional_vec) => {
174+
if !$field.is_empty() {
175+
$crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, vec_type);
176+
}
177+
}
168178
($len: expr, $type: expr, $field: expr, (option: $trait: ident $(, $read_arg: expr)?)) => {
169179
$crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, option);
170180
};
@@ -226,6 +236,9 @@ macro_rules! _check_decoded_tlv_order {
226236
($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, vec_type) => {{
227237
// no-op
228238
}};
239+
($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, optional_vec) => {{
240+
// no-op
241+
}};
229242
($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, upgradable_required) => {{
230243
_check_decoded_tlv_order!($last_seen_type, $typ, $type, $field, required)
231244
}};
@@ -271,6 +284,9 @@ macro_rules! _check_missing_tlv {
271284
($last_seen_type: expr, $type: expr, $field: ident, option) => {{
272285
// no-op
273286
}};
287+
($last_seen_type: expr, $type: expr, $field: ident, optional_vec) => {{
288+
// no-op
289+
}};
274290
($last_seen_type: expr, $type: expr, $field: ident, upgradable_required) => {{
275291
_check_missing_tlv!($last_seen_type, $type, $field, required)
276292
}};
@@ -308,6 +324,9 @@ macro_rules! _decode_tlv {
308324
($reader: expr, $field: ident, option) => {{
309325
$field = Some($crate::util::ser::Readable::read(&mut $reader)?);
310326
}};
327+
($reader: expr, $field: ident, optional_vec) => {{
328+
$crate::_decode_tlv!($reader, $field, vec_type);
329+
}};
311330
// `upgradable_required` indicates we're reading a required TLV that may have been upgraded
312331
// without backwards compat. We'll error if the field is missing, and return `Ok(None)` if the
313332
// field is present but we can no longer understand it.
@@ -675,6 +694,9 @@ macro_rules! _init_tlv_based_struct_field {
675694
($field: ident, vec_type) => {
676695
$field.unwrap()
677696
};
697+
($field: ident, optional_vec) => {
698+
$field.unwrap()
699+
};
678700
}
679701

680702
/// Initializes the variable we are going to read the TLV into.
@@ -701,6 +723,9 @@ macro_rules! _init_tlv_field_var {
701723
($field: ident, option) => {
702724
let mut $field = None;
703725
};
726+
($field: ident, optional_vec) => {
727+
let mut $field = Some(Vec::new());
728+
};
704729
($field: ident, (option: $trait: ident $(, $read_arg: expr)?)) => {
705730
$crate::_init_tlv_field_var!($field, option);
706731
};
@@ -733,7 +758,8 @@ macro_rules! _init_and_read_tlv_fields {
733758
/// If `$fieldty` is `required`, then `$field` is a required field that is not an [`Option`] nor a [`Vec`].
734759
/// If `$fieldty` is `(default_value, $default)`, then `$field` will be set to `$default` if not present.
735760
/// If `$fieldty` is `option`, then `$field` is optional field.
736-
/// If `$fieldty` is `vec_type`, then `$field` is a [`Vec`], which needs to have its individual elements serialized.
761+
/// If `$fieldty` is `optional_vec`, then `$field` is a [`Vec`], which needs to have its individual elements serialized.
762+
/// Note that for `optional_vec` no bytes are written if the vec is empty
737763
///
738764
/// For example,
739765
/// ```
@@ -749,7 +775,7 @@ macro_rules! _init_and_read_tlv_fields {
749775
/// (0, tlv_integer, required),
750776
/// (1, tlv_default_integer, (default_value, 7)),
751777
/// (2, tlv_optional_integer, option),
752-
/// (3, tlv_vec_type_integer, vec_type),
778+
/// (3, tlv_vec_type_integer, optional_vec),
753779
/// });
754780
/// ```
755781
///
@@ -907,7 +933,7 @@ macro_rules! _impl_writeable_tlv_based_enum_common {
907933
/// ```ignore
908934
/// impl_writeable_tlv_based_enum!(EnumName,
909935
/// (0, StructVariantA) => {(0, required_variant_field, required), (1, optional_variant_field, option)},
910-
/// (1, StructVariantB) => {(0, variant_field_a, required), (1, variant_field_b, required), (2, variant_vec_field, vec_type)};
936+
/// (1, StructVariantB) => {(0, variant_field_a, required), (1, variant_field_b, required), (2, variant_vec_field, optional_vec)};
911937
/// (2, TupleVariantA), (3, TupleVariantB),
912938
/// );
913939
/// ```

0 commit comments

Comments
 (0)