twilight_model/http/
permission_overwrite.rs

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