index.rs 3.8 KB

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