#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Notice {
Info(String),
Error(String),
Synced {
deleted: usize,
updated: usize,
},
NewMail(String),
}
impl Notice {
pub fn is_error(&self) -> bool {
matches!(self, Notice::Error(_))
}
pub fn is_new_mail(&self) -> bool {
matches!(self, Notice::NewMail(_))
}
pub fn text(&self) -> String {
match self {
Notice::Info(msg) | Notice::Error(msg) | Notice::NewMail(msg) => msg.clone(),
Notice::Synced { deleted, updated } => {
format!("synced: {deleted} deleted, {updated} updated")
}
}
}
}
pub trait NoticeSink {
fn notice(&mut self, notice: Notice);
fn latest(&self) -> Option<&Notice>;
fn clear(&mut self);
}
#[derive(Debug, Clone, Default)]
pub struct Log(std::rc::Rc<std::cell::RefCell<Vec<Notice>>>);
impl Log {
pub fn notices(&self) -> Vec<Notice> {
self.0.borrow().clone()
}
pub fn last_text(&self) -> String {
self.0.borrow().last().map(Notice::text).unwrap_or_default()
}
pub fn said(&self, needle: &str) -> bool {
self.0.borrow().iter().any(|n| n.text().contains(needle))
}
}
impl NoticeSink for Log {
fn notice(&mut self, notice: Notice) {
self.0.borrow_mut().push(notice);
}
fn latest(&self) -> Option<&Notice> {
None
}
fn clear(&mut self) {
self.0.borrow_mut().clear();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn synced_reads_as_prose() {
let notice = Notice::Synced {
deleted: 2,
updated: 3,
};
assert_eq!(notice.text(), "synced: 2 deleted, 3 updated");
assert!(!notice.is_error());
}
#[test]
fn new_mail_is_prose_a_bell_can_recognize() {
let notice = Notice::NewMail("new mail in inbox (+2)".into());
assert_eq!(notice.text(), "new mail in inbox (+2)");
assert!(notice.is_new_mail() && !notice.is_error());
assert!(!Notice::Info("x".into()).is_new_mail());
}
#[test]
fn a_log_keeps_the_order_and_a_handle_reads_it() {
let log = Log::default();
let mut handle = log.clone();
handle.notice(Notice::Info("first".into()));
handle.notice(Notice::Error("second".into()));
assert_eq!(log.notices().len(), 2);
assert_eq!(log.last_text(), "second");
assert!(log.said("fir"));
handle.clear();
assert_eq!(log.notices(), vec![]);
}
}