Skip to content

Commit bcde6b5

Browse files
committed
util: add default_value_vec for defaults without LengthReadable
Right now, use of `default_value` requires that the struct implements `LengthReadable` itself. When trying to use `default_value` outside of LDK for `Vec<T>`, your code will run into the orphan rule because it does not own the trait `LengthReadable` or the type `Vec`. There are various ugly workarounds for this (like using `custom`), but wanting to persist a vec with a default value seems like a common enough use case to justify the change.
1 parent 1f0763f commit bcde6b5

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

lightning/src/util/ser_macros.rs

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ macro_rules! _encode_tlv {
2121
($stream: expr, $type: expr, $field: expr, (default_value, $default: expr) $(, $self: ident)?) => {
2222
$crate::_encode_tlv!($stream, $type, $field, required)
2323
};
24+
($stream: expr, $type: expr, $field: expr, (default_value_vec, $default: expr) $(, $self: ident)?) => {
25+
$crate::_encode_tlv!($stream, $type, $field, required_vec)
26+
};
2427
($stream: expr, $type: expr, $field: expr, (static_value, $value: expr) $(, $self: ident)?) => {
2528
let _ = &$field; // Ensure we "use" the $field
2629
};
@@ -200,6 +203,9 @@ macro_rules! _get_varint_length_prefixed_tlv_length {
200203
($len: expr, $type: expr, $field: expr, (default_value, $default: expr) $(, $self: ident)?) => {
201204
$crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, required)
202205
};
206+
($len: expr, $type: expr, $field: expr, (default_value_vec, $default: expr) $(, $self: ident)?) => {
207+
$crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, required_vec)
208+
};
203209
($len: expr, $type: expr, $field: expr, (static_value, $value: expr) $(, $self: ident)?) => {};
204210
($len: expr, $type: expr, $field: expr, required $(, $self: ident)?) => {
205211
BigSize($type).write(&mut $len).expect("No in-memory data may fail to serialize");
@@ -301,6 +307,14 @@ macro_rules! _check_decoded_tlv_order {
301307
$field = $default.into();
302308
}
303309
}};
310+
($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, (default_value_vec, $default: expr)) => {{
311+
#[allow(unused_comparisons)]
312+
let invalid_order =
313+
($last_seen_type.is_none() || $last_seen_type.unwrap() < $type) && $typ.0 > $type;
314+
if invalid_order {
315+
$field = Some($default);
316+
}
317+
}};
304318
($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, (static_value, $value: expr)) => {};
305319
($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, required) => {{
306320
// Note that $type may be 0 making the second comparison always false
@@ -372,6 +386,13 @@ macro_rules! _check_missing_tlv {
372386
$field = $default.into();
373387
}
374388
}};
389+
($last_seen_type: expr, $type: expr, $field: ident, (default_value_vec, $default: expr)) => {{
390+
#[allow(unused_comparisons)]
391+
let missing_req_type = $last_seen_type.is_none() || $last_seen_type.unwrap() < $type;
392+
if missing_req_type {
393+
$field = Some($default);
394+
}
395+
}};
375396
($last_seen_type: expr, $type: expr, $field: expr, (static_value, $value: expr)) => {
376397
$field = $value;
377398
};
@@ -440,6 +461,10 @@ macro_rules! _decode_tlv {
440461
($outer_reader: expr, $reader: expr, $field: ident, (default_value, $default: expr)) => {{
441462
$crate::_decode_tlv!($outer_reader, $reader, $field, required)
442463
}};
464+
($outer_reader: expr, $reader: expr, $field: ident, (default_value_vec, $default: expr)) => {{
465+
let f: $crate::util::ser::WithoutLength<Vec<_>> = $crate::util::ser::LengthReadable::read_from_fixed_length_buffer(&mut $reader)?;
466+
$field = Some(f.0);
467+
}};
443468
($outer_reader: expr, $reader: expr, $field: ident, (static_value, $value: expr)) => {{
444469
}};
445470
($outer_reader: expr, $reader: expr, $field: ident, required) => {{
@@ -854,6 +879,9 @@ macro_rules! _init_tlv_based_struct_field {
854879
($field: ident, (default_value, $default: expr)) => {
855880
$field.0.unwrap()
856881
};
882+
($field: ident, (default_value_vec, $default: expr)) => {
883+
$field.unwrap()
884+
};
857885
($field: ident, (static_value, $value: expr)) => {
858886
$field
859887
};
@@ -905,6 +933,9 @@ macro_rules! _init_tlv_field_var {
905933
($field: ident, (default_value, $default: expr)) => {
906934
let mut $field = $crate::util::ser::RequiredWrapper(None);
907935
};
936+
($field: ident, (default_value_vec, $default: expr)) => {
937+
let mut $field: Option<Vec<_>> = None;
938+
};
908939
($field: ident, (static_value, $value: expr)) => {
909940
let $field;
910941
};
@@ -1007,6 +1038,9 @@ macro_rules! _decode_and_build {
10071038
///
10081039
/// If `$fieldty` is `required`, then `$field` is a required field that is not an [`Option`] nor a [`Vec`].
10091040
/// If `$fieldty` is `(default_value, $default)`, then `$field` will be set to `$default` if not present.
1041+
/// If `$fieldty` is `(default_value_vec, $default)`, then `$field` is a [`Vec`] which will be set to `$default`
1042+
/// if not present. Elements are serialized individually without a count prefix (like `optional_vec`),
1043+
/// but unlike `optional_vec` a default value is used when the TLV is absent rather than an empty vec.
10101044
/// If `$fieldty` is `(static_value, $static)`, then `$field` will be set to `$static`.
10111045
/// If `$fieldty` is `option`, then `$field` is optional field.
10121046
/// If `$fieldty` is `upgradable_option`, then `$field` is optional and read via [`MaybeReadable`].
@@ -1019,7 +1053,7 @@ macro_rules! _decode_and_build {
10191053
/// `Some`. When reading, an optional field of type `$ty` is read, and after all TLV fields are
10201054
/// read, the `$read` closure is called with the `Option<&$ty>` value. The `$read` closure should
10211055
/// return a `Result<(), DecodeError>`. Legacy field values can be used in later
1022-
/// `default_value` or `static_value` fields by referring to the value by name.
1056+
/// `default_value`, `default_value_vec`, or `static_value` fields by referring to the value by name.
10231057
/// If `$fieldty` is `(custom, $ty, $read, $write)` then, when writing, the same behavior as
10241058
/// `legacy`, above is used. When reading, if a TLV is present, it is read as `$ty` and the
10251059
/// `$read` method is called with `Some(decoded_$ty_object)`. If no TLV is present, the field
@@ -1956,6 +1990,53 @@ mod tests {
19561990
assert_eq!(read, ExpandedField { new_field: (42, 0) });
19571991
}
19581992

1993+
#[derive(Debug, PartialEq, Eq)]
1994+
struct DefaultValueVecStruct {
1995+
items: Vec<u32>,
1996+
}
1997+
impl_writeable_tlv_based!(DefaultValueVecStruct, {
1998+
(1, items, (default_value_vec, Vec::new())),
1999+
});
2000+
2001+
#[test]
2002+
fn test_default_value_vec() {
2003+
// Non-empty vec round-trips correctly.
2004+
let instance = DefaultValueVecStruct { items: vec![1, 2, 3] };
2005+
let encoded = instance.encode();
2006+
let decoded: DefaultValueVecStruct = Readable::read(&mut &encoded[..]).unwrap();
2007+
assert_eq!(decoded, instance);
2008+
2009+
// Empty TLV stream falls back to the default (empty vec).
2010+
let empty_encoded = <Vec<u8>>::from_hex("00").unwrap(); // zero-length TLV stream
2011+
let decoded: DefaultValueVecStruct = Readable::read(&mut &empty_encoded[..]).unwrap();
2012+
assert_eq!(decoded, DefaultValueVecStruct { items: Vec::new() });
2013+
}
2014+
2015+
#[derive(Debug, PartialEq, Eq)]
2016+
struct LegacyToVecStruct {
2017+
new_items: Vec<u32>,
2018+
}
2019+
impl_writeable_tlv_based!(LegacyToVecStruct, {
2020+
(0, old_item, (legacy, u32, |_| Ok(()),
2021+
|us: &LegacyToVecStruct| us.new_items.first().copied())),
2022+
(1, new_items, (default_value_vec,
2023+
old_item.map(|v| vec![v]).unwrap_or_default())),
2024+
});
2025+
2026+
#[test]
2027+
fn test_default_value_vec_with_legacy_fallback() {
2028+
// New format: round-trips via the new TLV.
2029+
let instance = LegacyToVecStruct { new_items: vec![10, 20, 30] };
2030+
let encoded = instance.encode();
2031+
let decoded: LegacyToVecStruct = Readable::read(&mut &encoded[..]).unwrap();
2032+
assert_eq!(decoded, instance);
2033+
2034+
// Old format: only the legacy type-0 field is present, falls back via default expression.
2035+
let old_encoded = <Vec<u8>>::from_hex("0600040000002a").unwrap(); // TLV len 6, type 0, len 4, value 42u32
2036+
let decoded: LegacyToVecStruct = Readable::read(&mut &old_encoded[..]).unwrap();
2037+
assert_eq!(decoded, LegacyToVecStruct { new_items: vec![42] });
2038+
}
2039+
19592040
#[test]
19602041
fn required_vec_with_encoding() {
19612042
// Ensure that serializing a required vec with a specified encoding will survive a ser round

0 commit comments

Comments
 (0)