Skip to main content

twilight_model/channel/message/component/
kind.rs

1use serde::{Deserialize, Serialize};
2use std::fmt::{Display, Formatter, Result as FmtResult};
3
4/// Type of [`Component`].
5///
6/// [`Component`]: super::Component
7#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
8#[non_exhaustive]
9#[serde(from = "u8", into = "u8")]
10pub enum ComponentType {
11    /// Component is an [`ActionRow`].
12    ///
13    /// [`ActionRow`]: super::ActionRow
14    ActionRow,
15    /// Component is an [`Button`].
16    ///
17    /// [`Button`]: super::Button
18    Button,
19    /// Component is a [`SelectMenu`] with custom string options.
20    ///
21    /// [`SelectMenu`]: super::SelectMenu
22    TextSelectMenu,
23    /// Component is an [`TextInput`].
24    ///
25    /// [`TextInput`]: super::TextInput
26    TextInput,
27    /// Component is a [`SelectMenu`] for users.
28    ///
29    /// [`SelectMenu`]: super::SelectMenu
30    UserSelectMenu,
31    /// Component is a [`SelectMenu`] for roles.
32    ///
33    /// [`SelectMenu`]: super::SelectMenu
34    RoleSelectMenu,
35    /// Component is a [`SelectMenu`] for mentionables.
36    ///
37    /// [`SelectMenu`]: super::SelectMenu
38    MentionableSelectMenu,
39    /// Component is a [`SelectMenu`] for channels.
40    ///
41    /// [`SelectMenu`]: super::SelectMenu
42    ChannelSelectMenu,
43    /// Component is a [`Container`] to display text alongside an accessory component.
44    ///
45    /// [`Container`]: super::Container
46    Section,
47    /// Component is a [`TextDisplay`] containing markdown text.
48    ///
49    /// [`TextDisplay`]: super::TextDisplay
50    TextDisplay,
51    /// Component is a [`Thumbnail`] that can be used as an accessory.
52    ///
53    /// [`Thumbnail`]: super::Thumbnail
54    Thumbnail,
55    /// Component is a [`MediaGallery`] that displays images and other media.
56    ///
57    /// [`MediaGallery`]: super::MediaGallery
58    MediaGallery,
59    /// Component is a [`FileDisplay`] that displays an attached file.
60    ///
61    /// [`FileDisplay`]: super::FileDisplay
62    File,
63    /// Component is a [`Separator`] that adds vertical padding between other components.
64    ///
65    /// [`Separator`]: super::Separator
66    Separator,
67    /// Component is a [`Container`] that visually groups a set of components.
68    ///
69    /// [`Container`]: super::Container
70    Container,
71    /// Component is a [`Label`] that provides a label and an optional description
72    /// for modal components.
73    ///
74    /// [`Label`]: super::Label
75    Label,
76    /// Component is a [`FileUpload`] that allows uploading files in modals.
77    ///
78    /// [`FileUpload`]: super::FileUpload
79    FileUpload,
80    /// Component is a [`CheckboxGroup`] that allows for a group of selectable checkboxes in modals
81    ///
82    /// [`CheckboxGroup`]: super::CheckboxGroup
83    CheckboxGroup,
84    /// Component is a [`Checkbox`] that allows for a selectable checkbox in modals
85    ///
86    /// [`Checkbox`]: super::Checkbox
87    Checkbox,
88    /// Variant value is unknown to the library.
89    Unknown(u8),
90}
91
92impl From<u8> for ComponentType {
93    fn from(value: u8) -> Self {
94        match value {
95            1 => ComponentType::ActionRow,
96            2 => ComponentType::Button,
97            3 => ComponentType::TextSelectMenu,
98            4 => ComponentType::TextInput,
99            5 => ComponentType::UserSelectMenu,
100            6 => ComponentType::RoleSelectMenu,
101            7 => ComponentType::MentionableSelectMenu,
102            8 => ComponentType::ChannelSelectMenu,
103            9 => ComponentType::Section,
104            10 => ComponentType::TextDisplay,
105            11 => ComponentType::Thumbnail,
106            12 => ComponentType::MediaGallery,
107            13 => ComponentType::File,
108            14 => ComponentType::Separator,
109            17 => ComponentType::Container,
110            18 => ComponentType::Label,
111            19 => ComponentType::FileUpload,
112            22 => ComponentType::CheckboxGroup,
113            23 => ComponentType::Checkbox,
114            unknown => ComponentType::Unknown(unknown),
115        }
116    }
117}
118
119impl From<ComponentType> for u8 {
120    fn from(value: ComponentType) -> Self {
121        match value {
122            ComponentType::ActionRow => 1,
123            ComponentType::Button => 2,
124            ComponentType::TextSelectMenu => 3,
125            ComponentType::TextInput => 4,
126            ComponentType::UserSelectMenu => 5,
127            ComponentType::RoleSelectMenu => 6,
128            ComponentType::MentionableSelectMenu => 7,
129            ComponentType::ChannelSelectMenu => 8,
130            ComponentType::Section => 9,
131            ComponentType::TextDisplay => 10,
132            ComponentType::Thumbnail => 11,
133            ComponentType::MediaGallery => 12,
134            ComponentType::File => 13,
135            ComponentType::Separator => 14,
136            ComponentType::Container => 17,
137            ComponentType::Label => 18,
138            ComponentType::FileUpload => 19,
139            ComponentType::CheckboxGroup => 22,
140            ComponentType::Checkbox => 23,
141            ComponentType::Unknown(unknown) => unknown,
142        }
143    }
144}
145
146impl ComponentType {
147    /// Name of the component type.
148    ///
149    /// Variants have a name equivalent to the variant name itself.
150    ///
151    /// # Examples
152    ///
153    /// Check the [`ActionRow`] variant's name:
154    ///
155    /// ```
156    /// use twilight_model::channel::message::component::ComponentType;
157    ///
158    /// assert_eq!("ActionRow", ComponentType::ActionRow.name());
159    /// ```
160    ///
161    /// [`ActionRow`]: Self::ActionRow
162    pub const fn name(self) -> &'static str {
163        match self {
164            ComponentType::ActionRow => "ActionRow",
165            ComponentType::Button => "Button",
166            ComponentType::TextSelectMenu
167            | ComponentType::UserSelectMenu
168            | ComponentType::RoleSelectMenu
169            | ComponentType::MentionableSelectMenu
170            | ComponentType::ChannelSelectMenu => "SelectMenu",
171            ComponentType::TextInput => "TextInput",
172            ComponentType::Section => "Section",
173            ComponentType::TextDisplay => "TextDisplay",
174            ComponentType::Thumbnail => "Thumbnail",
175            ComponentType::MediaGallery => "MediaGallery",
176            ComponentType::File => "File",
177            ComponentType::Separator => "Separator",
178            ComponentType::Container => "Container",
179            ComponentType::Label => "Label",
180            ComponentType::FileUpload => "FileUpload",
181            ComponentType::CheckboxGroup => "CheckboxGroup",
182            ComponentType::Checkbox => "Checkbox",
183            ComponentType::Unknown(_) => "Unknown",
184        }
185    }
186}
187
188impl Display for ComponentType {
189    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
190        f.write_str(self.name())
191    }
192}
193
194#[cfg(test)]
195mod tests {
196    use super::*;
197    use serde_test::Token;
198    use static_assertions::assert_impl_all;
199    use std::{fmt::Debug, hash::Hash};
200
201    assert_impl_all!(
202        ComponentType: Clone,
203        Copy,
204        Debug,
205        Deserialize<'static>,
206        Eq,
207        Hash,
208        PartialEq,
209        Send,
210        Serialize,
211        Sync
212    );
213
214    #[test]
215    fn variants() {
216        serde_test::assert_tokens(&ComponentType::ActionRow, &[Token::U8(1)]);
217        serde_test::assert_tokens(&ComponentType::Button, &[Token::U8(2)]);
218        serde_test::assert_tokens(&ComponentType::TextSelectMenu, &[Token::U8(3)]);
219        serde_test::assert_tokens(&ComponentType::TextInput, &[Token::U8(4)]);
220        serde_test::assert_tokens(&ComponentType::UserSelectMenu, &[Token::U8(5)]);
221        serde_test::assert_tokens(&ComponentType::RoleSelectMenu, &[Token::U8(6)]);
222        serde_test::assert_tokens(&ComponentType::MentionableSelectMenu, &[Token::U8(7)]);
223        serde_test::assert_tokens(&ComponentType::ChannelSelectMenu, &[Token::U8(8)]);
224        serde_test::assert_tokens(&ComponentType::Section, &[Token::U8(9)]);
225        serde_test::assert_tokens(&ComponentType::TextDisplay, &[Token::U8(10)]);
226        serde_test::assert_tokens(&ComponentType::Thumbnail, &[Token::U8(11)]);
227        serde_test::assert_tokens(&ComponentType::MediaGallery, &[Token::U8(12)]);
228        serde_test::assert_tokens(&ComponentType::File, &[Token::U8(13)]);
229        serde_test::assert_tokens(&ComponentType::Separator, &[Token::U8(14)]);
230        serde_test::assert_tokens(&ComponentType::Container, &[Token::U8(17)]);
231        serde_test::assert_tokens(&ComponentType::Label, &[Token::U8(18)]);
232        serde_test::assert_tokens(&ComponentType::Unknown(99), &[Token::U8(99)]);
233    }
234
235    #[test]
236    fn names() {
237        assert_eq!("ActionRow", ComponentType::ActionRow.name());
238        assert_eq!("Button", ComponentType::Button.name());
239        assert_eq!("SelectMenu", ComponentType::TextSelectMenu.name());
240        assert_eq!("SelectMenu", ComponentType::UserSelectMenu.name());
241        assert_eq!("SelectMenu", ComponentType::RoleSelectMenu.name());
242        assert_eq!("SelectMenu", ComponentType::MentionableSelectMenu.name());
243        assert_eq!("SelectMenu", ComponentType::ChannelSelectMenu.name());
244        assert_eq!("TextInput", ComponentType::TextInput.name());
245        assert_eq!("Section", ComponentType::Section.name());
246        assert_eq!("TextDisplay", ComponentType::TextDisplay.name());
247        assert_eq!("Thumbnail", ComponentType::Thumbnail.name());
248        assert_eq!("MediaGallery", ComponentType::MediaGallery.name());
249        assert_eq!("File", ComponentType::File.name());
250        assert_eq!("Separator", ComponentType::Separator.name());
251        assert_eq!("Container", ComponentType::Container.name());
252        assert_eq!("Label", ComponentType::Label.name());
253        assert_eq!("Unknown", ComponentType::Unknown(99).name());
254    }
255}