hyperstack_server/websocket/
subscription.rs

1use serde::{Deserialize, Serialize};
2
3/// Client subscription to a specific view
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct Subscription {
6    pub view: String,
7    #[serde(skip_serializing_if = "Option::is_none")]
8    pub key: Option<String>,
9    #[serde(skip_serializing_if = "Option::is_none")]
10    pub partition: Option<String>,
11}
12
13impl Subscription {
14    pub fn matches_view(&self, view_id: &str) -> bool {
15        self.view == view_id
16    }
17
18    pub fn matches_key(&self, key: &str) -> bool {
19        self.key.as_ref().is_none_or(|k| k == key)
20    }
21
22    pub fn matches(&self, view_id: &str, key: &str) -> bool {
23        self.matches_view(view_id) && self.matches_key(key)
24    }
25}
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30    use serde_json::json;
31
32    #[test]
33    fn test_subscription_parse() {
34        let json = json!({
35            "view": "SettlementGame/list",
36            "key": "835"
37        });
38
39        let sub: Subscription = serde_json::from_value(json).unwrap();
40        assert_eq!(sub.view, "SettlementGame/list");
41        assert_eq!(sub.key, Some("835".to_string()));
42    }
43
44    #[test]
45    fn test_subscription_no_key() {
46        let json = json!({
47            "view": "SettlementGame/list"
48        });
49
50        let sub: Subscription = serde_json::from_value(json).unwrap();
51        assert_eq!(sub.view, "SettlementGame/list");
52        assert!(sub.key.is_none());
53    }
54
55    #[test]
56    fn test_subscription_matches() {
57        let sub = Subscription {
58            view: "SettlementGame/list".to_string(),
59            key: Some("835".to_string()),
60            partition: None,
61        };
62
63        assert!(sub.matches("SettlementGame/list", "835"));
64        assert!(!sub.matches("SettlementGame/list", "836"));
65        assert!(!sub.matches("SettlementGame/state", "835"));
66    }
67
68    #[test]
69    fn test_subscription_matches_all_keys() {
70        let sub = Subscription {
71            view: "SettlementGame/list".to_string(),
72            key: None,
73            partition: None,
74        };
75
76        assert!(sub.matches("SettlementGame/list", "835"));
77        assert!(sub.matches("SettlementGame/list", "836"));
78        assert!(!sub.matches("SettlementGame/state", "835"));
79    }
80}