1#![warn(missing_docs)]
9
10pub mod allocator;
11pub mod export;
12pub mod export_enhanced;
13pub mod tracker;
14pub mod types;
15
16pub use allocator::TrackingAllocator;
18pub use tracker::{get_global_tracker, MemoryTracker};
19pub use types::{AllocationInfo, TrackingError, TrackingResult};
20
21#[cfg(feature = "tracking-allocator")]
23#[global_allocator]
24pub static GLOBAL: TrackingAllocator = TrackingAllocator::new();
26
27pub trait Trackable {
29 fn get_heap_ptr(&self) -> Option<usize>;
31
32 fn get_type_name(&self) -> &'static str;
34}
35
36impl<T> Trackable for Vec<T> {
38 fn get_heap_ptr(&self) -> Option<usize> {
39 if self.capacity() > 0 {
40 Some(self.as_ptr() as usize)
41 } else {
42 None
43 }
44 }
45
46 fn get_type_name(&self) -> &'static str {
47 std::any::type_name::<Vec<T>>()
48 }
49}
50
51impl Trackable for String {
52 fn get_heap_ptr(&self) -> Option<usize> {
53 if self.capacity() > 0 {
54 Some(self.as_ptr() as usize)
55 } else {
56 None
57 }
58 }
59
60 fn get_type_name(&self) -> &'static str {
61 "String"
62 }
63}
64
65impl<T> Trackable for Box<T> {
66 fn get_heap_ptr(&self) -> Option<usize> {
67 Some(self.as_ref() as *const T as usize)
68 }
69
70 fn get_type_name(&self) -> &'static str {
71 std::any::type_name::<Box<T>>()
72 }
73}
74
75impl<T> Trackable for std::rc::Rc<T> {
76 fn get_heap_ptr(&self) -> Option<usize> {
77 Some(std::rc::Rc::as_ptr(self) as usize)
80 }
81
82 fn get_type_name(&self) -> &'static str {
83 std::any::type_name::<std::rc::Rc<T>>()
84 }
85}
86
87impl<T> Trackable for std::sync::Arc<T> {
88 fn get_heap_ptr(&self) -> Option<usize> {
89 Some(std::sync::Arc::as_ptr(self) as usize)
92 }
93
94 fn get_type_name(&self) -> &'static str {
95 std::any::type_name::<std::sync::Arc<T>>()
96 }
97}
98
99#[macro_export]
112macro_rules! track_var {
113 ($var:ident) => {
114 $crate::_track_var_impl(&$var, stringify!($var))
115 };
116}
117
118#[doc(hidden)]
121pub fn _track_var_impl<T: Trackable>(var: &T, var_name: &str) -> TrackingResult<()> {
122 if let Some(ptr) = var.get_heap_ptr() {
123 let tracker = get_global_tracker();
124 tracker.associate_var(ptr, var_name.to_string(), var.get_type_name().to_string())
125 } else {
126 Ok(())
128 }
129}
130
131pub fn init() {
142 use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
143
144 tracing_subscriber::registry()
145 .with(
146 tracing_subscriber::EnvFilter::try_from_default_env()
147 .unwrap_or_else(|_| "memscope_rs=info".into()),
148 )
149 .with(tracing_subscriber::fmt::layer())
150 .init();
151
152 tracing::info!("memscope-rs initialized");
153}