use beve::Value;
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum Payload {
Telemetry(Vec<f64>),
MetaOnly(Meta),
Snapshot { label: String, counters: Vec<u32> },
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum Meta {
Codes(Vec<u32>),
}
fn has_empty_array(value: &Value) -> bool {
match value {
Value::Array(items) => items.is_empty() || items.iter().any(has_empty_array),
Value::Object(entries) => entries.values().any(has_empty_array),
_ => false,
}
}
fn assert_empty_collection_survives<T>(value: &T)
where
T: Serialize + serde::de::DeserializeOwned + PartialEq + std::fmt::Debug,
{
let bytes = beve::to_vec(value).expect("encode");
assert!(
!bytes.is_empty(),
"an empty collection still occupies bytes"
);
beve::validate_slice(&bytes)
.unwrap_or_else(|e| panic!("encoding of {value:?} failed validation: {e:?}"));
let decoded: T =
beve::from_slice(&bytes).unwrap_or_else(|e| panic!("decoding {value:?} back: {e:?}"));
assert_eq!(&decoded, value);
let as_value: Value = beve::from_slice(&bytes).expect("decode as Value");
assert!(
has_empty_array(&as_value),
"no empty array in the decoded document for {value:?}; the header is missing"
);
}
#[test]
fn an_empty_sequence_in_a_newtype_variant_keeps_its_header() {
assert_empty_collection_survives(&Payload::Telemetry(Vec::new()));
}
#[test]
fn an_empty_sequence_in_a_nested_enum_keeps_its_header() {
assert_empty_collection_survives(&Payload::MetaOnly(Meta::Codes(Vec::new())));
}
#[test]
fn an_empty_sequence_in_a_struct_variant_keeps_its_header() {
assert_empty_collection_survives(&Payload::Snapshot {
label: "a".to_string(),
counters: Vec::new(),
});
}