Browse Source

Add dup_filter

onyinyang 8 months ago
parent
commit
d6a3503e2c
1 changed files with 48 additions and 0 deletions
  1. 48 0
      src/dup_filter.rs

+ 48 - 0
src/dup_filter.rs

@@ -0,0 +1,48 @@
+/*! 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::collections::HashSet;
+use std::hash::Hash;
+
+use serde::{Deserialize, Serialize};
+
+/// Each instance of DupFilter maintains its own independent table of
+/// seen ids. IdType will typically be Scalar.
+#[derive(Default, Debug, Clone, Serialize, Deserialize)]
+pub struct DupFilter<IdType: Hash + Eq + Copy + Serialize> {
+    seen_table: HashSet<IdType>,
+}
+
+/// 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<IdType: Hash + Eq + Copy + Serialize> DupFilter<IdType> {
+    /// 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(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) {
+            true => SeenType::Fresh,
+            false => SeenType::Seen,
+        }
+    }
+}