net_hashmap.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::{
  19. borrow::Borrow,
  20. collections::{
  21. hash_map::{Iter, Keys, Values},
  22. HashMap,
  23. },
  24. hash::Hash,
  25. };
  26. use darkfi_serial::{Decodable, Encodable, SerialDecodable, SerialEncodable};
  27. use crate::{net, net::P2pPtr, Result};
  28. /// A general networked hashmap. Propagates changes over P2P.
  29. #[derive(Clone)]
  30. pub struct NetHashMap<K, V> {
  31. /// The internal [`HashMap`] that represents the actual state
  32. hashmap: HashMap<K, V>,
  33. /// Pointer to the P2P network
  34. p2p: P2pPtr,
  35. }
  36. impl<K, V> NetHashMap<K, V> {
  37. /// Instantiate a new [`NetHashMap`] with the given [`P2pPtr`]
  38. pub fn new(p2p: P2pPtr) -> Self {
  39. let hashmap = HashMap::new();
  40. Self { hashmap, p2p }
  41. }
  42. }
  43. impl<K, V> NetHashMap<K, V>
  44. where
  45. K: Eq + Hash + Send + Sync + Encodable + Decodable + Clone + 'static,
  46. V: Send + Sync + Encodable + Decodable + Clone + 'static,
  47. {
  48. /// Returns `true` if the map contains a value for the specified key.
  49. #[allow(dead_code)]
  50. pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
  51. where
  52. K: Borrow<Q>,
  53. Q: Hash + Eq,
  54. {
  55. self.hashmap.contains_key(k)
  56. }
  57. /// Returns `true` if the map contains no elements.
  58. #[allow(dead_code)]
  59. pub fn is_empty(&self) -> bool {
  60. self.hashmap.is_empty()
  61. }
  62. /// Returns the number of elements in the map.
  63. #[allow(dead_code)]
  64. pub fn len(&self) -> usize {
  65. self.hashmap.len()
  66. }
  67. /// Insert a key-value pair into the map.
  68. ///
  69. /// If the map did not have this key present, `None` is returned.
  70. ///
  71. /// If the map did have this key present, the value is updated, and
  72. /// the old value is returned.
  73. ///
  74. /// Additionally, this change will be broadcasted to the P2P network.
  75. pub async fn insert(&mut self, k: K, v: V) -> Result<Option<V>> {
  76. let message = NetHashMapInsert { k: k.clone(), v: v.clone() };
  77. self.p2p.broadcast(&message).await?;
  78. Ok(self.hashmap.insert(k, v))
  79. }
  80. /// Removes a key from the map, returning the value at the key if the key
  81. /// was previously in the map.
  82. ///
  83. /// Additionally, this change will be broadcasted to the P2P network.
  84. pub async fn remove<Q: Encodable + Decodable + ?Sized + Clone>(
  85. &mut self,
  86. k: Q,
  87. ) -> Result<Option<V>>
  88. where
  89. K: Borrow<Q>,
  90. Q: Hash + Eq + Send + Sync + Encodable + Decodable + 'static,
  91. {
  92. let message = NetHashMapRemove { k: k.clone() };
  93. self.p2p.broadcast(&message).await?;
  94. Ok(self.hashmap.remove(&k))
  95. }
  96. /// An iterator visiting all key-value pairs in arbitrary order.
  97. /// The iterator element type is `(&'a K, &'a V)`.
  98. #[allow(dead_code)]
  99. pub fn iter(&self) -> Iter<'_, K, V> {
  100. self.hashmap.iter()
  101. }
  102. /// An iterator visiting all keys in arbitrary order.
  103. /// The iterator element type is `&'a K`.
  104. #[allow(dead_code)]
  105. pub fn keys(&self) -> Keys<'_, K, V> {
  106. self.hashmap.keys()
  107. }
  108. /// An iterator visiting all values in arbitrary order.
  109. /// The iterator element type is `&'a V`.
  110. #[allow(dead_code)]
  111. pub fn values(&self) -> Values<'_, K, V> {
  112. self.hashmap.values()
  113. }
  114. }
  115. #[derive(Debug, Clone, SerialDecodable, SerialEncodable)]
  116. pub struct NetHashMapInsert<K, V> {
  117. pub k: K,
  118. pub v: V,
  119. }
  120. impl<K, V> net::Message for NetHashMapInsert<K, V>
  121. where
  122. K: Encodable + Decodable + Send + Sync + 'static,
  123. V: Encodable + Decodable + Send + Sync + 'static,
  124. {
  125. const NAME: &'static str = "nethashmap_insert";
  126. }
  127. #[derive(Debug, Clone, SerialDecodable, SerialEncodable)]
  128. pub struct NetHashMapRemove<K> {
  129. pub k: K,
  130. }
  131. impl<K> net::Message for NetHashMapRemove<K>
  132. where
  133. K: Encodable + Decodable + Send + Sync + 'static,
  134. {
  135. const NAME: &'static str = "nethashmap_remove";
  136. }