#![allow(dead_code)]
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashSet};
use revision::{
DeserializeRevisioned, Error, MapWalker, SeqWalker, SkipRevisioned, WalkRevisioned, revisioned,
to_vec,
};
#[test]
fn primitive_leaf_decode_matches_deserialize() {
let bytes = to_vec(&42u64).unwrap();
let mut r = bytes.as_slice();
let walker = u64::walk_revisioned(&mut r).unwrap();
let decoded = walker.decode().unwrap();
assert_eq!(decoded, 42);
assert!(r.is_empty(), "walker should consume entire encoded value");
let mut r2 = bytes.as_slice();
let direct = u64::deserialize_revisioned(&mut r2).unwrap();
assert_eq!(decoded, direct);
}
#[test]
fn primitive_leaf_skip_matches_skip_revisioned() {
let bytes = to_vec(&u128::MAX).unwrap();
let mut r = bytes.as_slice();
let walker = u128::walk_revisioned(&mut r).unwrap();
walker.skip().unwrap();
assert!(r.is_empty(), "walker should consume entire encoded value");
let mut r2 = bytes.as_slice();
u128::skip_revisioned(&mut r2).unwrap();
assert!(r2.is_empty());
}
#[test]
fn option_walker_some_decode_skip_walk() {
let bytes = to_vec(&Some(7u32)).unwrap();
let mut r = bytes.as_slice();
let walker = <Option<u32>>::walk_revisioned(&mut r).unwrap();
assert!(walker.is_some());
assert_eq!(walker.decode().unwrap(), Some(7));
assert!(r.is_empty());
let mut r = bytes.as_slice();
let walker = <Option<u32>>::walk_revisioned(&mut r).unwrap();
walker.skip().unwrap();
assert!(r.is_empty());
let mut r = bytes.as_slice();
let walker = <Option<u32>>::walk_revisioned(&mut r).unwrap();
let inner = walker.into_some().unwrap();
assert_eq!(inner.decode().unwrap(), 7);
assert!(r.is_empty());
}
#[test]
fn option_walker_none_skip_does_not_overread() {
let bytes = to_vec(&None::<u32>).unwrap();
let mut r = bytes.as_slice();
let walker = <Option<u32>>::walk_revisioned(&mut r).unwrap();
assert!(walker.is_none());
walker.skip().unwrap();
assert!(r.is_empty());
}
#[test]
fn seq_walker_iterates_decode_skip_mix() {
let v: Vec<String> =
vec!["one".into(), "two".into(), "three".into(), "four".into(), "five".into()];
let bytes = to_vec(&v).unwrap();
let mut r = bytes.as_slice();
let mut walker: SeqWalker<String, _> = <Vec<String>>::walk_revisioned(&mut r).unwrap();
assert_eq!(walker.remaining(), 5);
let mut decoded = Vec::new();
for _ in 0..3 {
let item = walker.next_item().expect("item available");
decoded.push(item.decode().unwrap());
}
assert_eq!(decoded, vec![String::from("one"), String::from("two"), String::from("three")]);
assert_eq!(walker.remaining(), 2);
walker.skip_remaining().unwrap();
assert!(r.is_empty(), "walker should fully consume the seq payload");
}
#[test]
fn map_walker_full_iteration_matches_deserialize() {
let mut map: BTreeMap<String, u32> = BTreeMap::new();
map.insert("alpha".into(), 1);
map.insert("beta".into(), 2);
map.insert("gamma".into(), 3);
let bytes = to_vec(&map).unwrap();
let mut r = bytes.as_slice();
let mut walker: MapWalker<String, u32, _> =
<BTreeMap<String, u32>>::walk_revisioned(&mut r).unwrap();
assert_eq!(walker.remaining(), 3);
let mut collected: BTreeMap<String, u32> = BTreeMap::new();
while let Some(entry) = walker.next_entry() {
let (k, v) = entry.decode_pair().unwrap();
collected.insert(k, v);
}
assert_eq!(collected, map);
assert!(r.is_empty());
}
#[test]
fn map_walker_skip_value_for_unwanted_keys() {
let mut map: BTreeMap<String, u32> = BTreeMap::new();
map.insert("a".into(), 1);
map.insert("b".into(), 2);
map.insert("c".into(), 3);
let bytes = to_vec(&map).unwrap();
let mut r = bytes.as_slice();
let mut walker: MapWalker<String, u32, _> =
<BTreeMap<String, u32>>::walk_revisioned(&mut r).unwrap();
let mut found = None;
while let Some(mut entry) = walker.next_entry() {
let key = entry.decode_key().unwrap();
if key == "b" {
found = Some(entry.decode_value().unwrap());
} else {
entry.skip_value().unwrap();
}
}
assert_eq!(found, Some(2));
assert!(r.is_empty(), "all entries must be consumed");
}
#[test]
fn map_walker_find_by_key_consumes_after_match() {
let mut map: BTreeMap<String, u32> = BTreeMap::new();
map.insert("alpha".into(), 1);
map.insert("beta".into(), 2);
map.insert("delta".into(), 3);
map.insert("epsilon".into(), 4);
let bytes = to_vec(&map).unwrap();
let mut r = bytes.as_slice();
let walker: MapWalker<String, u32, _> =
<BTreeMap<String, u32>>::walk_revisioned(&mut r).unwrap();
let needle = "delta";
let handle = walker
.find(|k: &String| {
let k = k.as_str();
k.cmp(needle)
})
.unwrap();
let handle = handle.expect("delta should be present");
let value: u32 = handle.decode().unwrap();
assert_eq!(value, 3);
let mut r2 = bytes.as_slice();
<BTreeMap<String, u32>>::skip_revisioned(&mut r2).unwrap();
assert!(r2.is_empty());
}
#[test]
fn map_walker_find_returns_none_consumes_all() {
let mut map: BTreeMap<String, u32> = BTreeMap::new();
map.insert("alpha".into(), 1);
map.insert("beta".into(), 2);
let bytes = to_vec(&map).unwrap();
let mut r = bytes.as_slice();
let walker: MapWalker<String, u32, _> =
<BTreeMap<String, u32>>::walk_revisioned(&mut r).unwrap();
let result = walker.find(|k: &String| k.as_str().cmp("zzz")).unwrap();
assert!(result.is_none());
assert!(r.is_empty(), "no-match find should consume entire map");
}
#[revisioned(revision = 1)]
#[derive(Debug, Clone, PartialEq)]
struct Document {
name: String,
count: u32,
}
#[test]
fn derive_struct_walker_decodes_each_field_in_order() {
let doc = Document {
name: "hello".into(),
count: 42,
};
let bytes = to_vec(&doc).unwrap();
let mut r = bytes.as_slice();
let mut walker = Document::walk_revisioned(&mut r).unwrap();
assert_eq!(walker.revision(), 1);
let name = walker.decode_name().unwrap();
let count = walker.decode_count().unwrap();
assert_eq!(name, doc.name);
assert_eq!(count, doc.count);
assert!(r.is_empty());
}
#[test]
fn derive_struct_walker_skip_field_skips_correctly() {
let doc = Document {
name: "skip-me".into(),
count: 99,
};
let bytes = to_vec(&doc).unwrap();
let mut r = bytes.as_slice();
let mut walker = Document::walk_revisioned(&mut r).unwrap();
walker.skip_name().unwrap();
let count = walker.decode_count().unwrap();
assert_eq!(count, 99);
assert!(r.is_empty());
}
#[test]
fn derive_struct_walker_field_table_is_emitted() {
assert_eq!(Document::walk_revisioned_field_names(1), &["name", "count"]);
}
#[revisioned(revision = 1)]
#[derive(Debug, PartialEq)]
enum Shape {
Square(u32),
Rectangle {
w: u32,
h: u32,
},
Circle(u32),
}
#[test]
fn derive_enum_walker_exposes_discriminant() {
let s = Shape::Circle(7);
let bytes = to_vec(&s).unwrap();
let mut r = bytes.as_slice();
let walker = Shape::walk_revisioned(&mut r).unwrap();
assert_eq!(walker.revision(), 1);
let disc = walker.discriminant();
let name = Shape::walk_revisioned_variant_name(1, disc);
assert_eq!(name, Some("Circle"));
assert!(walker.is_circle());
let inner = walker.into_circle().unwrap();
let payload = inner.decode().unwrap();
assert_eq!(payload, 7);
assert!(r.is_empty());
}
#[test]
fn derive_enum_variant_table_is_emitted() {
let table = Shape::walk_revisioned_variant_table(1);
let names: Vec<&'static str> = table.iter().map(|(n, _)| *n).collect();
assert_eq!(names, vec!["Square", "Rectangle", "Circle"]);
}
#[test]
fn derive_enum_walker_skip_matches_skip_revisioned() {
let s = Shape::Square(13);
let bytes = to_vec(&s).unwrap();
let mut r = bytes.as_slice();
let walker = Shape::walk_revisioned(&mut r).unwrap();
assert!(walker.is_square());
let inner = walker.into_square().unwrap();
inner.skip().unwrap();
assert!(r.is_empty());
let mut r2 = bytes.as_slice();
Shape::skip_revisioned(&mut r2).unwrap();
assert!(r2.is_empty());
}
#[revisioned(revision = 1)]
#[derive(Debug)]
struct Outer {
header: u16,
body: BTreeMap<String, u32>,
}
#[test]
fn struct_walker_walks_into_nested_map() {
let mut body = BTreeMap::new();
body.insert("alpha".into(), 10u32);
body.insert("beta".into(), 20);
body.insert("gamma".into(), 30);
let outer = Outer {
header: 7,
body,
};
let bytes = to_vec(&outer).unwrap();
let mut r = bytes.as_slice();
let mut walker = Outer::walk_revisioned(&mut r).unwrap();
let header = walker.decode_header().unwrap();
assert_eq!(header, 7);
let collected: BTreeMap<String, u32> = {
let mut map_walker = walker.walk_body().unwrap();
let mut acc = BTreeMap::new();
while let Some(entry) = map_walker.next_entry() {
let (k, v) = entry.decode_pair().unwrap();
acc.insert(k, v);
}
acc
};
assert_eq!(collected.len(), 3);
assert_eq!(collected["alpha"], 10);
assert_eq!(collected["beta"], 20);
assert_eq!(collected["gamma"], 30);
assert!(r.is_empty());
}
#[revisioned(revision = 1)]
#[derive(Debug)]
struct OldShape {
kind: u8,
}
#[revisioned(revision = 2)]
#[derive(Debug)]
struct NewShape {
kind: u8,
#[revision(start = 2)]
flags: u8,
}
#[test]
fn walker_accepts_older_wire_revision_with_default_for_added_field() {
let old = OldShape {
kind: 3,
};
let bytes = to_vec(&old).unwrap();
let mut r = bytes.as_slice();
let mut walker = NewShape::walk_revisioned(&mut r).unwrap();
assert_eq!(walker.revision(), 1);
let kind = walker.decode_kind().unwrap();
let flags = walker.decode_flags().unwrap();
assert_eq!(kind, 3);
assert_eq!(flags, 0); assert!(r.is_empty());
}
#[test]
fn walker_rejects_invalid_wire_revision() {
let mut bytes = Vec::new();
use revision::SerializeRevisioned;
99u16.serialize_revisioned(&mut bytes).unwrap();
bytes.push(0u8);
let mut r = bytes.as_slice();
let res = NewShape::walk_revisioned(&mut r);
assert!(matches!(res, Err(Error::Deserialize(_))));
}
#[revisioned(revision = 1)]
#[derive(Debug, Clone, PartialEq)]
struct ConvertedFooV1 {
width: u32,
}
#[revisioned(revision = 2)]
#[derive(Debug, PartialEq)]
struct ConvertedFoo {
#[revision(end = 2, convert_fn = "convert_width")]
width_old: u32,
#[revision(start = 2)]
width: u32,
#[revision(start = 2)]
height: u32,
}
impl ConvertedFoo {
fn convert_width(&mut self, _rev: u16, value: u32) -> Result<(), revision::Error> {
self.width = value * 10;
self.height = value + 1;
Ok(())
}
}
#[test]
fn walker_materialises_for_convert_fn_type_at_older_revision() {
let v1 = ConvertedFooV1 {
width: 5,
};
let bytes = to_vec(&v1).unwrap();
let mut r = bytes.as_slice();
let mut walker = ConvertedFoo::walk_revisioned(&mut r).unwrap();
assert_eq!(walker.revision(), 2);
let width = walker.decode_width().unwrap();
let height = walker.decode_height().unwrap();
assert_eq!(width, 50); assert_eq!(height, 6); assert!(r.is_empty());
}
#[test]
fn walker_materialised_walk_field_errors_with_useful_message() {
let v1 = ConvertedFooV1 {
width: 5,
};
let bytes = to_vec(&v1).unwrap();
let mut r = bytes.as_slice();
let mut walker = ConvertedFoo::walk_revisioned(&mut r).unwrap();
let res = walker.walk_width();
assert!(matches!(res, Err(Error::Conversion(_))));
let res = walker.into_walk_width();
assert!(matches!(res, Err(Error::Conversion(_))));
}
#[test]
fn walker_current_rev_path_for_convert_fn_type_uses_wire_mode() {
let v2 = ConvertedFoo {
width: 42,
height: 99,
};
let mut bytes = Vec::new();
use revision::SerializeRevisioned;
v2.serialize_revisioned(&mut bytes).unwrap();
let mut r = bytes.as_slice();
let mut walker = ConvertedFoo::walk_revisioned(&mut r).unwrap();
assert_eq!(walker.revision(), 2);
let width = walker.decode_width().unwrap();
let height = walker.decode_height().unwrap();
assert_eq!(width, 42);
assert_eq!(height, 99);
assert!(r.is_empty());
}
#[test]
fn deserialize_still_handles_older_wire_revision() {
let old = OldShape {
kind: 3,
};
let bytes = to_vec(&old).unwrap();
let mut r = bytes.as_slice();
let parsed = NewShape::deserialize_revisioned(&mut r).unwrap();
assert_eq!(parsed.kind, 3);
assert_eq!(parsed.flags, 0);
}
#[test]
fn leaf_walker_with_bytes_matches_decode_for_string() {
let s = "hello, walker".to_string();
let bytes = to_vec(&s).unwrap();
let mut r = bytes.as_slice();
let walker = String::walk_revisioned(&mut r).unwrap();
let observed = walker.with_bytes(|key| key.to_vec()).unwrap();
assert_eq!(observed.as_slice(), s.as_bytes());
assert!(r.is_empty(), "with_bytes should consume the whole leaf");
let mut r2 = bytes.as_slice();
let decoded = String::deserialize_revisioned(&mut r2).unwrap();
assert_eq!(decoded, s);
}
#[test]
fn leaf_walker_with_bytes_matches_decode_for_pathbuf() {
use std::path::PathBuf;
let p = PathBuf::from("/etc/passwd");
let bytes = to_vec(&p).unwrap();
let mut r = bytes.as_slice();
let walker = PathBuf::walk_revisioned(&mut r).unwrap();
let observed = walker.with_bytes(|raw| raw.to_vec()).unwrap();
assert_eq!(observed.as_slice(), p.to_string_lossy().as_bytes());
assert!(r.is_empty());
}
#[test]
fn map_walker_find_bytes_matches_find_for_string_keys() {
let mut map: BTreeMap<String, u32> = BTreeMap::new();
for (k, v) in [("alpha", 1u32), ("beta", 2), ("delta", 3), ("epsilon", 4)] {
map.insert(k.into(), v);
}
let bytes = to_vec(&map).unwrap();
let mut r1 = bytes.as_slice();
let walker_typed: MapWalker<String, u32, _> =
<BTreeMap<String, u32>>::walk_revisioned(&mut r1).unwrap();
let typed = walker_typed
.find(|k: &String| k.as_str().cmp("delta"))
.unwrap()
.expect("delta should be present")
.decode()
.unwrap();
let mut r2 = bytes.as_slice();
let walker_bytes: MapWalker<String, u32, _> =
<BTreeMap<String, u32>>::walk_revisioned(&mut r2).unwrap();
let bytewise = walker_bytes
.find_bytes(|k| k.cmp(b"delta".as_slice()))
.unwrap()
.expect("delta should be present")
.decode()
.unwrap();
assert_eq!(typed, bytewise);
}
#[test]
fn map_walker_find_bytes_returns_none_consumes_all() {
let mut map: BTreeMap<String, u32> = BTreeMap::new();
map.insert("alpha".into(), 1);
map.insert("beta".into(), 2);
let bytes = to_vec(&map).unwrap();
let mut r = bytes.as_slice();
let walker: MapWalker<String, u32, _> =
<BTreeMap<String, u32>>::walk_revisioned(&mut r).unwrap();
let result = walker.find_bytes(|k| k.cmp(b"zzz".as_slice())).unwrap();
assert!(result.is_none());
assert!(r.is_empty(), "no-match find_bytes should consume entire map");
}
#[test]
fn map_entry_with_key_bytes_zero_copy_iteration() {
let mut map: BTreeMap<String, u32> = BTreeMap::new();
map.insert("alpha".into(), 1);
map.insert("beta".into(), 2);
map.insert("gamma".into(), 3);
let bytes = to_vec(&map).unwrap();
let mut r = bytes.as_slice();
let mut walker: MapWalker<String, u32, _> =
<BTreeMap<String, u32>>::walk_revisioned(&mut r).unwrap();
let mut found_beta = None;
while let Some(mut entry) = walker.next_entry() {
let is_target = entry.with_key_bytes(|k| k == b"beta").unwrap();
if is_target {
found_beta = Some(entry.decode_value().unwrap());
} else {
entry.skip_value().unwrap();
}
}
assert_eq!(found_beta, Some(2));
assert!(r.is_empty(), "map walker should consume the entire map");
}
#[test]
fn map_entry_with_value_bytes_for_byte_values() {
let mut map: BTreeMap<String, Vec<u8>> = BTreeMap::new();
map.insert("a".into(), b"first-value".to_vec());
map.insert("b".into(), b"second-value-longer".to_vec());
let bytes = to_vec(&map).unwrap();
let mut r = bytes.as_slice();
let mut walker: MapWalker<String, Vec<u8>, _> =
<BTreeMap<String, Vec<u8>>>::walk_revisioned(&mut r).unwrap();
let mut second_observed: Option<Vec<u8>> = None;
while let Some(mut entry) = walker.next_entry() {
let key = entry.decode_key().unwrap();
if key == "b" {
second_observed = Some(entry.with_value_bytes(|raw| raw.to_vec()).unwrap());
} else {
entry.skip_value().unwrap();
}
}
assert_eq!(second_observed.as_deref(), Some(b"second-value-longer".as_slice()));
assert!(r.is_empty());
}
#[test]
fn seq_item_with_bytes_for_string_seq() {
let v: Vec<String> = vec!["alpha".into(), "beta".into(), "gamma".into(), "delta".into()];
let bytes = to_vec(&v).unwrap();
let mut r = bytes.as_slice();
let mut walker: SeqWalker<String, _> = <Vec<String>>::walk_revisioned(&mut r).unwrap();
assert_eq!(walker.remaining(), 4);
let first = walker.next_item().unwrap().with_bytes(|b| b.to_vec()).unwrap();
let second = walker.next_item().unwrap().decode().unwrap();
walker.next_item().unwrap().skip().unwrap();
let fourth_starts_with_d =
walker.next_item().unwrap().with_bytes(|b| b.starts_with(b"d")).unwrap();
assert_eq!(first.as_slice(), b"alpha");
assert_eq!(second, "beta");
assert!(fourth_starts_with_d);
assert!(r.is_empty());
}
#[test]
#[cfg(feature = "specialised-vectors")]
fn seq_walk_rejects_bulk_primitive_without_consuming_reader() {
let v: Vec<u32> = vec![1, 2, 3];
let bytes = to_vec(&v).unwrap();
let mut r = bytes.as_slice();
let before = r.len();
let err = match Vec::<u32>::walk_revisioned(&mut r) {
Err(e) => e,
Ok(_) => panic!("expected specialised bulk Vec<u32> walk to fail"),
};
assert!(matches!(err, Error::Deserialize(_)));
assert_eq!(r.len(), before);
}
#[test]
#[cfg(not(feature = "specialised-vectors"))]
fn seq_walk_accepts_numeric_vec_when_specialised_vectors_disabled() {
let v: Vec<u32> = vec![7, 8];
let bytes = to_vec(&v).unwrap();
let mut r = bytes.as_slice();
let mut walker = Vec::<u32>::walk_revisioned(&mut r).unwrap();
let first = walker.next_item().unwrap().decode().unwrap();
assert_eq!(first, 7);
let second = walker.next_item().unwrap().decode().unwrap();
assert_eq!(second, 8);
assert!(r.is_empty());
}
#[test]
#[cfg(all(feature = "specialised-vectors", feature = "uuid"))]
fn seq_walk_rejects_bulk_uuid_without_consuming_reader() {
let v = vec![uuid::Uuid::nil(), uuid::Uuid::nil()];
let bytes = to_vec(&v).unwrap();
let mut r = bytes.as_slice();
let before = r.len();
let err = match Vec::<uuid::Uuid>::walk_revisioned(&mut r) {
Err(e) => e,
Ok(_) => panic!("expected specialised bulk Vec<Uuid> walk to fail"),
};
assert!(matches!(err, Error::Deserialize(_)));
assert_eq!(r.len(), before);
}
#[test]
#[cfg(all(feature = "specialised-vectors", feature = "rust_decimal"))]
fn seq_walk_rejects_bulk_decimal_without_consuming_reader() {
use rust_decimal::Decimal;
let v = vec![Decimal::ZERO, Decimal::ONE];
let bytes = to_vec(&v).unwrap();
let mut r = bytes.as_slice();
let before = r.len();
let err = match Vec::<Decimal>::walk_revisioned(&mut r) {
Err(e) => e,
Ok(_) => panic!("expected specialised bulk Vec<Decimal> walk to fail"),
};
assert!(matches!(err, Error::Deserialize(_)));
assert_eq!(r.len(), before);
}
#[test]
fn btreeset_walks_primitive_elements() {
let s: BTreeSet<u32> = [1u32, 2, 3, 4].iter().copied().collect();
let bytes = to_vec(&s).unwrap();
let mut r = bytes.as_slice();
let mut walker: SeqWalker<u32, _> = BTreeSet::<u32>::walk_revisioned(&mut r).unwrap();
assert_eq!(walker.remaining(), 4);
let mut collected = Vec::new();
while let Some(item) = walker.next_item() {
collected.push(item.decode().unwrap());
}
assert_eq!(collected, vec![1, 2, 3, 4]);
assert!(r.is_empty());
}
#[test]
fn hashset_walks_primitive_elements() {
let mut s: HashSet<u64> = HashSet::new();
for v in [10u64, 20, 30] {
s.insert(v);
}
let bytes = to_vec(&s).unwrap();
let mut r = bytes.as_slice();
let mut walker: SeqWalker<u64, _> = HashSet::<u64>::walk_revisioned(&mut r).unwrap();
assert_eq!(walker.remaining(), 3);
let mut collected = HashSet::new();
while let Some(item) = walker.next_item() {
collected.insert(item.decode().unwrap());
}
assert_eq!(collected, s);
assert!(r.is_empty());
}
#[test]
fn binaryheap_walks_primitive_elements() {
let mut h: BinaryHeap<i32> = BinaryHeap::new();
for v in [3i32, 1, 4, 1, 5] {
h.push(v);
}
let bytes = to_vec(&h).unwrap();
let mut r = bytes.as_slice();
let mut walker: SeqWalker<i32, _> = BinaryHeap::<i32>::walk_revisioned(&mut r).unwrap();
assert_eq!(walker.remaining(), 5);
let mut count = 0;
while let Some(item) = walker.next_item() {
item.skip().unwrap();
count += 1;
}
assert_eq!(count, 5);
assert!(r.is_empty());
}
#[revisioned(revision = 1)]
#[derive(Debug)]
struct Sandwich {
header: u16,
body: BTreeMap<String, u32>,
trailer: u32,
}
#[test]
fn struct_walker_walk_field_lets_parent_continue_to_sibling() {
let outer = Sandwich {
header: 7,
body: [("a".into(), 1u32), ("b".into(), 2)].iter().cloned().collect(),
trailer: 99,
};
let bytes = to_vec(&outer).unwrap();
let mut r = bytes.as_slice();
let mut walker = Sandwich::walk_revisioned(&mut r).unwrap();
assert_eq!(walker.decode_header().unwrap(), 7);
{
let mut body = walker.walk_body().unwrap();
while let Some(entry) = body.next_entry() {
let _ = entry.decode_pair().unwrap();
}
}
assert_eq!(walker.decode_trailer().unwrap(), 99);
assert!(r.is_empty());
}
#[test]
fn struct_walker_into_walk_field_consumes_parent() {
let outer = Sandwich {
header: 1,
body: [("k".into(), 5u32)].iter().cloned().collect(),
trailer: 0,
};
let bytes = to_vec(&outer).unwrap();
let mut r = bytes.as_slice();
let mut walker = Sandwich::walk_revisioned(&mut r).unwrap();
assert_eq!(walker.decode_header().unwrap(), 1);
let mut body = walker.into_walk_body().unwrap();
while let Some(entry) = body.next_entry() {
let _ = entry.decode_pair().unwrap();
}
}
#[test]
fn map_entry_out_of_order_returns_error_without_io() {
let mut map = BTreeMap::new();
map.insert("only".to_string(), 42u32);
let bytes = to_vec(&map).unwrap();
let mut r = bytes.as_slice();
let mut walker = <BTreeMap<String, u32>>::walk_revisioned(&mut r).unwrap();
let mut entry = walker.next_entry().unwrap();
entry.skip_key().unwrap();
let err = entry.decode_key().unwrap_err();
assert!(matches!(err, Error::Deserialize(_)));
let v = entry.decode_value().unwrap();
assert_eq!(v, 42);
assert!(r.is_empty());
}