use crate::visitor::NodeKind;
use crate::visitor::VisitorImpl;
use crate::Allocative;
use crate::Key;
use crate::Visitor;
pub fn size_of_unique_allocated_data(root: &dyn Allocative) -> usize {
struct SizeOfUniqueAllocatedDataVisitor {
size: usize,
}
impl VisitorImpl for SizeOfUniqueAllocatedDataVisitor {
fn enter_inline_impl(&mut self, _name: Key, size: usize, parent: NodeKind) {
if let NodeKind::Unique = parent {
self.size += size;
}
}
fn enter_unique_impl(&mut self, _name: Key, _size: usize, _parent: NodeKind) {}
fn enter_shared_impl(
&mut self,
_name: Key,
_size: usize,
_ptr: *const (),
_parent: NodeKind,
) -> bool {
false
}
fn exit_inline_impl(&mut self) {}
fn exit_unique_impl(&mut self) {}
fn exit_shared_impl(&mut self) {
unreachable!("shared pointers are not visited")
}
fn exit_root_impl(&mut self) {}
}
let mut visitor_impl = SizeOfUniqueAllocatedDataVisitor { size: 0 };
let mut visitor = Visitor {
visitor: &mut visitor_impl,
node_kind: NodeKind::Root,
};
root.visit(&mut visitor);
visitor.exit();
visitor_impl.size
}
pub fn size_of_unique<T>(root: &T) -> usize
where
T: Allocative,
{
std::mem::size_of::<T>() + size_of_unique_allocated_data(root)
}
#[cfg(test)]
mod tests {
use std::mem;
use allocative_derive::Allocative;
use crate as allocative;
use crate::size_of_unique;
use crate::size_of_unique_allocated_data;
#[test]
fn test_box() {
#[derive(Allocative)]
struct Boxed {
data: Box<u32>,
}
let boxed = Boxed { data: Box::new(17) };
assert_eq!(mem::size_of::<u32>(), size_of_unique_allocated_data(&boxed));
assert_eq!(
mem::size_of::<u32>() + mem::size_of::<Boxed>(),
size_of_unique(&boxed)
);
}
#[test]
fn test_box_slice() {
#[derive(Allocative)]
struct Boxed {
data: Box<[u32]>,
}
let boxed = Boxed {
data: vec![1, 2, 3].into_boxed_slice(),
};
assert_eq!(
mem::size_of::<u32>() * 3,
size_of_unique_allocated_data(&boxed)
);
assert_eq!(
mem::size_of::<Boxed>() + mem::size_of::<u32>() * 3,
size_of_unique(&boxed)
);
}
#[test]
fn test_struct_in_box() {
#[derive(Allocative)]
struct Data {
a: u8,
b: Box<u32>,
}
#[derive(Allocative)]
struct Boxed {
data: Box<Data>,
}
let boxed = Boxed {
data: Box::new(Data {
a: 1,
b: Box::new(2),
}),
};
assert_eq!(
mem::size_of::<Data>() + mem::size_of::<u32>(),
size_of_unique_allocated_data(&boxed)
);
assert_eq!(
mem::size_of::<Boxed>() + mem::size_of::<Data>() + mem::size_of::<u32>(),
size_of_unique(&boxed)
);
}
}