Skip to main content

ab_networking/utils/
key_with_distance.rs

1use libp2p::PeerId;
2use libp2p::kad::{KBucketDistance, RecordKey};
3use std::cmp::Ordering;
4use std::hash::Hash;
5
6type KademliaBucketKey<T> = libp2p::kad::KBucketKey<T>;
7
8/// Helper structure. It wraps Kademlia distance to a given peer for heap-metrics.
9#[derive(Debug, Clone, Eq)]
10pub struct KeyWithDistance {
11    key: RecordKey,
12    distance: KBucketDistance,
13}
14
15impl KeyWithDistance {
16    /// Creates a new [`KeyWithDistance`] instance with the given `PeerId` and `K` key.
17    ///
18    /// The `distance` is calculated as the distance between the `KademliaBucketKey` derived
19    /// from the `PeerId` and the `KademliaBucketKey` derived from the `K` key.
20    pub fn new<K>(peer_id: PeerId, key: K) -> Self
21    where
22        RecordKey: From<K>,
23    {
24        Self::new_with_record_key(peer_id, RecordKey::from(key))
25    }
26
27    /// Creates a new [`KeyWithDistance`] instance with the given `PeerId` and `RecordKey`.
28    pub fn new_with_record_key(peer_id: PeerId, key: RecordKey) -> Self {
29        let peer_key = KademliaBucketKey::from(peer_id);
30        let distance = KademliaBucketKey::new(key.as_ref()).distance(&peer_key);
31        Self { key, distance }
32    }
33
34    /// Returns a reference to the record key.
35    pub fn record_key(&self) -> &RecordKey {
36        &self.key
37    }
38}
39
40impl PartialEq for KeyWithDistance {
41    fn eq(&self, other: &Self) -> bool {
42        self.key == other.key
43    }
44}
45
46impl PartialOrd for KeyWithDistance {
47    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
48        Some(self.cmp(other))
49    }
50}
51
52impl Ord for KeyWithDistance {
53    fn cmp(&self, other: &Self) -> Ordering {
54        self.distance.cmp(&other.distance)
55    }
56}
57
58impl Hash for KeyWithDistance {
59    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
60        self.key.hash(state);
61    }
62}