use std::sync::atomic::{AtomicUsize, Ordering};
#[derive(Debug, Copy, Clone, Eq, PartialEq, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub struct Scope {
pub id: usize,
pub marker: Marker,
}
impl Scope {
pub fn new(id: usize, marker: Marker) -> Self {
Self { id, marker }
}
pub fn is_start(&self) -> bool {
matches!(self.marker, Marker::Start)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Marker {
Start,
End,
}
pub trait SupplyScopeGenerator {
type ScopeGen: ScopeGenerator;
fn scope_generator(&self) -> &Self::ScopeGen;
}
pub trait ScopeGenerator {
fn generate(&self) -> (Scope, Scope);
}
pub struct ScopeCounter {
counter: AtomicUsize,
}
impl ScopeCounter {
pub const fn new() -> Self {
Self {
counter: AtomicUsize::new(0),
}
}
}
impl ScopeGenerator for ScopeCounter {
fn generate(&self) -> (Scope, Scope) {
let id = self.counter.fetch_add(1, Ordering::Relaxed);
(Scope::new(id, Marker::Start), Scope::new(id, Marker::End))
}
}
#[cfg(test)]
#[derive(Default)]
pub struct TestScopeGenerator;
#[cfg(test)]
impl ScopeGenerator for TestScopeGenerator {
fn generate(&self) -> (Scope, Scope) {
let id = 0;
(Scope::new(id, Marker::Start), Scope::new(id, Marker::End))
}
}
#[cfg(test)]
mod tests {
use crate::reporter::event::scope::{ScopeCounter, ScopeGenerator};
use crate::reporter::event::Marker;
use std::sync::atomic::Ordering;
#[test]
fn unused() {
let gen = ScopeCounter::new();
assert_eq!(gen.counter.load(Ordering::Relaxed), 0);
}
#[test]
fn first_id() {
let gen = ScopeCounter::new();
let (start, end) = gen.generate();
assert_eq!(start.id, 0);
assert_eq!(end.id, 0);
assert_eq!(start.marker, Marker::Start);
assert_eq!(end.marker, Marker::End);
}
#[test]
fn second_id() {
let gen = ScopeCounter::new();
let (start, end) = gen.generate();
assert_eq!(start.id, 0);
assert_eq!(end.id, 0);
assert_eq!(start.marker, Marker::Start);
assert_eq!(end.marker, Marker::End);
let (start, end) = gen.generate();
assert_eq!(start.id, 1);
assert_eq!(end.id, 1);
assert_eq!(start.marker, Marker::Start);
assert_eq!(end.marker, Marker::End);
}
#[test]
fn thousand() {
let gen = ScopeCounter::new();
for _ in 0..1000 {
gen.generate();
}
let (start, end) = gen.generate();
assert_eq!(start.id, 1000);
assert_eq!(end.id, 1000);
assert_eq!(start.marker, Marker::Start);
assert_eq!(end.marker, Marker::End);
}
}