use std::io::Write;
use std::sync::Mutex;
use std::sync::atomic::{AtomicBool, Ordering};
use serde_json::{Value, json};
static STREAMING: AtomicBool = AtomicBool::new(false);
pub fn enable() {
STREAMING.store(true, Ordering::Relaxed);
}
pub fn enabled() -> bool {
STREAMING.load(Ordering::Relaxed)
}
pub struct Progress {
step: &'static str,
total: usize,
done: Mutex<usize>,
}
impl Progress {
pub fn new(step: &'static str, total: usize) -> Self {
Progress {
step,
total,
done: Mutex::new(0),
}
}
pub fn tick(&self, detail: Value) {
if !enabled() {
return;
}
let mut done = self.done.lock().unwrap_or_else(|e| e.into_inner());
*done += 1;
let mut event =
json!({"event": "progress", "step": self.step, "done": *done, "total": self.total});
if let (Some(event), Value::Object(detail)) = (event.as_object_mut(), detail) {
event.extend(detail);
}
let mut out = std::io::stdout().lock();
let _ = writeln!(out, "{event}");
let _ = out.flush();
}
}