tetratto_core/model/
communities_permissions.rs

1use bitflags::bitflags;
2use serde::{
3    Deserialize, Deserializer, Serialize,
4    de::{Error as DeError, Visitor},
5};
6
7bitflags! {
8    /// Fine-grained community permissions built using bitwise operations.
9    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10    pub struct CommunityPermission: u32 {
11        const DEFAULT = 1 << 0;
12        const ADMINISTRATOR = 1 << 1;
13        const MEMBER = 1 << 2;
14        const MANAGE_POSTS = 1 << 3;
15        const MANAGE_ROLES = 1 << 4;
16        const BANNED = 1 << 5;
17        const REQUESTED = 1 << 6;
18        const MANAGE_PINS = 1 << 7;
19        const MANAGE_COMMUNITY = 1 << 8;
20        const MANAGE_QUESTIONS = 1 << 9;
21        const MANAGE_CHANNELS = 1 << 10;
22        const MANAGE_MESSAGES = 1 << 11;
23        const MANAGE_EMOJIS = 1 << 12;
24
25        const _ = !0;
26    }
27}
28
29impl Serialize for CommunityPermission {
30    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
31    where
32        S: serde::Serializer,
33    {
34        serializer.serialize_u32(self.bits())
35    }
36}
37
38struct CommunityPermissionVisitor;
39impl Visitor<'_> for CommunityPermissionVisitor {
40    type Value = CommunityPermission;
41
42    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
43        formatter.write_str("u32")
44    }
45
46    fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
47    where
48        E: DeError,
49    {
50        if let Some(permission) = CommunityPermission::from_bits(value) {
51            Ok(permission)
52        } else {
53            Ok(CommunityPermission::from_bits_retain(value))
54        }
55    }
56
57    fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
58    where
59        E: DeError,
60    {
61        if let Some(permission) = CommunityPermission::from_bits(value as u32) {
62            Ok(permission)
63        } else {
64            Ok(CommunityPermission::from_bits_retain(value as u32))
65        }
66    }
67
68    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
69    where
70        E: DeError,
71    {
72        if let Some(permission) = CommunityPermission::from_bits(value as u32) {
73            Ok(permission)
74        } else {
75            Ok(CommunityPermission::from_bits_retain(value as u32))
76        }
77    }
78}
79
80impl<'de> Deserialize<'de> for CommunityPermission {
81    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
82    where
83        D: Deserializer<'de>,
84    {
85        deserializer.deserialize_any(CommunityPermissionVisitor)
86    }
87}
88
89impl CommunityPermission {
90    /// Join two [`CommunityPermission`]s into a single `u32`.
91    pub fn join(lhs: CommunityPermission, rhs: CommunityPermission) -> CommunityPermission {
92        lhs | rhs
93    }
94
95    /// Check if the given `input` contains the given [`CommunityPermission`].
96    pub fn check(self, permission: CommunityPermission) -> bool {
97        if (self & CommunityPermission::ADMINISTRATOR) == CommunityPermission::ADMINISTRATOR {
98            // has administrator permission, meaning everything else is automatically true
99            return true;
100        } else if self.check_banned() {
101            // has banned permission, meaning everything else is automatically false
102            return false;
103        }
104
105        (self & permission) == permission
106    }
107
108    /// Check if the given [`CommunityPermission`] qualifies as "Member" status.
109    pub fn check_member(self) -> bool {
110        self.check(CommunityPermission::MEMBER)
111    }
112
113    /// Check if the given [`CommunityPermission`] qualifies as "Moderator" status.
114    pub fn check_moderator(self) -> bool {
115        self.check(CommunityPermission::MANAGE_POSTS)
116    }
117
118    /// Check if the given [`CommunityPermission`] qualifies as "Banned" status.
119    pub fn check_banned(self) -> bool {
120        (self & CommunityPermission::BANNED) == CommunityPermission::BANNED
121    }
122}
123
124impl Default for CommunityPermission {
125    fn default() -> Self {
126        Self::DEFAULT | Self::MEMBER
127    }
128}