nostr_types/types/
relay_usage.rs

1use std::convert::TryFrom;
2
3/// A way that a user uses a Relay
4#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
5#[repr(u32)]
6pub enum RelayUsage {
7    /// User seeks events here if they are not otherwise found
8    FallbackRead = 1 << 0,
9
10    /// User writes here but does not advertise it
11    Archive = 1 << 1,
12
13    // was a relay usage flag in gossip, but was retired
14    // Advertise = 1 << 2,
15    /// User accepts posts here from the public that tag them
16    Inbox = 1 << 3,
17
18    /// User posts here for the public
19    Outbox = 1 << 4,
20
21    /// User seeks relay lists here (index, discover)
22    Directory = 1 << 5,
23
24    // is used as SPAMSAFE bit in gossip so reserved, but isn't a relay usage
25    // ReservedSpamsafe = 1 << 6,
26    /// User accepts DMs here
27    Dm = 1 << 7,
28
29    /// user stores and reads back their own configurations here
30    Config = 1 << 8,
31
32    /// User does NIP-50 SEARCH here
33    Search = 1 << 9,
34}
35
36impl TryFrom<u32> for RelayUsage {
37    type Error = ();
38
39    fn try_from(u: u32) -> Result<RelayUsage, ()> {
40        match u {
41            1 => Ok(RelayUsage::FallbackRead),
42            2 => Ok(RelayUsage::Archive),
43            8 => Ok(RelayUsage::Inbox),
44            16 => Ok(RelayUsage::Outbox),
45            32 => Ok(RelayUsage::Directory),
46            128 => Ok(RelayUsage::Dm),
47            256 => Ok(RelayUsage::Config),
48            512 => Ok(RelayUsage::Search),
49            _ => Err(()),
50        }
51    }
52}
53
54/// The ways that a user uses a Relay
55///
56// See also https://github.com/mikedilger/gossip/blob/master/gossip-lib/src/storage/types/relay3.rs
57// See also https://github.com/nostr-protocol/nips/issues/1282 for possible future entries
58#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
59pub struct RelayUsageSet(u32);
60
61impl RelayUsageSet {
62    const MASK: u32 = RelayUsage::FallbackRead as u32
63        | RelayUsage::Archive as u32
64        | RelayUsage::Inbox as u32
65        | RelayUsage::Outbox as u32
66        | RelayUsage::Directory as u32
67        | RelayUsage::Dm as u32
68        | RelayUsage::Config as u32
69        | RelayUsage::Search as u32;
70
71    /// Create a new empty RelayUsageSet
72    pub const fn new_empty() -> Self {
73        RelayUsageSet(0)
74    }
75
76    /// Create a new RelayUsageSet with all usages
77    pub const fn new_all() -> Self {
78        Self(Self::MASK)
79    }
80
81    /// Get the u32 bitflag representation
82    pub const fn bits(&self) -> u32 {
83        self.0
84    }
85
86    /// Set from a u32 bitflag representation. If any unknown bits are set,
87    /// this will return None
88    pub const fn from_bits(bits: u32) -> Option<RelayUsageSet> {
89        if bits & !Self::MASK != 0 {
90            None
91        } else {
92            Some(RelayUsageSet(bits))
93        }
94    }
95
96    /// Set from a u32 bitflag representation. If any unknown bits are set,
97    /// they will be cleared
98    pub const fn from_bits_truncate(bits: u32) -> RelayUsageSet {
99        RelayUsageSet(bits & Self::MASK)
100    }
101
102    /// Whether all bits are unset
103    pub const fn is_empty(&self) -> bool {
104        self.0 == 0
105    }
106
107    /// Whether all defined bits are set
108    pub const fn is_all(&self) -> bool {
109        self.0 & Self::MASK == Self::MASK
110    }
111
112    /// Whether any usage in other is also in Self
113    pub const fn intersects(&self, other: Self) -> bool {
114        self.0 & other.0 != 0
115    }
116
117    /// Whether all usages in other are in Self
118    pub const fn contains(&self, other: Self) -> bool {
119        self.0 & other.0 == other.0
120    }
121
122    /// Has a RelayUsage set
123    pub fn has_usage(&mut self, ru: RelayUsage) -> bool {
124        self.0 & ru as u32 == ru as u32
125    }
126
127    /// Add a RelayUsage to Self
128    pub fn add_usage(&mut self, ru: RelayUsage) {
129        self.0 |= ru as u32
130    }
131
132    /// Remove a RelayUsage to Self
133    pub fn remove_usage(&mut self, ru: RelayUsage) {
134        self.0 &= !(ru as u32)
135    }
136}