Skip to content

Commit

Permalink
update packed test
Browse files Browse the repository at this point in the history
  • Loading branch information
jordens committed Oct 24, 2024
1 parent 489047d commit 76fce8e
Showing 1 changed file with 28 additions and 7 deletions.
35 changes: 28 additions & 7 deletions miniconf/tests/packed.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use miniconf::{Indices, Leaf, Node, Packed, Path, Traversal, Tree, TreeKey, TreeSerialize};
use miniconf::{
Indices, Leaf, Metadata, Node, Packed, Path, Traversal, Tree, TreeKey, TreeSerialize,
};

#[derive(Tree, Default)]
struct Settings {
Expand Down Expand Up @@ -133,17 +135,36 @@ fn zero_key() {

#[test]
fn size() {
// Play with the worst cases for Packed
// Bit-hungriest type is [T;0] but that doesn't have any keys so won't recurse/consume with any Transcode/Keys
// Then [T; 1] which takes one bit per level (not 0 bits, to distinguish empty packed)
// Worst case for a 32 bit usize we need 31 array levels (marker bit) but TreeKey is only implemented to 16
// Easiest way to get to 32 bit is to take 15 length-3 (2 bit) levels and one length-1 (1 bit) level to fill it, needing (3**15 ~ 14 M) storage.
// Play with the worst cases for 32 bit Packed
// Bit-hungriest type would be [T; 0] or () but (a) those are forbidden (internal without leaves) and (b) they doesn't have any keys
// so won't recurse in Transcode or consume from Keys
// Then [T; 1] which takes one bit per level (not 0 bits, to distinguish empty Packed)
// Worst case for a 32 bit usize we need 31 array levels (marker bit).
type A31 = [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[Leaf<()>; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1];
1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1]; 1];
assert_eq!(core::mem::size_of::<A31>(), 0);
let packed = Packed::new_from_lsb(1 << 31).unwrap();
let (path, node) = A31::transcode::<Path<String, '/'>, _>(packed).unwrap();
assert_eq!(node, Node::leaf(31));
assert_eq!(path.as_str().len(), 2 * 31);
let meta: Metadata = A31::traverse_all().unwrap();
assert_eq!(meta.max_bits, 31);
assert_eq!(meta.max_depth, 31);
assert_eq!(meta.count, 1usize.pow(31));
assert_eq!(meta.max_length, 31);

// Another way to get to 32 bit is to take 15 length-3 (2 bit) levels and one length-1 (1 bit) level to fill it, needing (3**15 ~ 14 M) storage.
// With the unit as type, we need 0 storage but can't do much.
type A16 =
[[[[[[[[[[[[[[[[Leaf<()>; 3]; 3]; 3]; 3]; 3]; 3]; 3]; 3]; 3]; 3]; 3]; 3]; 3]; 3]; 3]; 1];
assert_eq!(core::mem::size_of::<A16>(), 0);
let packed = Packed::new_from_lsb(1 << 31).unwrap();
let (path, node) = <A16 as TreeKey>::transcode::<Path<String, '/'>, _>(packed).unwrap();
let (path, node) = A16::transcode::<Path<String, '/'>, _>(packed).unwrap();
assert_eq!(node, Node::leaf(16));
assert_eq!(path.as_str().len(), 2 * 16);
let meta: Metadata = A16::traverse_all().unwrap();
assert_eq!(meta.max_bits, 31);
assert_eq!(meta.max_depth, 16);
assert_eq!(meta.count, 3usize.pow(15));
assert_eq!(meta.max_length, 16);
}

0 comments on commit 76fce8e

Please sign in to comment.