#[cfg(not(native_cache))]
use super::disabled as session;
#[cfg(native_cache)]
use super::session;
use super::{Record, RecordEffect, Stamp, base::write_stamped};
use alloc::string::String;
use core::time::Duration;
use serde::{Deserialize, Serialize};
#[must_use = "a span records nothing until it is closed"]
#[derive(Debug)]
pub struct Span {
start: Stamp,
}
impl Span {
pub fn new() -> Option<Self> {
session::stamp().map(|start| Self { start })
}
pub fn elapsed(&self) -> Option<Duration> {
session::offset(self.start.session).map(|now| now.saturating_sub(self.start.offset))
}
pub fn close<R: Record + Serialize>(self, effect: RecordEffect, record: &R) -> bool {
write_stamped(self.start, effect, record)
}
}
#[must_use = "a mark records the span until it is dropped"]
#[derive(Debug)]
pub struct Mark {
label: String,
span: Option<Span>,
}
impl Mark {
pub fn new<S: Into<String>>(label: S) -> Self {
let span = Span::new();
let label = match span {
Some(_) => label.into(),
None => String::new(),
};
Self { label, span }
}
}
impl Drop for Mark {
fn drop(&mut self) {
let Some(span) = self.span.take() else {
return;
};
let Some(wall) = span.elapsed() else {
return;
};
let record = MarkRecord {
label: core::mem::take(&mut self.label),
wall,
};
span.close(RecordEffect::Observed, &record);
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MarkRecord {
pub label: String,
pub wall: Duration,
}
impl Record for MarkRecord {
const KIND: &'static str = "marks";
}