use crate::allocator::{Allocator, NodePtr};
use crate::error::Result;
use crate::serde::bytes32::Bytes32;
use crate::serde::intern::intern_tree;
use crate::serde::node_from_bytes_backrefs;
use crate::serde::node_to_bytes;
use crate::serde::object_cache::{ObjectCache, treehash};
use rstest::rstest;
fn treehash_for_node(allocator: &Allocator, node: NodePtr) -> Bytes32 {
let mut object_cache = ObjectCache::new(treehash);
*object_cache
.get_or_calculate(allocator, &node, None)
.unwrap()
}
fn hex_to_node(allocator: &mut Allocator, hex: &str) -> Result<crate::allocator::NodePtr> {
let bytes = hex::decode(hex.trim().replace([' ', '\n'], "")).expect("invalid hex");
node_from_bytes_backrefs(allocator, &bytes)
}
fn test_hex_interning(hex: &str, expected_atoms: usize, expected_pairs: usize) -> Result<()> {
let mut allocator = Allocator::new();
let node = hex_to_node(&mut allocator, hex)?;
let tree = intern_tree(&allocator, node)?;
let original_serialized = node_to_bytes(&allocator, node)?;
let new_serialized = node_to_bytes(&tree.allocator, tree.root)?;
assert_eq!(
original_serialized, new_serialized,
"Serialized bytes do not match after interning."
);
let original_treehash = treehash_for_node(&allocator, node);
let new_treehash = tree.tree_hash();
assert_eq!(
original_treehash, new_treehash,
"Treehashes do not match after interning."
);
assert_eq!(
tree.atoms.len(),
expected_atoms,
"Atom count doesn't match expected.\nGot: {:?}\nExpected: {:?}",
tree.atoms.len(),
expected_atoms
);
assert_eq!(
tree.pairs.len(),
expected_pairs,
"Pair count doesn't match expected.\nGot: {:?}\nExpected: {:?}",
tree.pairs.len(),
expected_pairs
);
Ok(())
}
#[rstest]
#[case("01", 1, 0)] #[case("0a", 1, 0)] #[case("ff0101", 1, 1)] #[case("ff010a", 2, 1)] #[case("ff01ff0101", 1, 2)] #[case("ffff2a2a2a", 1, 2)] #[case("ff01ff02ff0301", 3, 3)] #[case("ff01ff02ff0300", 4, 3)] #[case("ff01ff02ff0304", 4, 3)] #[case("ff01ff02ff0103", 3, 3)] #[case("ffff0102ff0102", 2, 2)] #[case("ffff0102ffff0102ff0102", 2, 3)] #[case("ffff0102ffff010200", 3, 3)] #[case("ffff010aff010a", 2, 2)] #[case("00", 1, 0)] #[case("ff0100", 2, 1)] #[case("ff0000", 1, 1)] #[case("ff01ff01ff0100", 2, 3)] #[case("ff01ff01ff0101", 1, 3)] #[case("ffff01ff0203ff01ff0203", 3, 3)] #[case("ffff0102ffff0102ffff010200", 3, 4)] fn test_interning(
#[case] hex: &str,
#[case] expected_atoms: usize,
#[case] expected_pairs: usize,
) -> Result<()> {
test_hex_interning(hex, expected_atoms, expected_pairs)
}