use std::sync::mpsc::Receiver;
use std::sync::mpsc::TryRecvError;
use crate::reminder::Reminder;
#[derive(Debug)]
pub(crate) struct Reminders {
remind_recv: Receiver<Reminder>,
reminders: Vec<Reminder>,
}
impl Reminders {
pub fn new(remind_recv: Receiver<Reminder>, reminder: Reminder) -> Self {
Self {
remind_recv,
reminders: vec![reminder],
}
}
pub fn try_recv(&mut self) -> Result<(), ()> {
let result = self.remind_recv.try_recv();
let reminder = match result {
Ok(reminder) => reminder,
Err(TryRecvError::Empty) => {
return Ok(())
},
Err(TryRecvError::Disconnected) => {
return Err(())
},
};
let result = self
.reminders
.binary_search_by(|r| r.cmp(&reminder).reverse());
match result {
Ok(..) => {
},
Err(idx) => {
let () = self.reminders.insert(idx, reminder);
},
}
Ok(())
}
#[inline]
pub fn next_reminder(&self) -> Option<&Reminder> {
self.reminders.last()
}
#[inline]
pub fn remove_next(&mut self) {
let _reminder = self.reminders.pop();
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::mpsc::channel;
use std::time::Duration;
use std::time::UNIX_EPOCH;
fn reminder(secs: u64, msg: &str) -> Reminder {
Reminder {
time: UNIX_EPOCH + Duration::from_secs(secs),
message: msg.to_string(),
}
}
#[test]
fn initial_reminder_retrieval() {
let (_tx, rx) = channel();
let r = reminder(10, "initial");
let reminders = Reminders::new(rx, r.clone());
assert_eq!(reminders.next_reminder(), Some(&r));
}
#[test]
fn no_reminder_receive() {
let (_tx, rx) = channel();
let mut reminders = Reminders::new(rx, reminder(10, "initial"));
assert_eq!(reminders.try_recv(), Ok(()));
assert_eq!(reminders.next_reminder().unwrap().message, "initial");
}
#[test]
fn disconnected_channel_receive() {
let (tx, rx) = channel::<Reminder>();
let mut reminders = Reminders::new(rx, reminder(10, "initial"));
drop(tx);
assert_eq!(reminders.try_recv(), Err(()));
}
#[test]
fn reminder_ordering() {
let (tx, rx) = channel();
let initial = reminder(20, "20");
let mut reminders = Reminders::new(rx, initial);
let () = tx.send(reminder(10, "10")).unwrap();
let () = reminders.try_recv().unwrap();
let () = tx.send(reminder(30, "30")).unwrap();
let () = reminders.try_recv().unwrap();
assert_eq!(reminders.next_reminder().unwrap().message, "10");
let () = reminders.remove_next();
assert_eq!(reminders.next_reminder().unwrap().message, "20");
let () = reminders.remove_next();
assert_eq!(reminders.next_reminder().unwrap().message, "30");
}
#[test]
fn duplicate_reminder_ignoring() {
let (tx, rx) = channel();
let r = reminder(10, "duplicate");
let mut reminders = Reminders::new(rx, r.clone());
let () = tx.send(r).unwrap();
let () = reminders.try_recv().unwrap();
let () = reminders.remove_next();
assert_eq!(reminders.next_reminder(), None);
}
#[test]
fn remove_next_on_empty_container_is_safe() {
let (_tx, rx) = channel();
let mut reminders = Reminders::new(rx, reminder(10, "10"));
let () = reminders.remove_next();
let () = reminders.remove_next();
assert_eq!(reminders.next_reminder(), None);
}
}