summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-06-26 19:34:14 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-06-26 19:34:14 +0700
commitc8bba37510f01f116fea99204e934d35863a9d2b (patch)
tree799f39da3e8b2dc53a94b4f5e735626a83c8f7ef
parentReorganize test vector tests (diff)
downloadBouncyCastle.NET-ed25519-c8bba37510f01f116fea99204e934d35863a9d2b.tar.xz
Add store/selector API
-rw-r--r--crypto/src/util/collections/CollectionUtilities.cs38
-rw-r--r--crypto/src/util/collections/ISelector.cs16
-rw-r--r--crypto/src/util/collections/IStore.cs15
-rw-r--r--crypto/src/util/collections/StoreImpl.cs25
4 files changed, 90 insertions, 4 deletions
diff --git a/crypto/src/util/collections/CollectionUtilities.cs b/crypto/src/util/collections/CollectionUtilities.cs
index 37551e5b3..426700903 100644
--- a/crypto/src/util/collections/CollectionUtilities.cs
+++ b/crypto/src/util/collections/CollectionUtilities.cs
@@ -15,6 +15,36 @@ namespace Org.BouncyCastle.Utilities.Collections
             }
         }
 
+        public static void CollectMatches<T>(ICollection<T> matches, ISelector<T> selector, params IStore<T>[] stores)
+        {
+            CollectMatches(matches, selector, stores);
+        }
+
+        public static void CollectMatches<T>(ICollection<T> matches, ISelector<T> selector,
+            IEnumerable<IStore<T>> stores)
+        {
+            if (matches == null)
+                throw new ArgumentNullException(nameof(matches));
+            if (stores == null)
+                return;
+
+            foreach (var store in stores)
+            {
+                if (store == null)
+                    continue;
+
+                foreach (T match in store.EnumerateMatches(selector))
+                {
+                    matches.Add(match);
+                }
+            }
+        }
+
+        public static IStore<T> CreateStore<T>(IEnumerable<T> contents)
+        {
+            return new StoreImpl<T>(contents);
+        }
+
         public static IEnumerable Proxy(IEnumerable e)
         {
             return new EnumerableProxy(e);
@@ -48,18 +78,18 @@ namespace Org.BouncyCastle.Utilities.Collections
             return e.Current;
         }
 
-        public static string ToString(IEnumerable c)
+        public static string ToString<T>(IEnumerable<T> c)
         {
-            IEnumerator e = c.GetEnumerator();
+            IEnumerator<T> e = c.GetEnumerator();
             if (!e.MoveNext())
                 return "[]";
 
             StringBuilder sb = new StringBuilder("[");
-            sb.Append(e.Current.ToString());
+            sb.Append(e.Current);
             while (e.MoveNext())
             {
                 sb.Append(", ");
-                sb.Append(e.Current.ToString());
+                sb.Append(e.Current);
             }
             sb.Append(']');
             return sb.ToString();
diff --git a/crypto/src/util/collections/ISelector.cs b/crypto/src/util/collections/ISelector.cs
new file mode 100644
index 000000000..186b922d3
--- /dev/null
+++ b/crypto/src/util/collections/ISelector.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+    /// <summary>Interface for matching objects in an <see cref="IStore{T}"/>.</summary>
+    /// <typeparam name="T">The contravariant type of selectable objects.</typeparam>
+    public interface ISelector<in T>
+        : ICloneable
+    {
+        /// <summary>Match the passed in object, returning true if it would be selected by this selector, false
+        /// otherwise.</summary>
+        /// <param name="candidate">The object to be matched.</param>
+        /// <returns><code>true</code> if the objects is matched by this selector, false otherwise.</returns>
+        bool Match(T candidate);
+    }
+}
diff --git a/crypto/src/util/collections/IStore.cs b/crypto/src/util/collections/IStore.cs
new file mode 100644
index 000000000..12c19aaf4
--- /dev/null
+++ b/crypto/src/util/collections/IStore.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+    /// <summary>A generic interface describing a simple store of objects.</summary>
+    /// <typeparam name="T">The covariant type of stored objects.</typeparam>
+    public interface IStore<out T>
+    {
+        /// <summary>Enumerate the (possibly empty) collection of objects matched by the given selector.</summary>
+        /// <param name="selector">The <see cref="ISelector{T}"/> used to select matching objects.</param>
+        /// <returns>An <see cref="IEnumerable{T}"/> of the matching objects.</returns>
+        IEnumerable<T> EnumerateMatches(ISelector<T> selector);
+    }
+}
diff --git a/crypto/src/util/collections/StoreImpl.cs b/crypto/src/util/collections/StoreImpl.cs
new file mode 100644
index 000000000..3a7135007
--- /dev/null
+++ b/crypto/src/util/collections/StoreImpl.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+    internal sealed class StoreImpl<T>
+        : IStore<T>
+    {
+        private readonly List<T> m_contents;
+
+        internal StoreImpl(IEnumerable<T> e)
+        {
+            m_contents = new List<T>(e);
+        }
+
+        IEnumerable<T> IStore<T>.EnumerateMatches(ISelector<T> selector)
+        {
+            foreach (T candidate in m_contents)
+            {
+                if (selector == null || selector.Match(candidate))
+                    yield return candidate;
+            }
+        }
+    }
+}