twilight_model/application/command/
permissions.rs1use crate::id::{
4 marker::{
5 ApplicationMarker, ChannelMarker, CommandMarker, GenericMarker, GuildMarker, RoleMarker,
6 UserMarker,
7 },
8 Id,
9};
10use serde::{de::Deserializer, ser::Serializer, Deserialize, Serialize};
11use serde_repr::{Deserialize_repr, Serialize_repr};
12
13#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
15pub struct GuildCommandPermissions {
16 pub application_id: Id<ApplicationMarker>,
18 pub guild_id: Id<GuildMarker>,
20 pub id: Id<CommandMarker>,
22 pub permissions: Vec<CommandPermission>,
26}
27
28#[derive(Clone, Debug, Eq, Hash, PartialEq)]
30pub struct CommandPermission {
31 pub id: CommandPermissionType,
33 pub permission: bool,
35}
36
37#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
39pub enum CommandPermissionType {
40 Channel(Id<ChannelMarker>),
44 Role(Id<RoleMarker>),
48 User(Id<UserMarker>),
50}
51
52impl CommandPermissionType {
53 const fn id(self) -> Id<GenericMarker> {
55 match self {
56 Self::Channel(id) => id.cast(),
57 Self::Role(id) => id.cast(),
58 Self::User(id) => id.cast(),
59 }
60 }
61
62 const fn kind(self) -> CommandPermissionDataType {
64 match self {
65 Self::Channel(_) => CommandPermissionDataType::Channel,
66 Self::Role(_) => CommandPermissionDataType::Role,
67 Self::User(_) => CommandPermissionDataType::User,
68 }
69 }
70}
71
72#[derive(Deserialize, Serialize)]
73struct CommandPermissionData {
74 id: Id<GenericMarker>,
76 #[serde(rename = "type")]
78 kind: CommandPermissionDataType,
79 permission: bool,
81}
82
83#[derive(Clone, Debug, Deserialize_repr, Eq, PartialEq, Serialize_repr)]
84#[non_exhaustive]
85#[repr(u8)]
86enum CommandPermissionDataType {
87 Role = 1,
88 User = 2,
89 Channel = 3,
90}
91
92impl<'de> Deserialize<'de> for CommandPermission {
93 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
94 let data = CommandPermissionData::deserialize(deserializer)?;
95
96 let id = match data.kind {
97 CommandPermissionDataType::Role => CommandPermissionType::Role(data.id.cast()),
98 CommandPermissionDataType::User => CommandPermissionType::User(data.id.cast()),
99 CommandPermissionDataType::Channel => CommandPermissionType::Channel(data.id.cast()),
100 };
101
102 Ok(Self {
103 id,
104 permission: data.permission,
105 })
106 }
107}
108
109impl Serialize for CommandPermission {
110 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
111 let data = CommandPermissionData {
112 id: self.id.id(),
113 kind: self.id.kind(),
114 permission: self.permission,
115 };
116
117 data.serialize(serializer)
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::{
124 CommandPermission, CommandPermissionDataType, CommandPermissionType,
125 GuildCommandPermissions,
126 };
127 use crate::id::Id;
128 use serde_test::Token;
129
130 #[test]
131 fn serde_command_permission() {
132 let value = CommandPermission {
133 id: CommandPermissionType::Role(Id::new(100)),
134 permission: true,
135 };
136
137 serde_test::assert_tokens(
138 &value,
139 &[
140 Token::Struct {
141 name: "CommandPermissionData",
142 len: 3,
143 },
144 Token::Str("id"),
145 Token::NewtypeStruct { name: "Id" },
146 Token::Str("100"),
147 Token::Str("type"),
148 Token::U8(CommandPermissionDataType::Role as u8),
149 Token::Str("permission"),
150 Token::Bool(true),
151 Token::StructEnd,
152 ],
153 );
154 }
155
156 #[test]
157 fn serde_guild_command_permission() {
158 let value = GuildCommandPermissions {
159 application_id: Id::new(1),
160 guild_id: Id::new(2),
161 id: Id::new(3),
162 permissions: Vec::from([
163 CommandPermission {
164 id: CommandPermissionType::Channel(Id::new(50)),
165 permission: false,
166 },
167 CommandPermission {
168 id: CommandPermissionType::User(Id::new(200)),
169 permission: true,
170 },
171 ]),
172 };
173
174 serde_test::assert_tokens(
175 &value,
176 &[
177 Token::Struct {
178 name: "GuildCommandPermissions",
179 len: 4,
180 },
181 Token::Str("application_id"),
182 Token::NewtypeStruct { name: "Id" },
183 Token::Str("1"),
184 Token::Str("guild_id"),
185 Token::NewtypeStruct { name: "Id" },
186 Token::Str("2"),
187 Token::Str("id"),
188 Token::NewtypeStruct { name: "Id" },
189 Token::Str("3"),
190 Token::Str("permissions"),
191 Token::Seq { len: Some(2) },
192 Token::Struct {
193 name: "CommandPermissionData",
194 len: 3,
195 },
196 Token::Str("id"),
197 Token::NewtypeStruct { name: "Id" },
198 Token::Str("50"),
199 Token::Str("type"),
200 Token::U8(CommandPermissionDataType::Channel as u8),
201 Token::Str("permission"),
202 Token::Bool(false),
203 Token::StructEnd,
204 Token::Struct {
205 name: "CommandPermissionData",
206 len: 3,
207 },
208 Token::Str("id"),
209 Token::NewtypeStruct { name: "Id" },
210 Token::Str("200"),
211 Token::Str("type"),
212 Token::U8(CommandPermissionDataType::User as u8),
213 Token::Str("permission"),
214 Token::Bool(true),
215 Token::StructEnd,
216 Token::SeqEnd,
217 Token::StructEnd,
218 ],
219 );
220 }
221}