1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
use crate::{
    id::{
        marker::{IntegrationMarker, RoleSubscriptionSkuMarker, UserMarker},
        Id,
    },
    util::is_false,
};
use serde::{Deserialize, Serialize};

/// Tags that a [`Role`] has.
///
/// [`Role`]: super::Role
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct RoleTags {
    /// Whether this role is available for purchase.
    #[serde(
        default,
        skip_serializing_if = "is_false",
        with = "crate::visitor::null_boolean"
    )]
    pub available_for_purchase: bool,
    /// ID of the bot the role belongs to.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub bot_id: Option<Id<UserMarker>>,
    /// Whether this role is a guild's linked role.
    #[serde(
        default,
        skip_serializing_if = "is_false",
        with = "crate::visitor::null_boolean"
    )]
    pub guild_connections: bool,
    /// ID of the integration the role belongs to.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub integration_id: Option<Id<IntegrationMarker>>,
    /// ID of the role's subscription SKU and listing.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub subscription_listing_id: Option<Id<RoleSubscriptionSkuMarker>>,
    /// Whether this is the guild's premium subscriber role.
    #[serde(
        default,
        skip_serializing_if = "is_false",
        with = "crate::visitor::null_boolean"
    )]
    pub premium_subscriber: bool,
}

#[cfg(test)]
mod tests {
    use super::RoleTags;
    use crate::id::Id;
    use serde_test::Token;

    #[test]
    fn bot() {
        let tags = RoleTags {
            available_for_purchase: false,
            bot_id: Some(Id::new(1)),
            guild_connections: false,
            integration_id: Some(Id::new(2)),
            premium_subscriber: false,
            subscription_listing_id: None,
        };

        serde_test::assert_tokens(
            &tags,
            &[
                Token::Struct {
                    name: "RoleTags",
                    len: 2,
                },
                Token::Str("bot_id"),
                Token::Some,
                Token::NewtypeStruct { name: "Id" },
                Token::Str("1"),
                Token::Str("integration_id"),
                Token::Some,
                Token::NewtypeStruct { name: "Id" },
                Token::Str("2"),
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn premium_subscriber() {
        let tags = RoleTags {
            available_for_purchase: false,
            bot_id: None,
            guild_connections: false,
            integration_id: None,
            premium_subscriber: true,
            subscription_listing_id: None,
        };

        serde_test::assert_tokens(
            &tags,
            &[
                Token::Struct {
                    name: "RoleTags",
                    len: 1,
                },
                Token::Str("premium_subscriber"),
                Token::None,
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn subscription() {
        let tags = RoleTags {
            available_for_purchase: true,
            bot_id: None,
            guild_connections: false,
            integration_id: Some(Id::new(1)),
            subscription_listing_id: Some(Id::new(2)),
            premium_subscriber: false,
        };

        serde_test::assert_tokens(
            &tags,
            &[
                Token::Struct {
                    name: "RoleTags",
                    len: 3,
                },
                Token::Str("available_for_purchase"),
                Token::None,
                Token::Str("integration_id"),
                Token::Some,
                Token::NewtypeStruct { name: "Id" },
                Token::Str("1"),
                Token::Str("subscription_listing_id"),
                Token::Some,
                Token::NewtypeStruct { name: "Id" },
                Token::Str("2"),
                Token::StructEnd,
            ],
        );
    }

    /// Test that if all fields are None and the optional null fields are false,
    /// then serialize back into the source payload (where all fields are not
    /// present).
    #[test]
    fn none() {
        let tags = RoleTags {
            available_for_purchase: false,
            bot_id: None,
            guild_connections: false,
            integration_id: None,
            premium_subscriber: false,
            subscription_listing_id: None,
        };

        serde_test::assert_tokens(
            &tags,
            &[
                Token::Struct {
                    name: "RoleTags",
                    len: 0,
                },
                Token::StructEnd,
            ],
        );
    }
}