Skip to main content

nostr_types/types/
relay_message.rs

1use super::{Event, Id, SubscriptionId};
2use serde::de::Error as DeError;
3use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
4use serde::ser::{Serialize, SerializeSeq, Serializer};
5use std::fmt;
6
7/// A message from a relay to a client
8#[derive(Clone, Debug, Eq, PartialEq)]
9pub enum RelayMessage {
10    /// An event matching a subscription
11    Event(SubscriptionId, Box<Event>),
12
13    /// A human readable notice for errors and other information
14    Notice(String),
15
16    /// End of subscribed events notification
17    Eose(SubscriptionId),
18
19    /// Used to notify clients if an event was successuful
20    Ok(Id, bool, String),
21
22    /// Used to send authentication challenges
23    Auth(String),
24}
25
26impl RelayMessage {
27    // Mock data for testing
28    #[allow(dead_code)]
29    pub(crate) fn mock() -> RelayMessage {
30        RelayMessage::Event(SubscriptionId::mock(), Box::new(Event::mock()))
31    }
32}
33
34impl Serialize for RelayMessage {
35    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
36    where
37        S: Serializer,
38    {
39        match self {
40            RelayMessage::Event(id, event) => {
41                let mut seq = serializer.serialize_seq(Some(3))?;
42                seq.serialize_element("EVENT")?;
43                seq.serialize_element(&id)?;
44                seq.serialize_element(&event)?;
45                seq.end()
46            }
47            RelayMessage::Notice(s) => {
48                let mut seq = serializer.serialize_seq(Some(2))?;
49                seq.serialize_element("NOTICE")?;
50                seq.serialize_element(&s)?;
51                seq.end()
52            }
53            RelayMessage::Eose(id) => {
54                let mut seq = serializer.serialize_seq(Some(2))?;
55                seq.serialize_element("EOSE")?;
56                seq.serialize_element(&id)?;
57                seq.end()
58            }
59            RelayMessage::Ok(id, ok, message) => {
60                let mut seq = serializer.serialize_seq(Some(4))?;
61                seq.serialize_element("OK")?;
62                seq.serialize_element(&id)?;
63                seq.serialize_element(&ok)?;
64                seq.serialize_element(&message)?;
65                seq.end()
66            }
67            RelayMessage::Auth(challenge) => {
68                let mut seq = serializer.serialize_seq(Some(2))?;
69                seq.serialize_element("AUTH")?;
70                seq.serialize_element(&challenge)?;
71                seq.end()
72            }
73        }
74    }
75}
76
77impl<'de> Deserialize<'de> for RelayMessage {
78    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
79    where
80        D: Deserializer<'de>,
81    {
82        deserializer.deserialize_seq(RelayMessageVisitor)
83    }
84}
85
86struct RelayMessageVisitor;
87
88impl<'de> Visitor<'de> for RelayMessageVisitor {
89    type Value = RelayMessage;
90
91    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
92        write!(f, "a sequence of strings")
93    }
94
95    fn visit_seq<A>(self, mut seq: A) -> Result<RelayMessage, A::Error>
96    where
97        A: SeqAccess<'de>,
98    {
99        let word: &str = seq
100            .next_element()?
101            .ok_or_else(|| DeError::custom("Message missing initial string field"))?;
102        if word == "EVENT" {
103            let id: SubscriptionId = seq
104                .next_element()?
105                .ok_or_else(|| DeError::custom("Message missing id field"))?;
106            let event: Event = seq
107                .next_element()?
108                .ok_or_else(|| DeError::custom("Message missing event field"))?;
109            Ok(RelayMessage::Event(id, Box::new(event)))
110        } else if word == "NOTICE" {
111            let s: String = seq
112                .next_element()?
113                .ok_or_else(|| DeError::custom("Message missing string field"))?;
114            Ok(RelayMessage::Notice(s))
115        } else if word == "EOSE" {
116            let id: SubscriptionId = seq
117                .next_element()?
118                .ok_or_else(|| DeError::custom("Message missing id field"))?;
119            Ok(RelayMessage::Eose(id))
120        } else if word == "OK" {
121            let id: Id = seq
122                .next_element()?
123                .ok_or_else(|| DeError::custom("Message missing id field"))?;
124            let ok: bool = seq
125                .next_element()?
126                .ok_or_else(|| DeError::custom("Message missing ok field"))?;
127            let message: String = seq
128                .next_element()?
129                .ok_or_else(|| DeError::custom("Message missing string field"))?;
130            Ok(RelayMessage::Ok(id, ok, message))
131        } else if word == "AUTH" {
132            let challenge: String = seq
133                .next_element()?
134                .ok_or_else(|| DeError::custom("Message missing challenge field"))?;
135            Ok(RelayMessage::Auth(challenge))
136        } else {
137            Err(DeError::custom(format!("Unknown Message: {}", word)))
138        }
139    }
140}
141
142#[cfg(test)]
143mod test {
144    use super::*;
145
146    test_serde! {RelayMessage, test_relay_message_serde}
147}