1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
//! Naive implementation of a MRU numbering scheme. use std::collections::LinkedList; #[derive(Clone, Debug, PartialEq, Eq)] pub enum Seen { /// The entry has already been seen, `N` calls to `access` ago. So if /// we call `access(foo)` twice in a row, the second call will return /// `Age(0)`. Age(usize), /// The entry has never been seen. Never(usize), } /// A structure used to access values with repeated patterns. /// /// ``` /// use binjs_shared::mru::{ MRU, Seen }; /// /// let mut mru = MRU::new(); /// /// assert_eq!(mru.access(&'a'), Seen::Never(0), "Introducing a"); /// assert_eq!(mru.access(&'a'), Seen::Age(0), "Just introduced a"); /// assert_eq!(mru.access(&'a'), Seen::Age(0), "Just accessed a"); /// assert_eq!(mru.access(&'b'), Seen::Never(1), "Introducing b"); /// assert_eq!(mru.access(&'b'), Seen::Age(0), "Just introduced b"); /// assert_eq!(mru.access(&'a'), Seen::Age(1), "Accessing previous a"); /// assert_eq!(mru.access(&'a'), Seen::Age(0), "Just accessed a again"); /// assert_eq!(mru.access(&'c'), Seen::Never(2), "Just introduced c"); /// assert_eq!(mru.access(&'a'), Seen::Age(1), "Accessing previous a, again"); /// assert_eq!(mru.access(&'a'), Seen::Age(0), "Accessing previous a, again"); /// assert_eq!(mru.access(&'b'), Seen::Age(2), "Accessing previous b"); ///``` pub struct MRU<T> where T: Eq + Clone, { items: LinkedList<T>, } impl<T> MRU<T> where T: Eq + Clone, { pub fn new() -> Self { Self { items: LinkedList::new(), } } pub fn access(&mut self, value: &T) -> Seen { let position = self.items.iter().position(|x| x == value); match position { None => { let len = self.items.len(); self.items.push_front(value.clone()); Seen::Never(len) } Some(0) => Seen::Age(0), Some(position) => { // Remove item from position `position`. let mut suffix = self.items.split_off(position); let hd = suffix.pop_front().unwrap(); assert!(&hd == value); self.items.append(&mut suffix); // Add it at position 0. self.items.push_front(hd); Seen::Age(position) } } } }