Skip to content

Commit 1a24f8f

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 1a24f8f

File tree

1 file changed

+90
-1
lines changed

1 file changed

+90
-1
lines changed

lightning/src/util/ser_macros.rs

Lines changed: 90 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,15 @@ 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+
// Note that $type may be 0 making the second comparison always false
312+
#[allow(unused_comparisons)]
313+
let invalid_order =
314+
($last_seen_type.is_none() || $last_seen_type.unwrap() < $type) && $typ.0 > $type;
315+
if invalid_order {
316+
$field = Some($default);
317+
}
318+
}};
304319
($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, (static_value, $value: expr)) => {};
305320
($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, required) => {{
306321
// Note that $type may be 0 making the second comparison always false
@@ -372,6 +387,14 @@ macro_rules! _check_missing_tlv {
372387
$field = $default.into();
373388
}
374389
}};
390+
($last_seen_type: expr, $type: expr, $field: ident, (default_value_vec, $default: expr)) => {{
391+
// Note that $type may be 0 making the second comparison always false
392+
#[allow(unused_comparisons)]
393+
let missing_req_type = $last_seen_type.is_none() || $last_seen_type.unwrap() < $type;
394+
if missing_req_type {
395+
$field = Some($default);
396+
}
397+
}};
375398
($last_seen_type: expr, $type: expr, $field: expr, (static_value, $value: expr)) => {
376399
$field = $value;
377400
};
@@ -440,6 +463,10 @@ macro_rules! _decode_tlv {
440463
($outer_reader: expr, $reader: expr, $field: ident, (default_value, $default: expr)) => {{
441464
$crate::_decode_tlv!($outer_reader, $reader, $field, required)
442465
}};
466+
($outer_reader: expr, $reader: expr, $field: ident, (default_value_vec, $default: expr)) => {{
467+
let f: $crate::util::ser::WithoutLength<Vec<_>> = $crate::util::ser::LengthReadable::read_from_fixed_length_buffer(&mut $reader)?;
468+
$field = Some(f.0);
469+
}};
443470
($outer_reader: expr, $reader: expr, $field: ident, (static_value, $value: expr)) => {{
444471
}};
445472
($outer_reader: expr, $reader: expr, $field: ident, required) => {{
@@ -854,6 +881,9 @@ macro_rules! _init_tlv_based_struct_field {
854881
($field: ident, (default_value, $default: expr)) => {
855882
$field.0.unwrap()
856883
};
884+
($field: ident, (default_value_vec, $default: expr)) => {
885+
$field.unwrap()
886+
};
857887
($field: ident, (static_value, $value: expr)) => {
858888
$field
859889
};
@@ -905,6 +935,9 @@ macro_rules! _init_tlv_field_var {
905935
($field: ident, (default_value, $default: expr)) => {
906936
let mut $field = $crate::util::ser::RequiredWrapper(None);
907937
};
938+
($field: ident, (default_value_vec, $default: expr)) => {
939+
let mut $field: Option<Vec<_>> = None;
940+
};
908941
($field: ident, (static_value, $value: expr)) => {
909942
let $field;
910943
};
@@ -1007,6 +1040,9 @@ macro_rules! _decode_and_build {
10071040
///
10081041
/// If `$fieldty` is `required`, then `$field` is a required field that is not an [`Option`] nor a [`Vec`].
10091042
/// If `$fieldty` is `(default_value, $default)`, then `$field` will be set to `$default` if not present.
1043+
/// If `$fieldty` is `(default_value_vec, $default)`, then `$field` is a [`Vec`] which will be set to `$default`
1044+
/// if not present. Elements are serialized individually without a count prefix (like `required_vec`).
1045+
/// The TLV is always written, even if the vec is empty (matching `default_value` behavior).
10101046
/// If `$fieldty` is `(static_value, $static)`, then `$field` will be set to `$static`.
10111047
/// If `$fieldty` is `option`, then `$field` is optional field.
10121048
/// If `$fieldty` is `upgradable_option`, then `$field` is optional and read via [`MaybeReadable`].
@@ -1019,7 +1055,7 @@ macro_rules! _decode_and_build {
10191055
/// `Some`. When reading, an optional field of type `$ty` is read, and after all TLV fields are
10201056
/// read, the `$read` closure is called with the `Option<&$ty>` value. The `$read` closure should
10211057
/// 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.
1058+
/// `default_value`, `default_value_vec`, or `static_value` fields by referring to the value by name.
10231059
/// If `$fieldty` is `(custom, $ty, $read, $write)` then, when writing, the same behavior as
10241060
/// `legacy`, above is used. When reading, if a TLV is present, it is read as `$ty` and the
10251061
/// `$read` method is called with `Some(decoded_$ty_object)`. If no TLV is present, the field
@@ -1956,6 +1992,59 @@ mod tests {
19561992
assert_eq!(read, ExpandedField { new_field: (42, 0) });
19571993
}
19581994

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

0 commit comments

Comments
 (0)