From e8f6a40166eb3084a4bfe1c48939a7bd560c20cc Mon Sep 17 00:00:00 2001
From: Xiliang Chen <xlchen1291@gmail.com>
Date: Thu, 14 May 2020 16:43:12 +1200
Subject: [PATCH] ordered set (#160)

---
 schedule-update/Cargo.toml   |   2 +
 utilities/src/lib.rs         |   1 +
 utilities/src/ordered_set.rs | 131 +++++++++++++++++++++++++++++++++++
 3 files changed, 134 insertions(+)
 create mode 100644 utilities/src/ordered_set.rs

diff --git a/schedule-update/Cargo.toml b/schedule-update/Cargo.toml
index 40523d6..3d9814a 100644
--- a/schedule-update/Cargo.toml
+++ b/schedule-update/Cargo.toml
@@ -20,6 +20,8 @@ sp-io = { version = "2.0.0-alpha.6", default-features = false }
 sp-core = { version = "2.0.0-alpha.6", default-features = false }
 pallet-balances = { version = "2.0.0-alpha.6" }
 
+clear_on_drop = { version = "0.2.3", features = ["no_cc"] }	# https://github.com/paritytech/substrate/issues/4179
+
 [features]
 default = ["std"]
 std = [
diff --git a/utilities/src/lib.rs b/utilities/src/lib.rs
index a99a484..910f988 100644
--- a/utilities/src/lib.rs
+++ b/utilities/src/lib.rs
@@ -2,6 +2,7 @@
 
 pub mod fixed_u128;
 pub mod linked_item;
+pub mod ordered_set;
 
 pub use fixed_u128::FixedU128;
 pub use linked_item::{LinkedItem, LinkedList};
diff --git a/utilities/src/ordered_set.rs b/utilities/src/ordered_set.rs
new file mode 100644
index 0000000..56ec866
--- /dev/null
+++ b/utilities/src/ordered_set.rs
@@ -0,0 +1,131 @@
+use codec::{Decode, Encode};
+use sp_runtime::RuntimeDebug;
+use sp_std::prelude::*;
+
+#[derive(RuntimeDebug, PartialEq, Eq, Encode, Decode, Default)]
+pub struct OrderedSet<T>(Vec<T>);
+
+impl<T: Ord> OrderedSet<T> {
+	pub fn new() -> Self {
+		Self(Vec::new())
+	}
+
+	pub fn from(mut v: Vec<T>) -> Self {
+		v.sort();
+		v.dedup();
+		Self::from_sorted_set(v)
+	}
+
+	/// Assume v is sorted and contain unique elements
+	pub fn from_sorted_set(v: Vec<T>) -> Self {
+		Self(v)
+	}
+
+	pub fn insert(&mut self, value: T) -> bool {
+		match self.0.binary_search(&value) {
+			Ok(_) => false,
+			Err(loc) => {
+				self.0.insert(loc, value);
+				true
+			}
+		}
+	}
+
+	pub fn remove(&mut self, value: &T) -> bool {
+		match self.0.binary_search(&value) {
+			Ok(loc) => {
+				self.0.remove(loc);
+				true
+			}
+			Err(_) => false,
+		}
+	}
+
+	pub fn contains(&self, value: &T) -> bool {
+		self.0.binary_search(&value).is_ok()
+	}
+
+	pub fn clear(&mut self) {
+		self.0.clear();
+	}
+}
+
+impl<T: Ord> From<Vec<T>> for OrderedSet<T> {
+	fn from(v: Vec<T>) -> Self {
+		Self::from(v)
+	}
+}
+
+#[cfg(test)]
+mod tests {
+	use super::*;
+
+	#[test]
+	fn from() {
+		let v = vec![4, 2, 3, 4, 3, 1];
+		let set: OrderedSet<i32> = v.into();
+		assert_eq!(set, OrderedSet::from(vec![1, 2, 3, 4]));
+	}
+
+	#[test]
+	fn insert() {
+		let mut set: OrderedSet<i32> = OrderedSet::new();
+		assert_eq!(set, OrderedSet::from(vec![]));
+
+		assert_eq!(set.insert(1), true);
+		assert_eq!(set, OrderedSet::from(vec![1]));
+
+		assert_eq!(set.insert(5), true);
+		assert_eq!(set, OrderedSet::from(vec![1, 5]));
+
+		assert_eq!(set.insert(3), true);
+		assert_eq!(set, OrderedSet::from(vec![1, 3, 5]));
+
+		assert_eq!(set.insert(3), false);
+		assert_eq!(set, OrderedSet::from(vec![1, 3, 5]));
+	}
+
+	#[test]
+	fn remove() {
+		let mut set: OrderedSet<i32> = OrderedSet::from(vec![1, 2, 3, 4]);
+
+		assert_eq!(set.remove(&5), false);
+		assert_eq!(set, OrderedSet::from(vec![1, 2, 3, 4]));
+
+		assert_eq!(set.remove(&1), true);
+		assert_eq!(set, OrderedSet::from(vec![2, 3, 4]));
+
+		assert_eq!(set.remove(&3), true);
+		assert_eq!(set, OrderedSet::from(vec![2, 4]));
+
+		assert_eq!(set.remove(&3), false);
+		assert_eq!(set, OrderedSet::from(vec![2, 4]));
+
+		assert_eq!(set.remove(&4), true);
+		assert_eq!(set, OrderedSet::from(vec![2]));
+
+		assert_eq!(set.remove(&2), true);
+		assert_eq!(set, OrderedSet::from(vec![]));
+
+		assert_eq!(set.remove(&2), false);
+		assert_eq!(set, OrderedSet::from(vec![]));
+	}
+
+	#[test]
+	fn contains() {
+		let set: OrderedSet<i32> = OrderedSet::from(vec![1, 2, 3, 4]);
+
+		assert_eq!(set.contains(&5), false);
+
+		assert_eq!(set.contains(&1), true);
+
+		assert_eq!(set.contains(&3), true);
+	}
+
+	#[test]
+	fn clear() {
+		let mut set: OrderedSet<i32> = OrderedSet::from(vec![1, 2, 3, 4]);
+		set.clear();
+		assert_eq!(set, OrderedSet::new());
+	}
+}
-- 
GitLab