pub enum MemUsageTree {
Bytes(u64),
Node(MemUsageNode),
}
impl Default for MemUsageTree {
fn default() -> Self {
Self::Bytes(0)
}
}
impl From<u64> for MemUsageTree {
fn from(size: u64) -> Self {
Self::Bytes(size)
}
}
impl MemUsageTree {
pub fn size_bytes(&self) -> u64 {
match self {
Self::Bytes(size) => *size,
Self::Node(node) => node.size_bytes,
}
}
}
pub struct NamedMemUsageTree {
pub name: String,
pub value: MemUsageTree,
}
impl NamedMemUsageTree {
pub fn new(name: impl Into<String>, child: impl Into<MemUsageTree>) -> Self {
Self {
name: name.into(),
value: child.into(),
}
}
pub fn size_bytes(&self) -> u64 {
self.value.size_bytes()
}
}
#[derive(Default)]
pub struct MemUsageNode {
children: Vec<NamedMemUsageTree>,
size_bytes: u64,
}
impl MemUsageNode {
pub fn new() -> Self {
Self::default()
}
pub fn add(&mut self, name: impl Into<String>, child: impl Into<MemUsageTree>) {
self.add_named_child(NamedMemUsageTree::new(name, child));
}
pub fn add_named_child(&mut self, tree: NamedMemUsageTree) {
self.size_bytes += tree.size_bytes();
self.children.push(tree);
}
pub fn with_named_child(mut self, tree: NamedMemUsageTree) -> Self {
self.add_named_child(tree);
self
}
pub fn with_child(mut self, name: impl Into<String>, child: impl Into<MemUsageTree>) -> Self {
self.add_named_child(NamedMemUsageTree::new(name, child));
self
}
pub fn size_bytes(&self) -> u64 {
self.size_bytes
}
pub fn children(&self) -> &[NamedMemUsageTree] {
&self.children
}
pub fn with_total_size_bytes(mut self, size_bytes: u64) -> MemUsageTree {
self.size_bytes = size_bytes;
self.into_tree()
}
pub fn into_tree(self) -> MemUsageTree {
MemUsageTree::Node(self)
}
}
pub trait MemUsageTreeCapture {
fn capture_mem_usage_tree(&self) -> MemUsageTree;
}
impl<T: MemUsageTreeCapture> MemUsageTreeCapture for Option<T> {
fn capture_mem_usage_tree(&self) -> MemUsageTree {
match self {
Some(value) => value.capture_mem_usage_tree(),
None => MemUsageTree::Bytes(0),
}
}
}
impl<K, V, S> MemUsageTreeCapture for std::collections::HashMap<K, V, S>
where
K: std::fmt::Display,
V: MemUsageTreeCapture,
{
fn capture_mem_usage_tree(&self) -> MemUsageTree {
let mut node = MemUsageNode::new();
for (key, value) in self {
node.add(key.to_string(), value.capture_mem_usage_tree());
}
node.into_tree()
}
}