use std::io;
use fxhash::FxHashMap;
use std::cell::RefCell;
use crate::filters::Filter;
#[derive(Clone, Debug, Eq)]
pub struct Counters {
events: RefCell<FxHashMap<&'static str, u64>>
}
impl std::cmp::PartialEq for Counters {
fn eq(&self, _other: &Self) -> bool { true }
}
impl std::hash::Hash for Counters {
fn hash<H>(&self, _state: &mut H) where H: std::hash::Hasher {}
}
impl Counters {
pub fn new() -> Self {
Counters {
events: RefCell::new(FxHashMap::default()),
}
}
pub fn with_capacity(cap: usize) -> Self {
let mut events = FxHashMap::default();
events.reserve(cap);
Counters { events: RefCell::new(events) }
}
pub fn event(&self, key: &'static str) {
*self.events.borrow_mut().entry(key.into()).or_insert(0) += 1
}
pub fn set(&self, key: &'static str, value: u64) {
self.events.borrow_mut().insert(key.into(), value);
}
pub fn reset_event(&self, key: &'static str) {
self.events.borrow_mut().insert(key.into(), 0);
}
pub fn reset_events<F: Filter>(&self, mut filter: F) {
self.events.borrow_mut().retain(|key, val| !filter.apply(key, *val));
}
pub fn reset_all(&self) {
self.events.borrow_mut().clear();
}
pub fn retain<F: Filter>(&self, mut filter: F) {
self.events.borrow_mut().retain(|key, val| filter.apply(key, *val));
}
pub fn get(&self, key: &'static str) -> u64 {
self.events.borrow().get(key).cloned().unwrap_or(0)
}
pub fn accumulate<F: Filter>(&self, mut filter: F) -> u64 {
let mut n = 0;
for (key, value) in self.events.borrow().iter() {
if filter.apply(key, *value) {
n += value
}
}
n
}
pub fn print<F: Filter>(&self, mut filter: F, to: &mut io::Write) -> io::Result<()> {
for (key, value) in self.events.borrow().iter() {
if filter.apply(key, *value) {
writeln!(to, "{}: {}", key, value)?;
}
}
Ok(())
}
pub fn print_to_stdout<F: Filter>(&self, filter: F) {
let stdout = io::stdout();
let mut to = stdout.lock();
self.print(filter, &mut to).unwrap();
}
pub fn append(&self, other: &Counters) {
for (key, value) in other.events.borrow_mut().drain() {
*self.events.borrow_mut().entry(key).or_insert(0) += value;
}
}
pub fn apply<F: Filter, Cb: FnMut(&'static str, u64) -> u64>(&self, mut filter: F, mut callback: Cb) {
for (key, value) in self.events.borrow_mut().iter_mut() {
if filter.apply(key, *value) {
*value = callback(key, *value);
}
}
}
}
#[cfg(feature = "dummy_serialization")]
use serde::{Serialize, Deserialize};
#[cfg(feature = "dummy_serialization")]
use crate::Dummy;
#[cfg(feature = "dummy_serialization")]
impl Serialize for Counters {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: serde::Serializer {
Dummy.serialize(serializer)
}
}
#[cfg(feature = "dummy_serialization")]
impl<'de> Deserialize<'de> for Counters {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: serde::Deserializer<'de> {
Dummy::deserialize(deserializer)?;
Ok(Counters::new())
}
}