libp2p_pubsub_core/
subscription.rs

1use std::fmt::{Debug, Formatter};
2use std::rc::Rc;
3
4use crate::framing::Message as FrameMessage;
5use crate::message_id::{MessageId, MessageIdFn};
6use crate::topic::{Hasher, Topic, TopicHash};
7
8#[derive(Clone)]
9pub struct Subscription {
10    /// The topic to subscribe to.
11    pub topic: TopicHash,
12    /// The message id function to use for this subscription.
13    pub message_id_fn: Option<Rc<MessageIdFn>>,
14}
15
16impl Debug for Subscription {
17    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
18        f.debug_struct("Subscription")
19            .field("topic", &self.topic)
20            .field(
21                "message_id_fn",
22                match &self.message_id_fn {
23                    None => &"MessageIdFn(not_defined)",
24                    Some(_) => &"MessageIdFn(custom)",
25                },
26            )
27            .finish()
28    }
29}
30
31impl From<TopicHash> for Subscription {
32    fn from(topic: TopicHash) -> Self {
33        Self {
34            topic,
35            message_id_fn: None,
36        }
37    }
38}
39
40impl<H: Hasher> From<Topic<H>> for Subscription {
41    fn from(topic: Topic<H>) -> Self {
42        topic.hash().into()
43    }
44}
45
46/// A builder for a subscription.
47pub struct SubscriptionBuilder {
48    topic: TopicHash,
49    message_id_fn: Option<Rc<MessageIdFn>>,
50}
51
52impl SubscriptionBuilder {
53    /// Create a new subscription builder.
54    pub fn new<H: Hasher>(topic: Topic<H>) -> Self {
55        Self {
56            topic: topic.hash(),
57            message_id_fn: None,
58        }
59    }
60
61    /// A user-defined function allowing the user to specify the message id of a pub-sub message.
62    /// The default value is to concatenate the source peer id with a sequence number. Setting this
63    /// parameter allows the user to address packets arbitrarily. One example is content based
64    /// addressing, where this function may be set to `hash(message)`. This would prevent messages
65    /// of the same content from being duplicated.
66    ///
67    /// The function takes a [`FrameMessage`] as input and outputs a String to be interpreted as the
68    /// message id.
69    pub fn message_id_fn<F>(&mut self, id_fn: F) -> &mut Self
70    where
71        F: Fn(&FrameMessage) -> MessageId + Send + Sync + 'static,
72    {
73        self.message_id_fn = Some(Rc::new(id_fn));
74        self
75    }
76
77    pub fn build(self) -> Subscription {
78        Subscription {
79            topic: self.topic,
80            message_id_fn: self.message_id_fn,
81        }
82    }
83}