use std::time::{Duration, Instant};
#[derive(Debug, Clone, Default)]
pub struct StatusMessage {
message: Option<String>,
set_at: Option<Instant>,
auto_clear_after: Option<Duration>,
}
impl StatusMessage {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub const fn with_auto_clear(duration: Duration) -> Self {
Self {
message: None,
set_at: None,
auto_clear_after: Some(duration),
}
}
pub fn set(&mut self, msg: impl Into<String>) {
self.message = Some(msg.into());
self.set_at = Some(Instant::now());
}
pub fn clear(&mut self) {
self.message = None;
self.set_at = None;
}
pub fn message(&mut self) -> Option<&str> {
if let (Some(set_at), Some(duration)) = (self.set_at, self.auto_clear_after)
&& set_at.elapsed() >= duration
{
self.message = None;
self.set_at = None;
}
self.message.as_deref()
}
#[must_use]
pub fn peek(&self) -> Option<&str> {
self.message.as_deref()
}
#[must_use]
pub const fn has_message(&self) -> bool {
self.message.is_some()
}
#[must_use]
pub const fn as_option(&self) -> &Option<String> {
&self.message
}
pub const fn take(&mut self) -> Option<String> {
self.set_at = None;
self.message.take()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::thread;
#[test]
fn test_status_message_set_clear() {
let mut status = StatusMessage::new();
assert!(!status.has_message());
assert!(status.peek().is_none());
status.set("Test message");
assert!(status.has_message());
assert_eq!(status.peek(), Some("Test message"));
status.clear();
assert!(!status.has_message());
assert!(status.peek().is_none());
}
#[test]
fn test_status_message_take() {
let mut status = StatusMessage::new();
status.set("Take me");
let taken = status.take();
assert_eq!(taken, Some("Take me".to_string()));
assert!(!status.has_message());
}
#[test]
fn test_status_message_auto_clear() {
let mut status = StatusMessage::with_auto_clear(Duration::from_millis(50));
status.set("Auto clear message");
assert!(status.message().is_some());
thread::sleep(Duration::from_millis(60));
assert!(status.message().is_none());
}
#[test]
fn test_status_message_no_auto_clear_default() {
let mut status = StatusMessage::new();
status.set("No auto clear");
thread::sleep(Duration::from_millis(10));
assert!(status.message().is_some()); }
}