/*! Filter duplicate shows of credentials and open invitations by id (which will typically be a Scalar). This implementation just keeps the table of seen ids in memory, but a production one would of course use a disk-backed database. */ use std::cmp::Eq; use std::collections::HashMap; use std::hash::Hash; /// Each instance of DupFilter maintains its own independent table of /// seen ids. IdType will typically be Scalar. #[derive(Default, Debug)] pub struct DupFilter { seen_table: HashMap, } /// A return type indicating whether the item was fresh (not previously /// seen) or previously seen #[derive(PartialEq, Eq, Debug)] pub enum SeenType { Fresh, Seen, } impl DupFilter { /// Check to see if the id is in the seen table, but do not add it /// to the seen table. Return Seen if it is already in the table, /// Fresh if not. pub fn check(&self, id: &IdType) -> SeenType { if self.seen_table.contains_key(id) { SeenType::Seen } else { SeenType::Fresh } } /// As atomically as possible, check to see if the id is in the seen /// table, and add it if not. Return Fresh if it was not already /// in the table, and Seen if it was. pub fn filter(&mut self, id: &IdType) -> SeenType { match self.seen_table.insert(*id, ()) { None => SeenType::Fresh, Some(()) => SeenType::Seen, } } }