57 lines
1.4 KiB
Rust
57 lines
1.4 KiB
Rust
use std::{fs::File, os::unix::fs::MetadataExt as _, sync::mpsc};
|
|
|
|
use chrono::{DateTime, Local};
|
|
use egui::Id;
|
|
use eyre::{Context, ContextCompat};
|
|
use rand::{Rng, rng};
|
|
|
|
pub fn random_id() -> Id {
|
|
Id::new(rng().random::<u64>())
|
|
}
|
|
|
|
/// An [mpsc::Sender] where the receiver is the GUI.
|
|
#[derive(Clone)]
|
|
pub struct GuiSender<T> {
|
|
tx: mpsc::Sender<T>,
|
|
ctx: egui::Context,
|
|
}
|
|
|
|
impl<T> GuiSender<T> {
|
|
pub fn new(tx: mpsc::Sender<T>, ctx: &egui::Context) -> Self {
|
|
Self {
|
|
tx,
|
|
ctx: ctx.clone(),
|
|
}
|
|
}
|
|
|
|
pub fn send(&self, t: T) -> Result<(), mpsc::SendError<T>> {
|
|
self.tx.send(t)?;
|
|
self.ctx.request_repaint();
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[track_caller]
|
|
pub fn log_error<T>(chain: eyre::Report, f: impl FnOnce() -> eyre::Result<T>) -> Option<T> {
|
|
f().map_err(|e| e.wrap_err(chain))
|
|
.inspect_err(|e| log::error!("{e}"))
|
|
.ok()
|
|
}
|
|
|
|
pub fn file_mtime(file: &File) -> eyre::Result<DateTime<Local>> {
|
|
(move || {
|
|
let meta = file.metadata().wrap_err("Failed to stat file")?;
|
|
|
|
let sec = meta.mtime();
|
|
let nsec = meta
|
|
.mtime_nsec()
|
|
.try_into()
|
|
.wrap_err("Nanoseconds overflowed")?;
|
|
|
|
DateTime::from_timestamp(sec, nsec)
|
|
.wrap_err("Bad timestamp")
|
|
.map(Into::into)
|
|
})()
|
|
.wrap_err("Failed to get file mtime")
|
|
}
|