index.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. //! WS Index
  2. use std::fmt::Debug;
  3. use std::ops::Deref;
  4. use std::sync::atomic::{AtomicUsize, Ordering};
  5. use super::SubId;
  6. /// Indexable trait
  7. pub trait Indexable {
  8. /// The type of the index, it is unknown and it is up to the Manager's
  9. /// generic type
  10. type Index: Clone + PartialOrd + Ord + Send + Sync + Debug;
  11. /// To indexes
  12. fn to_indexes(&self) -> Vec<Index<Self::Index>>;
  13. }
  14. #[derive(Debug, Ord, PartialOrd, PartialEq, Eq, Clone)]
  15. /// Index
  16. ///
  17. /// The Index is a sorted structure that is used to quickly find matches
  18. ///
  19. /// The counter is used to make sure each Index is unique, even if the prefix
  20. /// are the same, and also to make sure that earlier indexes matches first
  21. pub struct Index<T>
  22. where
  23. T: PartialOrd + Ord + Send + Sync + Debug,
  24. {
  25. prefix: T,
  26. counter: SubscriptionGlobalId,
  27. id: super::SubId,
  28. }
  29. impl<T> From<&Index<T>> for super::SubId
  30. where
  31. T: PartialOrd + Ord + Send + Sync + Debug,
  32. {
  33. fn from(val: &Index<T>) -> Self {
  34. val.id.clone()
  35. }
  36. }
  37. impl<T> Deref for Index<T>
  38. where
  39. T: PartialOrd + Ord + Send + Sync + Debug,
  40. {
  41. type Target = T;
  42. fn deref(&self) -> &Self::Target {
  43. &self.prefix
  44. }
  45. }
  46. impl<T> Index<T>
  47. where
  48. T: PartialOrd + Ord + Send + Sync + Debug,
  49. {
  50. /// Compare the
  51. pub fn cmp_prefix(&self, other: &Index<T>) -> std::cmp::Ordering {
  52. self.prefix.cmp(&other.prefix)
  53. }
  54. /// Returns a globally unique id for the Index
  55. pub fn unique_id(&self) -> usize {
  56. self.counter.0
  57. }
  58. }
  59. impl<T> From<(T, SubId, SubscriptionGlobalId)> for Index<T>
  60. where
  61. T: PartialOrd + Ord + Send + Sync + Debug,
  62. {
  63. fn from((prefix, id, counter): (T, SubId, SubscriptionGlobalId)) -> Self {
  64. Self {
  65. prefix,
  66. id,
  67. counter,
  68. }
  69. }
  70. }
  71. impl<T> From<(T, SubId)> for Index<T>
  72. where
  73. T: PartialOrd + Ord + Send + Sync + Debug,
  74. {
  75. fn from((prefix, id): (T, SubId)) -> Self {
  76. Self {
  77. prefix,
  78. id,
  79. counter: Default::default(),
  80. }
  81. }
  82. }
  83. impl<T> From<T> for Index<T>
  84. where
  85. T: PartialOrd + Ord + Send + Sync + Debug,
  86. {
  87. fn from(prefix: T) -> Self {
  88. Self {
  89. prefix,
  90. id: Default::default(),
  91. counter: SubscriptionGlobalId(0),
  92. }
  93. }
  94. }
  95. static COUNTER: AtomicUsize = AtomicUsize::new(0);
  96. /// Dummy type
  97. ///
  98. /// This is only use so each Index is unique, with the same prefix.
  99. ///
  100. /// The prefix is used to leverage the BTree to find things quickly, but each
  101. /// entry/key must be unique, so we use this dummy type to make sure each Index
  102. /// is unique.
  103. ///
  104. /// Unique is also used to make sure that the indexes are sorted by creation order
  105. #[derive(Debug, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
  106. pub struct SubscriptionGlobalId(usize);
  107. impl Default for SubscriptionGlobalId {
  108. fn default() -> Self {
  109. Self(COUNTER.fetch_add(1, Ordering::Relaxed))
  110. }
  111. }
  112. #[cfg(test)]
  113. mod tests {
  114. use super::*;
  115. #[test]
  116. fn test_index_from_tuple() {
  117. let sub_id = SubId::from("test_sub_id");
  118. let prefix = "test_prefix";
  119. let index: Index<&str> = Index::from((prefix, sub_id.clone()));
  120. assert_eq!(index.prefix, "test_prefix");
  121. assert_eq!(index.id, sub_id);
  122. }
  123. #[test]
  124. fn test_index_cmp_prefix() {
  125. let sub_id = SubId::from("test_sub_id");
  126. let index1: Index<&str> = Index::from(("a", sub_id.clone()));
  127. let index2: Index<&str> = Index::from(("b", sub_id.clone()));
  128. assert_eq!(index1.cmp_prefix(&index2), std::cmp::Ordering::Less);
  129. }
  130. #[test]
  131. fn test_sub_id_from_str() {
  132. let sub_id = SubId::from("test_sub_id");
  133. assert_eq!(sub_id.0, "test_sub_id");
  134. }
  135. #[test]
  136. fn test_sub_id_deref() {
  137. let sub_id = SubId::from("test_sub_id");
  138. assert_eq!(&*sub_id, "test_sub_id");
  139. }
  140. }