twilight_model/channel/
permission_overwrite.rs

1use crate::{
2    guild::Permissions,
3    id::{marker::GenericMarker, Id},
4};
5use serde::{Deserialize, Serialize};
6
7/// Permission overwrite data for a role or member.
8#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
9pub struct PermissionOverwrite {
10    pub allow: Permissions,
11    pub deny: Permissions,
12    pub id: Id<GenericMarker>,
13    #[serde(rename = "type")]
14    pub kind: PermissionOverwriteType,
15}
16
17/// Type of a permission overwrite target.
18// Keep in sync with `twilight_util::permission_calculator::PermissionCalculator`!
19#[derive(Clone, Copy, Debug, Serialize, Eq, Hash, PartialEq, Deserialize)]
20#[non_exhaustive]
21#[serde(from = "u8", into = "u8", rename_all = "snake_case")]
22pub enum PermissionOverwriteType {
23    /// Permission overwrite targets an individual member.
24    Member,
25    /// Permission overwrite targets an individual role.
26    Role,
27    /// Variant value is unknown to the library.
28    Unknown(u8),
29}
30
31impl From<u8> for PermissionOverwriteType {
32    fn from(value: u8) -> Self {
33        match value {
34            0 => PermissionOverwriteType::Role,
35            1 => PermissionOverwriteType::Member,
36            unknown => PermissionOverwriteType::Unknown(unknown),
37        }
38    }
39}
40
41impl From<PermissionOverwriteType> for u8 {
42    fn from(value: PermissionOverwriteType) -> Self {
43        match value {
44            PermissionOverwriteType::Member => 1,
45            PermissionOverwriteType::Role => 0,
46            PermissionOverwriteType::Unknown(unknown) => unknown,
47        }
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::{PermissionOverwrite, PermissionOverwriteType, Permissions};
54    use crate::id::Id;
55    use serde::{Deserialize, Serialize};
56    use serde_test::Token;
57    use static_assertions::{assert_fields, assert_impl_all};
58    use std::{fmt::Debug, hash::Hash};
59
60    assert_fields!(PermissionOverwrite: allow, deny, id, kind);
61    assert_impl_all!(
62        PermissionOverwrite: Clone,
63        Debug,
64        Deserialize<'static>,
65        Eq,
66        Hash,
67        PartialEq,
68        Send,
69        Serialize,
70        Sync
71    );
72    assert_impl_all!(
73        PermissionOverwriteType: Clone,
74        Copy,
75        Debug,
76        Eq,
77        Hash,
78        PartialEq,
79        Send,
80        Sync
81    );
82
83    #[test]
84    fn overwrite() {
85        let value = PermissionOverwrite {
86            allow: Permissions::CREATE_INVITE,
87            deny: Permissions::KICK_MEMBERS,
88            id: Id::new(12_345_678),
89            kind: PermissionOverwriteType::Member,
90        };
91
92        serde_test::assert_tokens(
93            &value,
94            &[
95                Token::Struct {
96                    name: "PermissionOverwrite",
97                    len: 4,
98                },
99                Token::Str("allow"),
100                Token::Str("1"),
101                Token::Str("deny"),
102                Token::Str("2"),
103                Token::Str("id"),
104                Token::NewtypeStruct { name: "Id" },
105                Token::Str("12345678"),
106                Token::Str("type"),
107                Token::U8(PermissionOverwriteType::Member.into()),
108                Token::StructEnd,
109            ],
110        );
111    }
112
113    #[test]
114    fn blank_overwrite() {
115        // Test integer deser used in guild templates.
116        let raw = r#"{
117  "allow": "1",
118  "deny": "2",
119  "id": 1,
120  "type": 1
121}"#;
122
123        let value = PermissionOverwrite {
124            allow: Permissions::CREATE_INVITE,
125            deny: Permissions::KICK_MEMBERS,
126            id: Id::new(1),
127            kind: PermissionOverwriteType::Member,
128        };
129
130        let deserialized = serde_json::from_str::<PermissionOverwrite>(raw).unwrap();
131
132        assert_eq!(deserialized, value);
133
134        serde_test::assert_tokens(
135            &value,
136            &[
137                Token::Struct {
138                    name: "PermissionOverwrite",
139                    len: 4,
140                },
141                Token::Str("allow"),
142                Token::Str("1"),
143                Token::Str("deny"),
144                Token::Str("2"),
145                Token::Str("id"),
146                Token::NewtypeStruct { name: "Id" },
147                Token::Str("1"),
148                Token::Str("type"),
149                Token::U8(1),
150                Token::StructEnd,
151            ],
152        );
153    }
154
155    #[test]
156    fn overwrite_type_name() {
157        serde_test::assert_tokens(&PermissionOverwriteType::Member, &[Token::U8(1)]);
158        serde_test::assert_tokens(&PermissionOverwriteType::Role, &[Token::U8(0)]);
159        serde_test::assert_tokens(&PermissionOverwriteType::Unknown(99), &[Token::U8(99)]);
160    }
161}