1use crate::visitor::NodeKind;
11use crate::visitor::VisitorImpl;
12use crate::Allocative;
13use crate::Key;
14use crate::Visitor;
15
16pub fn size_of_unique_allocated_data(root: &dyn Allocative) -> usize {
40 struct SizeOfUniqueAllocatedDataVisitor {
41 size: usize,
43 }
44
45 impl VisitorImpl for SizeOfUniqueAllocatedDataVisitor {
46 fn enter_inline_impl(&mut self, _name: Key, size: usize, parent: NodeKind) {
47 if let NodeKind::Unique = parent {
48 self.size += size;
49 }
50 }
51
52 fn enter_unique_impl(&mut self, _name: Key, _size: usize, _parent: NodeKind) {}
53
54 fn enter_shared_impl(
55 &mut self,
56 _name: Key,
57 _size: usize,
58 _ptr: *const (),
59 _parent: NodeKind,
60 ) -> bool {
61 false
62 }
63
64 fn exit_inline_impl(&mut self) {}
65
66 fn exit_unique_impl(&mut self) {}
67
68 fn exit_shared_impl(&mut self) {
69 unreachable!("shared pointers are not visited")
70 }
71
72 fn exit_root_impl(&mut self) {}
73 }
74
75 let mut visitor_impl = SizeOfUniqueAllocatedDataVisitor { size: 0 };
76 let mut visitor = Visitor {
77 visitor: &mut visitor_impl,
78 node_kind: NodeKind::Root,
79 };
80 root.visit(&mut visitor);
81 visitor.exit();
82 visitor_impl.size
83}
84
85pub fn size_of_unique<T>(root: &T) -> usize
107where
108 T: Allocative,
109{
110 std::mem::size_of::<T>() + size_of_unique_allocated_data(root)
111}
112
113#[cfg(test)]
114mod tests {
115 use std::mem;
116
117 use allocative_derive::Allocative;
118
119 use crate as allocative;
120 use crate::size_of_unique;
121 use crate::size_of_unique_allocated_data;
122
123 #[test]
124 fn test_box() {
125 #[derive(Allocative)]
126 struct Boxed {
127 data: Box<u32>,
128 }
129
130 let boxed = Boxed { data: Box::new(17) };
131
132 assert_eq!(mem::size_of::<u32>(), size_of_unique_allocated_data(&boxed));
133
134 assert_eq!(
135 mem::size_of::<u32>() + mem::size_of::<Boxed>(),
136 size_of_unique(&boxed)
137 );
138 }
139
140 #[test]
141 fn test_box_slice() {
142 #[derive(Allocative)]
143 struct Boxed {
144 data: Box<[u32]>,
145 }
146
147 let boxed = Boxed {
148 data: vec![1, 2, 3].into_boxed_slice(),
149 };
150
151 assert_eq!(
152 mem::size_of::<u32>() * 3,
153 size_of_unique_allocated_data(&boxed)
154 );
155
156 assert_eq!(
157 mem::size_of::<Boxed>() + mem::size_of::<u32>() * 3,
158 size_of_unique(&boxed)
159 );
160 }
161
162 #[test]
163 fn test_struct_in_box() {
164 #[derive(Allocative)]
165 struct Data {
166 a: u8,
167 b: Box<u32>,
168 }
169
170 #[derive(Allocative)]
171 struct Boxed {
172 data: Box<Data>,
173 }
174
175 let boxed = Boxed {
176 data: Box::new(Data {
177 a: 1,
178 b: Box::new(2),
179 }),
180 };
181
182 assert_eq!(
183 mem::size_of::<Data>() + mem::size_of::<u32>(),
184 size_of_unique_allocated_data(&boxed)
185 );
186
187 assert_eq!(
188 mem::size_of::<Boxed>() + mem::size_of::<Data>() + mem::size_of::<u32>(),
189 size_of_unique(&boxed)
190 );
191 }
192}