use std::collections::HashMap;
use std::fmt::{Debug, Formatter};
use spin::RwLock;
use crate::backend::pprofrs::frames::Frames;
use crate::backend::pprofrs::profiler::Profiler;
use crate::backend::pprofrs::{Error, Result};
pub struct Report {
pub data: HashMap<Frames, isize>,
}
type FramesPostProcessor = Box<dyn Fn(&mut Frames)>;
pub struct ReportBuilder<'a> {
frames_post_processor: Option<FramesPostProcessor>,
profiler: &'a RwLock<Result<Profiler>>,
}
impl<'a> ReportBuilder<'a> {
pub(crate) fn new(profiler: &'a RwLock<Result<Profiler>>) -> Self {
Self {
frames_post_processor: None,
profiler,
}
}
pub fn build_and_clear(&self, clear: bool) -> Result<Report> {
let mut hash_map = HashMap::new();
match self.profiler.write().as_mut() {
Err(err) => {
log::error!("Error in creating profiler: {}", err);
Err(Error::Creating)
}
Ok(profiler) => {
profiler.data.try_iter()?.for_each(|entry| {
let count = entry.count;
if count > 0 {
let mut key = Frames::from(entry.item.clone());
if let Some(processor) = &self.frames_post_processor {
processor(&mut key);
}
match hash_map.get_mut(&key) {
Some(value) => {
*value += count;
}
None => {
match hash_map.insert(key, count) {
None => {}
Some(_) => {
unreachable!();
}
};
}
}
}
});
if clear {
profiler.clear()?;
}
Ok(Report { data: hash_map })
}
}
}
}
impl Debug for Report {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
for (key, val) in self.data.iter() {
write!(f, "{key:?} {val}")?;
writeln!(f)?;
}
Ok(())
}
}