Skip to main content

synd_protocol/
capability.rs

1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5pub const TIMELINE_READ: &str = "timeline.read";
6pub const SUBSCRIPTION_WRITE: &str = "subscription.write";
7pub const FEED_REFRESH: &str = "feed.refresh";
8
9pub fn local_api_capabilities() -> CapabilitySet {
10    CapabilitySet::new([TIMELINE_READ, SUBSCRIPTION_WRITE, FEED_REFRESH])
11}
12
13/// Capability names negotiated across the client/server protocol.
14#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
15pub struct CapabilitySet {
16    names: Vec<String>,
17}
18
19impl CapabilitySet {
20    pub fn new(names: impl IntoIterator<Item = impl Into<String>>) -> Self {
21        Self {
22            names: names.into_iter().map(Into::into).collect(),
23        }
24    }
25
26    pub fn names(&self) -> &[String] {
27        &self.names
28    }
29
30    pub fn is_empty(&self) -> bool {
31        self.names.is_empty()
32    }
33
34    #[must_use]
35    pub fn missing_from(&self, available: &Self) -> Self {
36        Self::new(
37            self.names
38                .iter()
39                .filter(|name| !available.names.contains(name))
40                .cloned(),
41        )
42    }
43}
44
45impl fmt::Display for CapabilitySet {
46    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47        if self.names.is_empty() {
48            return f.write_str("<none>");
49        }
50
51        f.write_str(&self.names.join(", "))
52    }
53}