Skip to main content

get_size2/
lib.rs

1#![doc = include_str!("./lib.md")]
2// `doc_cfg` enables the automatic feature badges on docs.rs, so every `std`, `alloc` and
3// optional dependency gated item shows what it requires.
4#![cfg_attr(docsrs, feature(doc_cfg))]
5#![no_std]
6
7#[cfg(feature = "alloc")]
8extern crate alloc;
9#[cfg(feature = "std")]
10extern crate std;
11
12#[cfg(feature = "derive")]
13pub use get_size_derive2::*;
14
15mod impls;
16mod tracker;
17pub use tracker::*;
18// The test suite exercises the `std` implementations and is therefore only
19// compiled when the `std` feature is active.
20#[cfg(all(test, feature = "std"))]
21mod tests;
22
23/// Determines how many bytes the object occupies inside the heap.
24pub fn heap_size<T: GetSize>(value: &T) -> usize {
25    value.get_heap_size()
26}
27
28/// The tracker used by the [`GetSize`] implementations generated by the derive macro.
29///
30/// This is [`StandardTracker`] if the `alloc` feature is active, since tracking requires an
31/// allocated set of already seen addresses. Without `alloc` there is no shared ownership type
32/// (`Rc`/`Arc`) to track, so [`NoTracker`] is used instead.
33#[cfg(feature = "alloc")]
34pub type DefaultTracker = StandardTracker;
35
36/// The tracker used by the [`GetSize`] implementations generated by the derive macro.
37///
38/// This is [`StandardTracker`] if the `alloc` feature is active, since tracking requires an
39/// allocated set of already seen addresses. Without `alloc` there is no shared ownership type
40/// (`Rc`/`Arc`) to track, so [`NoTracker`] is used instead.
41#[cfg(not(feature = "alloc"))]
42pub type DefaultTracker = NoTracker;
43
44/// Creates the [`DefaultTracker`] used by the derive macro.
45///
46/// Mostly an implementation detail of the derive macro, which cannot know whether the `alloc`
47/// feature is active at the call site.
48#[cfg(feature = "alloc")]
49#[must_use]
50pub fn default_tracker() -> DefaultTracker {
51    StandardTracker::new()
52}
53
54/// Creates the [`DefaultTracker`] used by the derive macro.
55///
56/// Mostly an implementation detail of the derive macro, which cannot know whether the `alloc`
57/// feature is active at the call site.
58#[cfg(not(feature = "alloc"))]
59#[must_use]
60pub const fn default_tracker() -> DefaultTracker {
61    NoTracker::new(true)
62}
63
64/// Determine the size in bytes an object occupies inside RAM.
65pub trait GetSize: Sized {
66    /// Determines how may bytes this object occupies inside the stack.
67    ///
68    /// The default implementation uses [`core::mem::size_of`] and should work for almost all types.
69    #[must_use]
70    fn get_stack_size() -> usize {
71        core::mem::size_of::<Self>()
72    }
73
74    /// Determines how many bytes this object occupies inside the heap.
75    ///
76    /// The default implementation simply delegates to [`get_heap_size_with_tracker`](Self::get_heap_size_with_tracker)
77    /// with a noop tracker. This method is not meant to be implemented directly, and only exists for convenience.
78    fn get_heap_size(&self) -> usize {
79        let tracker = NoTracker::new(true);
80        Self::get_heap_size_with_tracker(self, tracker).0
81    }
82
83    /// Determines how many bytes this object occupies inside the heap while using a `tracker`.
84    ///
85    /// The default implementation returns 0, assuming the object is fully allocated on the stack.
86    /// It must be adjusted as appropriate for objects which hold data inside the heap.
87    fn get_heap_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
88        (0, tracker)
89    }
90
91    /// Determines the total size of the object.
92    ///
93    /// The default implementation simply adds up the results of [`get_stack_size`](Self::get_stack_size)
94    /// and [`get_heap_size`](Self::get_heap_size) and is not meant to be changed.
95    fn get_size(&self) -> usize {
96        Self::get_stack_size() + GetSize::get_heap_size(self)
97    }
98
99    /// Determines the total size of the object while using a `tracker`.
100    ///
101    /// The default implementation simply adds up the results of [`get_stack_size`](Self::get_stack_size)
102    /// and [`get_heap_size_with_tracker`](Self::get_heap_size_with_tracker) and is not meant to
103    /// be changed.
104    fn get_size_with_tracker<T: GetSizeTracker>(&self, tracker: T) -> (usize, T) {
105        let stack_size = Self::get_stack_size();
106        let (heap_size, tracker) = Self::get_heap_size_with_tracker(self, tracker);
107        (stack_size + heap_size, tracker)
108    }
109}