use std::{ops, slice};
use crate::{Event, Machine, Violation};
#[derive(Debug, Clone)]
pub struct Events {
data: Vec<Event>,
}
impl Events {
pub const fn new() -> Self {
Self { data: Vec::new() }
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn capacity(&self) -> usize {
self.data.capacity()
}
pub fn reserve(&mut self, cap: usize) {
self.data.reserve(cap.saturating_sub(self.data.capacity()));
}
pub fn as_slice(&self) -> &[Event] {
ops::Deref::deref(self)
}
pub fn as_slice_mut(&mut self) -> &mut [Event] {
ops::DerefMut::deref_mut(self)
}
pub fn clear(&mut self) {
self.data.clear();
}
pub fn push(&mut self, event: Event) {
if self.data.capacity() == self.data.len() {
let _g = crate::mute_guard(true);
self.data.reserve(1);
}
self.data.push(event);
}
pub fn allocs(&self) -> usize {
self.data
.iter()
.map(|e| match e {
Event::Alloc { .. } | Event::AllocZeroed { .. } => 1,
_ => 0,
})
.sum()
}
pub fn reallocs(&self) -> usize {
self.data
.iter()
.map(|e| match e {
Event::Realloc { .. } => 1,
_ => 0,
})
.sum()
}
pub fn frees(&self) -> usize {
self.data
.iter()
.map(|e| match e {
Event::Free { .. } => 1,
_ => 0,
})
.sum()
}
pub fn validate(&self, errors: &mut Vec<Violation>) {
let mut machine = Machine::default();
for event in self.as_slice() {
if let Err(e) = machine.push(event) {
errors.push(e);
}
}
for alloc in machine.trailing_regions() {
errors.push(Violation::Leaked { alloc });
}
}
pub fn max_memory_used(&self) -> Result<usize, Violation> {
let mut machine = Machine::default();
let mut max = 0usize;
for event in self.as_slice() {
machine.push(event)?;
max = usize::max(machine.memory_used, max);
}
Ok(max)
}
}
impl Default for Events {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl ops::Deref for Events {
type Target = [Event];
fn deref(&self) -> &[Event] {
ops::Deref::deref(&self.data)
}
}
impl ops::DerefMut for Events {
fn deref_mut(&mut self) -> &mut [Event] {
ops::DerefMut::deref_mut(&mut self.data)
}
}
impl<I: slice::SliceIndex<[Event]>> ops::Index<I> for Events {
type Output = I::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output {
std::ops::Index::index(&self.data, index)
}
}