Skip to content

Commit 8c87216

Browse files
committed
Add enums to deepsize_derive, migrate to 2015 edition
Using the 2015 edition until rust-lang/rust#57407 is merged, so that the derive macro can be used within the crate (for tests)
1 parent 80d11dd commit 8c87216

File tree

6 files changed

+153
-63
lines changed

6 files changed

+153
-63
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ description = "A crate for measuring the total size of object on the stack and h
77
repository = "https://github.com/Aeledfyr/deepsize/"
88
readme = "README.md"
99
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"]
10-
edition = "2018"
10+
edition = "2015"
1111

1212
[dependencies]
1313
deepsize_derive = { path = "deepsize_derive", version = "0.1" }

deepsize_derive/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ license = "MIT"
66
description = "A crate for measuring the total size of object on the stack and heap"
77
repository = "https://github.com/Aeledfyr/deepsize/"
88
include = ["Cargo.toml", "src/**/*.rs", "../LICENSE"]
9-
edition = "2018"
9+
edition = "2015"
1010

1111
[lib]
1212
proc-macro = true

deepsize_derive/src/lib.rs

Lines changed: 113 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
/// Mainly from `syn`'s heap_size derive example:
44
/// https://github.com/dtolnay/syn/commits/master/examples/heapsize/heapsize_derive/src/lib.rs
55
extern crate proc_macro;
6+
extern crate proc_macro2;
7+
extern crate syn;
8+
extern crate quote;
69

710
use proc_macro2::TokenStream;
811
use quote::{quote, quote_spanned};
@@ -24,7 +27,7 @@ pub fn derive_deep_size(input: proc_macro::TokenStream) -> proc_macro::TokenStre
2427
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
2528

2629
// Generate an expression to sum up the size of each field.
27-
let sum = deepsize_sum(&input.data);
30+
let sum = deepsize_sum(&input.data, &name);
2831

2932
let expanded = quote! {
3033
// The generated impl.
@@ -49,39 +52,119 @@ fn add_trait_bounds(mut generics: Generics) -> Generics {
4952
generics
5053
}
5154

52-
// Generate an expression to sum up the size of each field.
53-
fn deepsize_sum(data: &Data) -> TokenStream {
54-
match *data {
55-
Data::Struct(ref data) => {
56-
match data.fields {
57-
Fields::Named(ref fields) => {
58-
let recurse = fields.named.iter().map(|f| {
59-
let name = &f.ident;
60-
quote_spanned! {f.span()=>
61-
::deepsize::DeepSizeOf::deep_size_of_children(&self.#name, context)
62-
}
63-
});
64-
quote! {
65-
0 #(+ #recurse)*
66-
}
55+
fn match_fields(fields: &syn::Fields) -> TokenStream {
56+
match fields {
57+
Fields::Named(ref fields) => {
58+
let recurse = fields.named.iter().map(|f| {
59+
let name = &f.ident;
60+
quote_spanned! {f.span()=>
61+
::deepsize::DeepSizeOf::deep_size_of_children(&self.#name, context)
62+
}
63+
});
64+
quote! {
65+
0 #(+ #recurse)*
66+
}
67+
}
68+
Fields::Unnamed(ref fields) => {
69+
let recurse = fields.unnamed.iter().enumerate().map(|(i, f)| {
70+
let index = Index::from(i);
71+
quote_spanned! {f.span()=>
72+
::deepsize::DeepSizeOf::deep_size_of_children(&self.#index, context)
73+
}
74+
});
75+
quote! {
76+
0 #(+ #recurse)*
77+
}
78+
}
79+
Fields::Unit => {
80+
// Unit structs cannot own more than 0 bytes of memory.
81+
quote!(0)
82+
}
83+
}
84+
}
85+
86+
fn match_enum_fields(fields: &syn::Fields) -> TokenStream {
87+
match fields {
88+
Fields::Named(ref fields) => {
89+
let recurse = fields.named.iter().map(|f| {
90+
let name = &f.ident;
91+
quote_spanned! {f.span()=>
92+
::deepsize::DeepSizeOf::deep_size_of_children(#name, context)
6793
}
68-
Fields::Unnamed(ref fields) => {
69-
let recurse = fields.unnamed.iter().enumerate().map(|(i, f)| {
70-
let index = Index::from(i);
71-
quote_spanned! {f.span()=>
72-
::deepsize::DeepSizeOf::deep_size_of_children(&self.#index, context)
73-
}
74-
});
75-
quote! {
76-
0 #(+ #recurse)*
77-
}
94+
});
95+
quote! {
96+
0 #(+ #recurse)*
97+
}
98+
}
99+
Fields::Unnamed(ref fields) => {
100+
let recurse = fields.unnamed.iter().enumerate().map(|(i, f)| {
101+
let i = syn::Ident::new(&format!("_{}", i), proc_macro2::Span::call_site());
102+
quote_spanned! {f.span()=>
103+
::deepsize::DeepSizeOf::deep_size_of_children(#i, context)
78104
}
79-
Fields::Unit => {
80-
// Unit structs cannot own more than 0 bytes of memory.
81-
quote!(0)
105+
});
106+
quote! {
107+
0 #(+ #recurse)*
108+
}
109+
}
110+
Fields::Unit => {
111+
// Unit structs cannot own more than 0 bytes of memory.
112+
quote!(0)
113+
}
114+
}
115+
}
116+
117+
fn get_matcher(var: &syn::Variant) -> TokenStream {
118+
let matcher = match &var.fields {
119+
Fields::Unit => TokenStream::new(),
120+
Fields::Unnamed(fields) => {
121+
let fields: TokenStream = (0..fields.unnamed.len())
122+
.map(|n| {
123+
let i = syn::Ident::new(&format!("_{}", n), proc_macro2::Span::call_site());
124+
quote!(#i,)
125+
})
126+
.collect();
127+
quote!((#fields))
128+
}
129+
Fields::Named(fields) => {
130+
let fields: TokenStream = fields
131+
.named
132+
.iter()
133+
.map(|f| {
134+
let i = f.ident.as_ref().unwrap();
135+
quote!(#i,)
136+
})
137+
.collect();
138+
quote!({#fields})
139+
}
140+
};
141+
142+
quote!(#matcher)
143+
}
144+
145+
// Generate an expression to sum up the size of each field.
146+
fn deepsize_sum(data: &Data, struct_name: &proc_macro2::Ident) -> TokenStream {
147+
match *data {
148+
Data::Struct(ref inner) => {
149+
match_fields(&inner.fields)
150+
}
151+
Data::Enum(ref inner) => {
152+
let arms = inner.variants.iter()
153+
.map(|var| {
154+
let matcher = get_matcher(var);
155+
let output = match_enum_fields(&var.fields);
156+
let name = &var.ident;
157+
let ident = quote!(#struct_name::#name);
158+
quote!(#ident #matcher => #output,)
159+
});
160+
161+
quote! {
162+
match self {
163+
#(#arms)*
164+
_ => 0 // This is needed for empty enums
82165
}
83166
}
84167
}
85-
Data::Enum(_) | Data::Union(_) => unimplemented!(),
168+
Data::Union(_) => unimplemented!(),
86169
}
87170
}

examples/derive.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
extern crate deepsize;
2+
13
use deepsize::DeepSizeOf;
24

35
#[derive(DeepSizeOf)]

src/lib.rs

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@
2525
//! ```
2626
//!
2727
28+
// Hack so that #[derive(DeepSizeOf)] is usable within the crate
29+
// until [this](https://github.com/rust-lang/rust/pull/57407) stabalizes
30+
// Also means that both crates need to be on the 2015 edition
31+
mod deepsize { pub use super::*; }
32+
33+
extern crate deepsize_derive;
34+
2835
pub use deepsize_derive::*;
2936

3037
use std::collections::HashSet;
@@ -73,7 +80,7 @@ pub trait DeepSizeOf {
7380
/// This is an internal function, and requires a [`Context`](Context)
7481
/// to track visited references.
7582
fn recurse_deep_size_of(&self, context: &mut Context) -> usize {
76-
self.stack_size() + self.deep_size_of_children(context)
83+
std::mem::size_of_val(self) + self.deep_size_of_children(context)
7784
}
7885

7986
/// Returns an estimation of a total size of memory owned by the
@@ -85,13 +92,6 @@ pub trait DeepSizeOf {
8592
/// This is an internal function, and requires a [`Context`](Context)
8693
/// to track visited references.
8794
fn deep_size_of_children(&self, context: &mut Context) -> usize;
88-
89-
/// Returns the size of the memory the object uses itself
90-
///
91-
/// This method is generally equivalent to [`size_of_val`](std::mem::size_of_val)
92-
fn stack_size(&self) -> usize {
93-
std::mem::size_of_val(self)
94-
}
9595
}
9696

9797

@@ -198,8 +198,8 @@ where
198198
/// ```
199199
fn deep_size_of_children(&self, context: &mut Context) -> usize {
200200
self.iter()
201-
.fold(0, |sum, child| sum + child.recurse_deep_size_of(context))
202-
+ (self.capacity() - self.len()) * std::mem::size_of::<T>()
201+
.fold(0, |sum, child| sum + child.deep_size_of_children(context))
202+
+ self.capacity() * std::mem::size_of::<T>()
203203
// Size of unused capacity
204204
}
205205
}
@@ -241,8 +241,8 @@ where
241241
/// ```
242242
fn deep_size_of_children(&self, context: &mut Context) -> usize {
243243
self.iter()
244-
.fold(0, |sum, child| sum + child.recurse_deep_size_of(context))
245-
+ (self.capacity() - self.len()) * std::mem::size_of::<T>()
244+
.fold(0, |sum, child| sum + child.deep_size_of_children(context))
245+
+ self.capacity() * std::mem::size_of::<T>()
246246
// Size of unused capacity
247247
}
248248
}
@@ -287,10 +287,9 @@ where
287287
.fold(0, |sum, (key, val)| {
288288
sum + key.deep_size_of_children(context)
289289
+ val.deep_size_of_children(context)
290-
+ std::mem::size_of::<Option<(u64, K, V)>>()
291290
})
292-
+ (self.capacity() - self.len()) * (std::mem::size_of::<Option<(u64, K, V)>>())
293-
// Size of unused capacity
291+
+ self.capacity() * std::mem::size_of::<Option<(u64, K, V)>>()
292+
// Size of container capacity
294293
}
295294
}
296295

@@ -302,10 +301,9 @@ where
302301
self.iter()
303302
.fold(0, |sum, item| {
304303
sum + item.deep_size_of_children(context)
305-
+ std::mem::size_of::<Option<(u64, T, ())>>()
306304
})
307-
+ (self.capacity() - self.len()) * (std::mem::size_of::<Option<(u64, T, ())>>())
308-
// Size of unused capacity
305+
+ self.capacity() * std::mem::size_of::<Option<(u64, T, ())>>()
306+
// Size container storage
309307
}
310308
}
311309

@@ -331,10 +329,10 @@ where
331329

332330
fn recurse_deep_size_of(&self, context: &mut Context) -> usize {
333331
if context.contains_arc(self) {
334-
self.stack_size()
332+
std::mem::size_of::<Self>()
335333
} else {
336334
context.add_arc(self);
337-
self.stack_size() + self.deep_size_of_children(context)
335+
std::mem::size_of::<Self>() + self.deep_size_of_children(context)
338336
}
339337
}
340338
}
@@ -350,10 +348,10 @@ where
350348

351349
fn recurse_deep_size_of(&self, context: &mut Context) -> usize {
352350
if context.contains_rc(self) {
353-
self.stack_size()
351+
std::mem::size_of::<Self>()
354352
} else {
355353
context.add_rc(self);
356-
self.stack_size() + self.deep_size_of_children(context)
354+
std::mem::size_of::<Self>() + self.deep_size_of_children(context)
357355
}
358356
}
359357
}
@@ -373,10 +371,10 @@ where
373371

374372
fn recurse_deep_size_of(&self, context: &mut Context) -> usize {
375373
if context.contains_ref(&self) {
376-
self.stack_size()
374+
std::mem::size_of::<Self>()
377375
} else {
378376
context.add_ref(&self);
379-
self.stack_size() + self.deep_size_of_children(context)
377+
std::mem::size_of::<Self>() + self.deep_size_of_children(context)
380378
}
381379
}
382380
}
@@ -387,10 +385,6 @@ where
387385
{
388386
fn deep_size_of_children(&self, context: &mut Context) -> usize {
389387
self.iter()
390-
.fold(0, |sum, child| sum + child.recurse_deep_size_of(context))
391-
}
392-
393-
fn stack_size(&self) -> usize {
394-
0
388+
.fold(0, |sum, child| sum + child.deep_size_of_children(context))
395389
}
396390
}

src/test.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ fn alignment() {
5454
assert_eq!(std::mem::size_of::<[Test; 3]>(), array.deep_size_of());
5555

5656
let vec = vec![Test(5), Test(16), Test(2)];
57-
assert_eq!(array.deep_size_of(), 256 * 3);
57+
assert_eq!(vec.deep_size_of(), 256 * 3 + 24);
5858

5959
let vec = vec![Test2(Test(5), 0), Test2(Test(16), 0), Test2(Test(2), 0)];
60-
assert_eq!(array.deep_size_of(), 256 * 3);
60+
assert_eq!(vec.deep_size_of(), 512 * 3 + 24);
6161
}
6262

6363
mod context_tests {
@@ -94,3 +94,14 @@ mod context_tests {
9494
}
9595
}
9696

97+
fn test_derive() {
98+
99+
#[derive(DeepSizeOf)]
100+
enum Example {
101+
One,
102+
Two(),
103+
Three(u32, Box<u8>),
104+
Four { name: Box<u32> },
105+
Five { },
106+
}
107+
}

0 commit comments

Comments
 (0)