use crate::event::Event;
use super::TRACKER;
pub fn reset() {
let mut tracker = TRACKER.lock();
tracker.clear();
}
pub fn get_events() -> Vec<Event> {
TRACKER.lock().events().to_vec()
}
pub fn get_events_filtered<F>(predicate: F) -> Vec<Event>
where
F: Fn(&Event) -> bool,
{
TRACKER.lock().events().iter().filter(|e| predicate(e)).cloned().collect()
}
pub fn get_new_events() -> Vec<Event> {
get_events_filtered(|e| e.is_new())
}
pub fn get_borrow_events() -> Vec<Event> {
get_events_filtered(|e| e.is_borrow())
}
pub fn get_drop_events() -> Vec<Event> {
get_events_filtered(|e| e.is_drop())
}
pub fn get_move_events() -> Vec<Event> {
get_events_filtered(|e| e.is_move())
}
pub fn get_events_for_var(name: &str) -> Vec<Event> {
get_events_filtered(|e| e.var_name().map(|n| n == name).unwrap_or(false))
}
pub fn get_event_counts() -> (usize, usize, usize, usize) {
let events = TRACKER.lock();
let events = events.events();
(
events.iter().filter(|e| e.is_new()).count(),
events.iter().filter(|e| e.is_borrow()).count(),
events.iter().filter(|e| e.is_move()).count(),
events.iter().filter(|e| e.is_drop()).count(),
)
}
#[derive(Debug, Clone, Default)]
pub struct TrackingSummary {
pub variables_created: usize,
pub variables_dropped: usize,
pub immutable_borrows: usize,
pub mutable_borrows: usize,
pub moves: usize,
pub rc_operations: usize,
pub arc_operations: usize,
pub refcell_operations: usize,
pub cell_operations: usize,
pub unsafe_operations: usize,
}
impl std::fmt::Display for TrackingSummary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "=== BorrowScope Summary ===")?;
writeln!(
f,
"Variables: {} created, {} dropped",
self.variables_created, self.variables_dropped
)?;
writeln!(
f,
"Borrows: {} immutable, {} mutable",
self.immutable_borrows, self.mutable_borrows
)?;
if self.moves > 0 {
writeln!(f, "Moves: {}", self.moves)?;
}
if self.rc_operations > 0 || self.arc_operations > 0 {
writeln!(
f,
"Smart pointers: {} Rc, {} Arc",
self.rc_operations, self.arc_operations
)?;
}
if self.refcell_operations > 0 || self.cell_operations > 0 {
writeln!(
f,
"Interior mutability: {} RefCell, {} Cell",
self.refcell_operations, self.cell_operations
)?;
}
if self.unsafe_operations > 0 {
writeln!(f, "Unsafe operations: {}", self.unsafe_operations)?;
}
Ok(())
}
}
pub fn get_summary() -> TrackingSummary {
let events = TRACKER.lock();
let events = events.events();
let mut summary = TrackingSummary::default();
for event in events {
match event {
Event::New { .. } => summary.variables_created += 1,
Event::Drop { .. } => summary.variables_dropped += 1,
Event::Borrow { mutable, .. } => {
if *mutable {
summary.mutable_borrows += 1;
} else {
summary.immutable_borrows += 1;
}
}
Event::Move { .. } => summary.moves += 1,
Event::RcNew { .. } | Event::RcClone { .. } => summary.rc_operations += 1,
Event::ArcNew { .. } | Event::ArcClone { .. } => summary.arc_operations += 1,
Event::RefCellNew { .. } | Event::RefCellBorrow { .. } | Event::RefCellDrop { .. } => {
summary.refcell_operations += 1
}
Event::CellNew { .. } | Event::CellGet { .. } | Event::CellSet { .. } => {
summary.cell_operations += 1
}
Event::RawPtrCreated { .. }
| Event::RawPtrDeref { .. }
| Event::UnsafeBlockEnter { .. }
| Event::UnsafeBlockExit { .. }
| Event::UnsafeFnCall { .. }
| Event::FfiCall { .. }
| Event::Transmute { .. }
| Event::UnionFieldAccess { .. } => summary.unsafe_operations += 1,
_ => {}
}
}
summary
}
pub fn print_summary() {
println!("{}", get_summary());
}