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    /// Variant value is unknown to the library.
72    Unknown(u8),
73}
74
75impl From<u8> for ComponentType {
76    fn from(value: u8) -> Self {
77        match value {
78            1 => ComponentType::ActionRow,
79            2 => ComponentType::Button,
80            3 => ComponentType::TextSelectMenu,
81            4 => ComponentType::TextInput,
82            5 => ComponentType::UserSelectMenu,
83            6 => ComponentType::RoleSelectMenu,
84            7 => ComponentType::MentionableSelectMenu,
85            8 => ComponentType::ChannelSelectMenu,
86            9 => ComponentType::Section,
87            10 => ComponentType::TextDisplay,
88            11 => ComponentType::Thumbnail,
89            12 => ComponentType::MediaGallery,
90            13 => ComponentType::File,
91            14 => ComponentType::Separator,
92            17 => ComponentType::Container,
93            unknown => ComponentType::Unknown(unknown),
94        }
95    }
96}
97
98impl From<ComponentType> for u8 {
99    fn from(value: ComponentType) -> Self {
100        match value {
101            ComponentType::ActionRow => 1,
102            ComponentType::Button => 2,
103            ComponentType::TextSelectMenu => 3,
104            ComponentType::TextInput => 4,
105            ComponentType::UserSelectMenu => 5,
106            ComponentType::RoleSelectMenu => 6,
107            ComponentType::MentionableSelectMenu => 7,
108            ComponentType::ChannelSelectMenu => 8,
109            ComponentType::Section => 9,
110            ComponentType::TextDisplay => 10,
111            ComponentType::Thumbnail => 11,
112            ComponentType::MediaGallery => 12,
113            ComponentType::File => 13,
114            ComponentType::Separator => 14,
115            ComponentType::Container => 17,
116            ComponentType::Unknown(unknown) => unknown,
117        }
118    }
119}
120
121impl ComponentType {
122    /// Name of the component type.
123    ///
124    /// Variants have a name equivalent to the variant name itself.
125    ///
126    /// # Examples
127    ///
128    /// Check the [`ActionRow`] variant's name:
129    ///
130    /// ```
131    /// use twilight_model::channel::message::component::ComponentType;
132    ///
133    /// assert_eq!("ActionRow", ComponentType::ActionRow.name());
134    /// ```
135    ///
136    /// [`ActionRow`]: Self::ActionRow
137    pub const fn name(self) -> &'static str {
138        match self {
139            ComponentType::ActionRow => "ActionRow",
140            ComponentType::Button => "Button",
141            ComponentType::TextSelectMenu
142            | ComponentType::UserSelectMenu
143            | ComponentType::RoleSelectMenu
144            | ComponentType::MentionableSelectMenu
145            | ComponentType::ChannelSelectMenu => "SelectMenu",
146            ComponentType::TextInput => "TextInput",
147            ComponentType::Section => "Section",
148            ComponentType::TextDisplay => "TextDisplay",
149            ComponentType::Thumbnail => "Thumbnail",
150            ComponentType::MediaGallery => "MediaGallery",
151            ComponentType::File => "File",
152            ComponentType::Separator => "Separator",
153            ComponentType::Container => "Container",
154            ComponentType::Unknown(_) => "Unknown",
155        }
156    }
157}
158
159impl Display for ComponentType {
160    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
161        f.write_str(self.name())
162    }
163}
164
165#[cfg(test)]
166mod tests {
167    use super::*;
168    use serde_test::Token;
169    use static_assertions::assert_impl_all;
170    use std::{fmt::Debug, hash::Hash};
171
172    assert_impl_all!(
173        ComponentType: Clone,
174        Copy,
175        Debug,
176        Deserialize<'static>,
177        Eq,
178        Hash,
179        PartialEq,
180        Send,
181        Serialize,
182        Sync
183    );
184
185    #[test]
186    fn variants() {
187        serde_test::assert_tokens(&ComponentType::ActionRow, &[Token::U8(1)]);
188        serde_test::assert_tokens(&ComponentType::Button, &[Token::U8(2)]);
189        serde_test::assert_tokens(&ComponentType::TextSelectMenu, &[Token::U8(3)]);
190        serde_test::assert_tokens(&ComponentType::TextInput, &[Token::U8(4)]);
191        serde_test::assert_tokens(&ComponentType::UserSelectMenu, &[Token::U8(5)]);
192        serde_test::assert_tokens(&ComponentType::RoleSelectMenu, &[Token::U8(6)]);
193        serde_test::assert_tokens(&ComponentType::MentionableSelectMenu, &[Token::U8(7)]);
194        serde_test::assert_tokens(&ComponentType::ChannelSelectMenu, &[Token::U8(8)]);
195        serde_test::assert_tokens(&ComponentType::Section, &[Token::U8(9)]);
196        serde_test::assert_tokens(&ComponentType::TextDisplay, &[Token::U8(10)]);
197        serde_test::assert_tokens(&ComponentType::Thumbnail, &[Token::U8(11)]);
198        serde_test::assert_tokens(&ComponentType::MediaGallery, &[Token::U8(12)]);
199        serde_test::assert_tokens(&ComponentType::File, &[Token::U8(13)]);
200        serde_test::assert_tokens(&ComponentType::Separator, &[Token::U8(14)]);
201        serde_test::assert_tokens(&ComponentType::Container, &[Token::U8(17)]);
202        serde_test::assert_tokens(&ComponentType::Unknown(99), &[Token::U8(99)]);
203    }
204
205    #[test]
206    fn names() {
207        assert_eq!("ActionRow", ComponentType::ActionRow.name());
208        assert_eq!("Button", ComponentType::Button.name());
209        assert_eq!("SelectMenu", ComponentType::TextSelectMenu.name());
210        assert_eq!("SelectMenu", ComponentType::UserSelectMenu.name());
211        assert_eq!("SelectMenu", ComponentType::RoleSelectMenu.name());
212        assert_eq!("SelectMenu", ComponentType::MentionableSelectMenu.name());
213        assert_eq!("SelectMenu", ComponentType::ChannelSelectMenu.name());
214        assert_eq!("TextInput", ComponentType::TextInput.name());
215        assert_eq!("Unknown", ComponentType::Unknown(99).name());
216    }
217}