use std::{ cmp::{Ordering, Reverse}, ops::Deref, }; use serde::Serialize; #[derive(Debug, Clone, Serialize)] pub struct Item { pub novel: String, pub post_at: jiff::Zoned, } pub struct Closest<'a> { queue: &'a mut Queue, } impl<'a> Closest<'a> { pub fn try_pop(self, now: &jiff::Zoned) -> Option { let last = self.queue.entries.pop().unwrap(); if now >= &last.post_at { Some(last) } else { self.queue.entries.push(last); None } } } impl<'a> Deref for Closest<'a> { type Target = Item; fn deref(&self) -> &Self::Target { let len = self.queue.entries.len() - 1; &self.queue.entries[len] } } fn cmp_items(lhs: &Item, rhs: &Item) -> Ordering { Reverse(&lhs.post_at).cmp(&Reverse(&rhs.post_at)) } #[derive(Debug, Default)] pub struct Queue { entries: Vec, } impl FromIterator for Queue { fn from_iter>(iter: T) -> Self { let mut entries: Vec = iter.into_iter().collect(); entries.sort_unstable_by(cmp_items); #[cfg(debug_assertions)] if entries.len() >= 2 { let first = &entries[0].post_at; let second = &entries[1].post_at; assert!(first >= second); } Self { entries } } } impl Queue { pub fn len(&self) -> usize { self.entries.len() } pub fn closest(&self) -> Option<&Item> { self.entries.last() } pub fn closest_mut(&mut self) -> Option> { if self.entries.is_empty() { None } else { Some(Closest { queue: self }) } } pub fn add(&mut self, item: Item) { // This could be: // let Ok(idx) | Err(idx) = ..; // But fuck rust, it's not allowed. let res = self .entries .binary_search_by(|probe| cmp_items(probe, &item)); // The why блядь? let idx = match res { Ok(i) => i, Err(i) => i, }; self.entries.insert(idx, item); } pub const fn new() -> Self { Self { entries: Vec::new(), } } }