use std::collections::HashMap;
use utils::sync::Mutex;
use super::ResourceId;
#[derive(
Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize,
)]
pub enum ResourceTraceLevel {
Info,
Warn,
Error,
}
#[derive(
Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize,
)]
pub struct ResourceTraceItem {
level: ResourceTraceLevel,
message: String,
}
impl ResourceTraceItem {
pub fn new(level: ResourceTraceLevel, message: String) -> Self {
Self { level, message }
}
pub fn level(&self) -> ResourceTraceLevel {
self.level
}
pub fn message(&self) -> &str {
&self.message
}
}
#[derive(Default)]
pub struct ResourceTrace {
items: Mutex<HashMap<String, Vec<ResourceTraceItem>>>,
}
impl ResourceTrace {
pub fn items(&self, id: &str) -> Vec<ResourceTraceItem> {
self.items.lock().get(id).cloned().unwrap_or_default()
}
pub fn resource_ids(&self) -> Vec<String> {
let mut ids = self.items.lock().keys().cloned().collect::<Vec<_>>();
ids.sort_unstable();
ids
}
pub(crate) fn clear(&self, id: ResourceId<'_>) {
self.items.lock().remove(id.as_ref());
}
pub(crate) fn record(&self, id: ResourceId<'_>, level: ResourceTraceLevel, message: String) {
let mut traces = self.items.lock();
let item = ResourceTraceItem::new(level, message);
if let Some(items) = traces.get_mut(id.as_ref()) {
items.push(item);
} else {
traces.insert(id.to_string(), vec![item]);
}
}
pub(crate) fn has_error(&self, id: ResourceId<'_>) -> bool {
self.items
.lock()
.get(id.as_ref())
.is_some_and(|items| items.iter().any(|item| item.level == ResourceTraceLevel::Error))
}
}