#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum NodeType {
Invalid = 0,
Leaf = 1,
Prefix = 2,
Blob = 3,
Node4 = 4,
Node16 = 5,
Node48 = 6,
Node256 = 7,
EmptyRoot = 8,
}
impl NodeType {
#[must_use]
pub fn from_raw(v: u8) -> Option<Self> {
match v {
0 => Some(Self::Invalid),
1 => Some(Self::Leaf),
2 => Some(Self::Prefix),
3 => Some(Self::Blob),
4 => Some(Self::Node4),
5 => Some(Self::Node16),
6 => Some(Self::Node48),
7 => Some(Self::Node256),
8 => Some(Self::EmptyRoot),
_ => None,
}
}
#[must_use]
pub const fn as_u8(self) -> u8 {
self as u8
}
}
pub const SIZE_BY_TYPE: [u32; 8] = [
16, 128, 128, 24, 88, 456, 1032, 8, ];
#[must_use]
pub fn size_of_node(ntype: NodeType) -> u32 {
assert!(ntype != NodeType::Invalid, "size_of_node(Invalid)");
let idx = ntype as usize - 1;
SIZE_BY_TYPE[idx]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ntype_round_trip_via_raw() {
let all = [
NodeType::Invalid,
NodeType::Leaf,
NodeType::Prefix,
NodeType::Blob,
NodeType::Node4,
NodeType::Node16,
NodeType::Node48,
NodeType::Node256,
NodeType::EmptyRoot,
];
for t in all {
assert_eq!(NodeType::from_raw(t.as_u8()), Some(t));
}
assert_eq!(NodeType::from_raw(9), None);
assert_eq!(NodeType::from_raw(255), None);
}
#[test]
fn size_table_per_node_type() {
assert_eq!(size_of_node(NodeType::Leaf), 16);
assert_eq!(size_of_node(NodeType::Prefix), 128);
assert_eq!(size_of_node(NodeType::Blob), 128);
assert_eq!(size_of_node(NodeType::Node4), 24);
assert_eq!(size_of_node(NodeType::Node16), 88);
assert_eq!(size_of_node(NodeType::Node48), 456);
assert_eq!(size_of_node(NodeType::Node256), 1032);
assert_eq!(size_of_node(NodeType::EmptyRoot), 8);
}
}