twilight_http/request/guild/create_guild/
builder.rs

1use super::{CategoryFields, GuildChannelFields, RoleFields, TextFields, VoiceFields};
2use std::{
3    error::Error,
4    fmt::{Display, Formatter, Result as FmtResult},
5};
6use twilight_model::{
7    channel::ChannelType,
8    guild::Permissions,
9    http::permission_overwrite::PermissionOverwrite,
10    id::{
11        marker::{ChannelMarker, RoleMarker},
12        Id,
13    },
14};
15
16/// Error building role fields.
17#[derive(Debug)]
18pub struct RoleFieldsError {
19    kind: RoleFieldsErrorType,
20}
21
22impl RoleFieldsError {
23    /// Immutable reference to the type of error that occurred.
24    #[must_use = "retrieving the type has no effect if left unused"]
25    pub const fn kind(&self) -> &RoleFieldsErrorType {
26        &self.kind
27    }
28
29    /// Consume the error, returning the source error if there is any.
30    #[allow(clippy::unused_self)]
31    #[must_use = "consuming the error and retrieving the source has no effect if left unused"]
32    pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
33        None
34    }
35
36    /// Consume the error, returning the owned error type and the source error.
37    #[must_use = "consuming the error into its parts has no effect if left unused"]
38    pub fn into_parts(self) -> (RoleFieldsErrorType, Option<Box<dyn Error + Send + Sync>>) {
39        (self.kind, None)
40    }
41}
42
43impl Display for RoleFieldsError {
44    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
45        match &self.kind {
46            RoleFieldsErrorType::ColorNotRgb { color } => {
47                f.write_str("the color ")?;
48                Display::fmt(color, f)?;
49
50                f.write_str(" is invalid")
51            }
52            RoleFieldsErrorType::IdInvalid => {
53                f.write_str("the given id value is 1, which is not acceptable")
54            }
55        }
56    }
57}
58
59impl Error for RoleFieldsError {}
60
61/// Type of [`RoleFieldsError`] that occurred.
62#[derive(Debug)]
63#[non_exhaustive]
64pub enum RoleFieldsErrorType {
65    /// Color was larger than a valid RGB hexadecimal value.
66    ColorNotRgb {
67        /// Provided color hex value.
68        color: u32,
69    },
70    /// Invalid id for builders.
71    IdInvalid,
72}
73
74/// A builder for role fields.
75#[derive(Debug)]
76#[must_use = "must be built into a role"]
77pub struct RoleFieldsBuilder(Result<RoleFields, RoleFieldsError>);
78
79impl RoleFieldsBuilder {
80    /// The maximum accepted color value.
81    ///
82    /// This is used by [`color`].
83    ///
84    /// [`color`]: Self::color
85    pub const COLOR_MAXIMUM: u32 = 0xff_ff_ff;
86
87    const ROLE_ID: Id<RoleMarker> = Id::new(1);
88
89    /// Create a new default role field builder.
90    pub const fn new(name: String) -> Self {
91        Self(Ok(RoleFields {
92            color: None,
93            hoist: None,
94            id: Self::ROLE_ID,
95            mentionable: None,
96            name,
97            permissions: None,
98            position: None,
99        }))
100    }
101
102    /// Build the role fields.
103    ///
104    /// # Errors
105    ///
106    /// Returns a [`RoleFieldsErrorType::ColorNotRgb`] error type if the color
107    /// is not valid RGB.
108    #[allow(clippy::missing_const_for_fn)]
109    pub fn build(self) -> Result<RoleFields, RoleFieldsError> {
110        self.0
111    }
112
113    /// Set the role color.
114    ///
115    /// This must be a valid hexadecimal RGB value. `0x000000` is ignored
116    /// and doesn't count towards the final computed color in the user list.
117    /// Refer to [`Self::COLOR_MAXIMUM`] for the maximum
118    /// acceptable value.
119    pub fn color(mut self, color: u32) -> Self {
120        self.0 = self.0.and_then(|mut fields| {
121            if color > Self::COLOR_MAXIMUM {
122                return Err(RoleFieldsError {
123                    kind: RoleFieldsErrorType::ColorNotRgb { color },
124                });
125            }
126
127            fields.color.replace(color);
128
129            Ok(fields)
130        });
131
132        self
133    }
134
135    /// Show the role above other roles in the user list.
136    pub fn hoist(mut self) -> Self {
137        if let Ok(fields) = self.0.as_mut() {
138            fields.hoist = Some(true);
139        }
140
141        self
142    }
143
144    /// Set the id of the role.
145    ///
146    /// # Errors
147    ///
148    /// Returns a [`RoleFieldsErrorType::IdInvalid`] error type if the ID is set
149    /// to 1.
150    pub fn id(mut self, id: Id<RoleMarker>) -> Self {
151        self.0 = self.0.and_then(|mut fields| {
152            if id == Self::ROLE_ID {
153                return Err(RoleFieldsError {
154                    kind: RoleFieldsErrorType::IdInvalid,
155                });
156            }
157
158            fields.id = id;
159
160            Ok(fields)
161        });
162
163        self
164    }
165
166    /// Allow the role to be @mentioned.
167    pub fn mentionable(mut self) -> Self {
168        if let Ok(fields) = self.0.as_mut() {
169            fields.mentionable = Some(true);
170        }
171
172        self
173    }
174
175    /// Set the permissions of the role.
176    pub fn permissions(mut self, permissions: Permissions) -> Self {
177        if let Ok(fields) = self.0.as_mut() {
178            fields.permissions = Some(permissions);
179        }
180
181        self
182    }
183
184    /// Set the position of the role.
185    pub fn position(mut self, position: i64) -> Self {
186        if let Ok(fields) = self.0.as_mut() {
187            fields.position = Some(position);
188        }
189
190        self
191    }
192}
193
194/// Error building text fields.
195#[derive(Debug)]
196pub struct TextFieldsError {
197    kind: TextFieldsErrorType,
198}
199
200impl TextFieldsError {
201    /// Immutable reference to the type of error that occurred.
202    #[must_use = "retrieving the type has no effect if left unused"]
203    pub const fn kind(&self) -> &TextFieldsErrorType {
204        &self.kind
205    }
206
207    /// Consume the error, returning the source error if there is any.
208    #[allow(clippy::unused_self)]
209    #[must_use = "consuming the error and retrieving the source has no effect if left unused"]
210    pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
211        None
212    }
213
214    /// Consume the error, returning the owned error type and the source error.
215    #[must_use = "consuming the error into its parts has no effect if left unused"]
216    pub fn into_parts(self) -> (TextFieldsErrorType, Option<Box<dyn Error + Send + Sync>>) {
217        (self.kind, None)
218    }
219}
220
221impl Display for TextFieldsError {
222    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
223        match &self.kind {
224            TextFieldsErrorType::NameTooShort { name } => {
225                f.write_str("the name is too short: ")?;
226
227                Display::fmt(&name.len(), f)
228            }
229            TextFieldsErrorType::NameTooLong { name } => {
230                f.write_str("the name is too long: ")?;
231
232                Display::fmt(&name.len(), f)
233            }
234            TextFieldsErrorType::RateLimitInvalid { limit } => {
235                f.write_str("the rate limit ")?;
236                Display::fmt(limit, f)?;
237
238                f.write_str(" is invalid")
239            }
240            TextFieldsErrorType::TopicTooLong { topic } => {
241                f.write_str("the topic is too long: ")?;
242
243                Display::fmt(&topic.len(), f)
244            }
245        }
246    }
247}
248
249impl Error for TextFieldsError {}
250
251/// Type of [`TextFieldsError`] that occurred.
252#[derive(Debug)]
253#[non_exhaustive]
254pub enum TextFieldsErrorType {
255    /// The name is too short.
256    NameTooShort {
257        /// The invalid name.
258        name: String,
259    },
260    /// The name is too long.
261    NameTooLong {
262        /// The invalid name.
263        name: String,
264    },
265    /// The rate limit is invalid.
266    RateLimitInvalid {
267        /// The incorrect rate limit.
268        limit: u16,
269    },
270    /// The topic is too long.
271    TopicTooLong {
272        /// The incorrect topic.
273        topic: String,
274    },
275}
276
277/// A builder for text fields.
278#[derive(Debug)]
279#[must_use = "must be built into a text channel"]
280pub struct TextFieldsBuilder(Result<TextFields, TextFieldsError>);
281
282impl TextFieldsBuilder {
283    /// The minimum number of UTF-16 code points that can be in a channel name.
284    ///
285    /// This is used by [`new`].
286    ///
287    /// [`new`]: Self::new
288    pub const MIN_NAME_LENGTH: usize = 1;
289
290    /// The maximum number of UTF-16 code points that can be in a channel name.
291    ///
292    /// This is used by [`new`].
293    ///
294    /// [`new`]: Self::new
295    pub const MAX_NAME_LENGTH: usize = 100;
296
297    /// The maximum length of a rate limit.
298    ///
299    /// This is used by [`rate_limit_per_user`].
300    ///
301    /// [`rate_limit_per_user`]: Self::rate_limit_per_user
302    pub const MAX_RATE_LIMIT: u16 = 21600;
303
304    /// The maximum number of UTF-16 code points that can be in a channel topic.
305    ///
306    /// This is used by [`topic`].
307    ///
308    /// [`topic`]: Self::topic
309    pub const MAX_TOPIC_LENGTH: usize = 1024;
310
311    /// Create a new text fields builder.
312    pub fn new(name: String) -> Self {
313        let fields = Ok(TextFields {
314            id: Id::new(1),
315            kind: ChannelType::GuildText,
316            name: String::new(),
317            nsfw: None,
318            permission_overwrites: None,
319            parent_id: None,
320            rate_limit_per_user: None,
321            topic: None,
322        })
323        .and_then(|mut fields| {
324            if name.len() < Self::MIN_NAME_LENGTH {
325                return Err(TextFieldsError {
326                    kind: TextFieldsErrorType::NameTooShort { name },
327                });
328            }
329
330            if name.len() > Self::MAX_NAME_LENGTH {
331                return Err(TextFieldsError {
332                    kind: TextFieldsErrorType::NameTooLong { name },
333                });
334            }
335
336            fields.name = name;
337
338            Ok(fields)
339        });
340
341        Self(fields)
342    }
343
344    /// Build the text fields.
345    ///
346    /// # Errors
347    ///
348    /// Returns a [`TextFieldsErrorType::NameTooShort`] error type if the name
349    /// is too short.
350    ///
351    /// Returns a [`TextFieldsErrorType::NameTooLong`] error type if the name is
352    /// too long.
353    #[allow(clippy::missing_const_for_fn)]
354    pub fn build(self) -> Result<TextFields, TextFieldsError> {
355        self.0
356    }
357
358    /// Make the channel NSFW.
359    pub fn nsfw(mut self) -> Self {
360        if let Ok(fields) = self.0.as_mut() {
361            fields.nsfw = Some(true);
362        }
363
364        self
365    }
366
367    /// Set the channel's permission overwrites.
368    pub fn permission_overwrites(mut self, overwrites: Vec<PermissionOverwrite>) -> Self {
369        if let Ok(fields) = self.0.as_mut() {
370            fields.permission_overwrites.replace(overwrites);
371        }
372
373        self
374    }
375
376    /// Set the channel's rate limit per user.
377    ///
378    /// # Errors
379    ///
380    /// Returns a [`TextFieldsErrorType::RateLimitInvalid`] error type if the
381    /// rate limit is invalid.
382    pub fn rate_limit_per_user(mut self, limit: u16) -> Self {
383        self.0 = self.0.and_then(|mut fields| {
384            if limit > Self::MAX_RATE_LIMIT {
385                return Err(TextFieldsError {
386                    kind: TextFieldsErrorType::RateLimitInvalid { limit },
387                });
388            }
389
390            fields.rate_limit_per_user.replace(limit);
391
392            Ok(fields)
393        });
394
395        self
396    }
397
398    /// Set the channel's topic.
399    ///
400    /// # Errors
401    ///
402    /// Returns a [`TextFieldsErrorType::TopicTooLong`] error type if the topic
403    /// is too long.
404    pub fn topic(mut self, topic: String) -> Self {
405        self.0 = self.0.and_then(|mut fields| {
406            if topic.len() > Self::MAX_TOPIC_LENGTH {
407                return Err(TextFieldsError {
408                    kind: TextFieldsErrorType::TopicTooLong { topic },
409                });
410            }
411
412            fields.topic.replace(topic);
413
414            Ok(fields)
415        });
416
417        self
418    }
419}
420
421/// Error building voice fields.
422#[derive(Debug)]
423pub struct VoiceFieldsError {
424    kind: VoiceFieldsErrorType,
425}
426
427impl VoiceFieldsError {
428    /// Immutable reference to the type of error that occurred.
429    #[must_use = "retrieving the type has no effect if left unused"]
430    pub const fn kind(&self) -> &VoiceFieldsErrorType {
431        &self.kind
432    }
433
434    /// Consume the error, returning the source error if there is any.
435    #[allow(clippy::unused_self)]
436    #[must_use = "consuming the error and retrieving the source has no effect if left unused"]
437    pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
438        None
439    }
440
441    /// Consume the error, returning the owned error type and the source error.
442    #[must_use = "consuming the error into its parts has no effect if left unused"]
443    pub fn into_parts(self) -> (VoiceFieldsErrorType, Option<Box<dyn Error + Send + Sync>>) {
444        (self.kind, None)
445    }
446}
447
448impl Display for VoiceFieldsError {
449    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
450        match &self.kind {
451            VoiceFieldsErrorType::NameTooShort { name } => {
452                f.write_str("the name is too short: ")?;
453
454                Display::fmt(&name.len(), f)
455            }
456            VoiceFieldsErrorType::NameTooLong { name } => {
457                f.write_str("the name is too long: ")?;
458
459                Display::fmt(&name.len(), f)
460            }
461        }
462    }
463}
464
465impl Error for VoiceFieldsError {}
466
467/// Type of [`VoiceFieldsError`] that occurred.
468#[derive(Debug)]
469#[non_exhaustive]
470pub enum VoiceFieldsErrorType {
471    /// The name is too short.
472    NameTooShort {
473        /// The invalid name.
474        name: String,
475    },
476    /// The name is too long.
477    NameTooLong {
478        /// The invalid name.
479        name: String,
480    },
481}
482
483/// A builder for voice fields.
484#[derive(Debug)]
485#[must_use = "must be built into a voice channel"]
486pub struct VoiceFieldsBuilder(Result<VoiceFields, VoiceFieldsError>);
487
488impl VoiceFieldsBuilder {
489    /// The minimum number of UTF-16 code points that can be in a channel name.
490    ///
491    /// This is used by [`new`].
492    ///
493    /// [`new`]: Self::new
494    pub const MIN_NAME_LENGTH: usize = 1;
495
496    /// The maximum number of UTF-16 code points that can be in a channel name.
497    ///
498    /// This is used by [`new`].
499    ///
500    /// [`new`]: Self::new
501    pub const MAX_NAME_LENGTH: usize = 100;
502
503    /// Create a new voice fields builder.
504    pub fn new(name: String) -> Self {
505        let fields = Ok(VoiceFields {
506            bitrate: None,
507            id: Id::new(1),
508            kind: ChannelType::GuildVoice,
509            name: String::new(),
510            permission_overwrites: None,
511            parent_id: None,
512            user_limit: None,
513        })
514        .and_then(|mut fields| {
515            if name.len() < Self::MIN_NAME_LENGTH {
516                return Err(VoiceFieldsError {
517                    kind: VoiceFieldsErrorType::NameTooShort { name },
518                });
519            }
520
521            if name.len() > Self::MAX_NAME_LENGTH {
522                return Err(VoiceFieldsError {
523                    kind: VoiceFieldsErrorType::NameTooLong { name },
524                });
525            }
526
527            fields.name = name;
528
529            Ok(fields)
530        });
531
532        Self(fields)
533    }
534
535    /// Build the voice fields.
536    ///
537    /// # Errors
538    ///
539    /// Returns a [`VoiceFieldsErrorType::NameTooShort`] error type if the name
540    /// is too short.
541    ///
542    /// Returns a [`VoiceFieldsErrorType::NameTooLong`] error type if the name
543    /// is too long.
544    #[allow(clippy::missing_const_for_fn)]
545    pub fn build(self) -> Result<VoiceFields, VoiceFieldsError> {
546        self.0
547    }
548
549    /// Set the voice channel's bitrate.
550    pub fn bitrate(mut self, bitrate: u32) -> Self {
551        if let Ok(fields) = self.0.as_mut() {
552            fields.bitrate = Some(bitrate);
553        }
554
555        self
556    }
557
558    /// Set the channel's permission overwrites.
559    pub fn permission_overwrites(mut self, overwrites: Vec<PermissionOverwrite>) -> Self {
560        if let Ok(fields) = self.0.as_mut() {
561            fields.permission_overwrites.replace(overwrites);
562        }
563
564        self
565    }
566
567    /// Set the voice channel's user limit.
568    pub fn user_limit(mut self, limit: u16) -> Self {
569        if let Ok(fields) = self.0.as_mut() {
570            fields.user_limit = Some(limit);
571        }
572
573        self
574    }
575}
576
577/// Error creating category fields.
578#[derive(Debug)]
579pub struct CategoryFieldsError {
580    kind: CategoryFieldsErrorType,
581}
582
583impl CategoryFieldsError {
584    /// Immutable reference to the type of error that occurred.
585    #[must_use = "retrieving the type has no effect if left unused"]
586    pub const fn kind(&self) -> &CategoryFieldsErrorType {
587        &self.kind
588    }
589
590    /// Consume the error, returning the source error if there is any.
591    #[allow(clippy::unused_self)]
592    #[must_use = "consuming the error and retrieving the source has no effect if left unused"]
593    pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
594        None
595    }
596
597    /// Consume the error, returning the owned error type and the source error.
598    #[must_use = "consuming the error into its parts has no effect if left unused"]
599    pub fn into_parts(
600        self,
601    ) -> (
602        CategoryFieldsErrorType,
603        Option<Box<dyn Error + Send + Sync>>,
604    ) {
605        (self.kind, None)
606    }
607}
608
609impl Display for CategoryFieldsError {
610    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
611        match &self.kind {
612            CategoryFieldsErrorType::NameTooShort { name } => {
613                f.write_str("the name is too short: ")?;
614
615                Display::fmt(&name.len(), f)
616            }
617            CategoryFieldsErrorType::NameTooLong { name } => {
618                f.write_str("the name is too long: ")?;
619
620                Display::fmt(&name.len(), f)
621            }
622        }
623    }
624}
625
626impl Error for CategoryFieldsError {}
627
628/// Type of [`CategoryFieldsError`] that occurred.
629#[derive(Debug)]
630#[non_exhaustive]
631pub enum CategoryFieldsErrorType {
632    /// The name is too short.
633    NameTooShort {
634        /// The invalid name.
635        name: String,
636    },
637    /// The name is too long.
638    NameTooLong {
639        /// The invalid name.
640        name: String,
641    },
642}
643
644/// A builder for a category channel, and its children.
645#[derive(Debug)]
646#[must_use = "must be built into a category channel"]
647pub struct CategoryFieldsBuilder {
648    fields: Result<CategoryFields, CategoryFieldsError>,
649    channels: Vec<GuildChannelFields>,
650}
651
652impl CategoryFieldsBuilder {
653    /// The minimum number of UTF-16 code points that can be in a channel name.
654    ///
655    /// This is used by [`new`].
656    ///
657    /// [`new`]: Self::new
658    pub const MIN_NAME_LENGTH: usize = 1;
659
660    /// The maximum number of UTF-16 code points that can be in a channel name.
661    ///
662    /// This is used by [`new`].
663    ///
664    /// [`new`]: Self::new
665    pub const MAX_NAME_LENGTH: usize = 100;
666
667    /// Create a new category fields builder.
668    pub fn new(name: String) -> Self {
669        let fields = Ok(CategoryFields {
670            id: Id::new(1),
671            name: String::new(),
672            kind: ChannelType::GuildCategory,
673            permission_overwrites: None,
674        })
675        .and_then(|mut fields| {
676            if name.len() < Self::MIN_NAME_LENGTH {
677                return Err(CategoryFieldsError {
678                    kind: CategoryFieldsErrorType::NameTooShort { name },
679                });
680            }
681
682            if name.len() > Self::MAX_NAME_LENGTH {
683                return Err(CategoryFieldsError {
684                    kind: CategoryFieldsErrorType::NameTooLong { name },
685                });
686            }
687
688            fields.name = name;
689
690            Ok(fields)
691        });
692
693        Self {
694            fields,
695            channels: Vec::new(),
696        }
697    }
698
699    /// Build the category fields.
700    ///
701    /// # Errors
702    ///
703    /// Returns a [`CategoryFieldsErrorType::NameTooShort`] error type if the
704    /// name is too short.
705    ///
706    /// Returns a [`CategoryFieldsErrorType::NameTooLong`] error type if the
707    /// name is too long.
708    pub(super) fn build(
709        mut self,
710        id: Id<ChannelMarker>,
711    ) -> Result<Vec<GuildChannelFields>, CategoryFieldsError> {
712        let fields = self.fields?;
713
714        for channel in &mut self.channels {
715            match channel {
716                GuildChannelFields::Text(t) => t.parent_id.replace(id),
717                GuildChannelFields::Voice(v) => v.parent_id.replace(id),
718                GuildChannelFields::Category(_) => None,
719            };
720        }
721
722        self.channels.insert(
723            0,
724            GuildChannelFields::Category(CategoryFields { id, ..fields }),
725        );
726
727        Ok(self.channels)
728    }
729
730    /// Add a child text channel.
731    pub fn add_text(mut self, channel: TextFields) -> Self {
732        self.channels.push(GuildChannelFields::Text(channel));
733
734        self
735    }
736
737    /// add a child voice channel.
738    pub fn add_voice(mut self, channel: VoiceFields) -> Self {
739        self.channels.push(GuildChannelFields::Voice(channel));
740
741        self
742    }
743}
744
745/// A builder for a list of channels.
746#[derive(Debug)]
747#[must_use = "must be built into a list of channels"]
748pub struct GuildChannelFieldsBuilder(Result<Vec<GuildChannelFields>, CategoryFieldsError>);
749
750impl GuildChannelFieldsBuilder {
751    /// Create a new channels builder.
752    pub const fn new() -> Self {
753        Self(Ok(Vec::new()))
754    }
755
756    /// Build the list of channels.
757    ///
758    /// # Errors
759    ///
760    /// Returns a [`CategoryFieldsErrorType::NameTooShort`] error type if the
761    /// name of a category is too short.
762    ///
763    /// Returns a [`CategoryFieldsErrorType::NameTooLong`] error type if the
764    /// name of a category is too long.
765    #[allow(clippy::missing_const_for_fn)]
766    pub fn build(self) -> Result<Vec<GuildChannelFields>, CategoryFieldsError> {
767        self.0
768    }
769
770    /// Add a text channel to the builder.
771    pub fn add_text(mut self, channel: TextFields) -> Self {
772        if let Ok(list) = self.0.as_mut() {
773            list.push(GuildChannelFields::Text(channel));
774        }
775
776        self
777    }
778
779    /// Add a voice channel to the builder.
780    pub fn add_voice(mut self, channel: VoiceFields) -> Self {
781        if let Ok(list) = self.0.as_mut() {
782            list.push(GuildChannelFields::Voice(channel));
783        }
784
785        self
786    }
787
788    /// Add a category channel builder, and all its children to the builder.
789    pub fn add_category_builder(mut self, channel: CategoryFieldsBuilder) -> Self {
790        self.0 = self.0.and_then(|mut list| {
791            let last_id = list
792                .iter()
793                .rev()
794                .find(|c| matches!(c, GuildChannelFields::Category(_)))
795                .map_or(Id::new(1), GuildChannelFields::id);
796
797            let mut channels = channel.build(Id::new(last_id.get() + 1))?;
798
799            list.append(&mut channels);
800
801            Ok(list)
802        });
803
804        self
805    }
806}
807
808impl Default for GuildChannelFieldsBuilder {
809    fn default() -> Self {
810        Self::new()
811    }
812}
813
814#[cfg(test)]
815mod tests {
816    use super::{
817        super::{CategoryFields, GuildChannelFields, RoleFields, TextFields, VoiceFields},
818        CategoryFieldsBuilder, CategoryFieldsErrorType, GuildChannelFieldsBuilder,
819        RoleFieldsBuilder, RoleFieldsErrorType, TextFieldsBuilder, TextFieldsErrorType,
820        VoiceFieldsBuilder, VoiceFieldsErrorType,
821    };
822    use static_assertions::assert_impl_all;
823    use std::fmt::Debug;
824    use twilight_model::{
825        channel::ChannelType,
826        guild::Permissions,
827        http::permission_overwrite::{PermissionOverwrite, PermissionOverwriteType},
828        id::Id,
829    };
830
831    assert_impl_all!(RoleFieldsBuilder: Debug, Send, Sync);
832    assert_impl_all!(TextFieldsBuilder: Debug, Send, Sync);
833    assert_impl_all!(VoiceFieldsBuilder: Debug, Send, Sync);
834    assert_impl_all!(CategoryFieldsBuilder: Debug, Send, Sync);
835    assert_impl_all!(GuildChannelFieldsBuilder: Debug, Send, Sync);
836
837    fn perms() -> Permissions {
838        Permissions::CONNECT | Permissions::SPEAK | Permissions::SEND_TTS_MESSAGES
839    }
840
841    fn overwrite() -> PermissionOverwrite {
842        PermissionOverwrite {
843            allow: Some(perms()),
844            deny: Some(Permissions::empty()),
845            id: Id::new(2),
846            kind: PermissionOverwriteType::Role,
847        }
848    }
849
850    fn voice() -> VoiceFields {
851        VoiceFieldsBuilder::new("voicename".to_owned())
852            .bitrate(96_000)
853            .permission_overwrites(vec![overwrite()])
854            .user_limit(40)
855            .build()
856            .unwrap()
857    }
858
859    #[test]
860    fn role_fields() {
861        assert!(matches!(
862            RoleFieldsBuilder::new("role".to_owned())
863                .color(123_123_123)
864                .build()
865                .unwrap_err()
866                .kind(),
867            RoleFieldsErrorType::ColorNotRgb { color: 123_123_123 },
868        ));
869
870        let fields = RoleFieldsBuilder::new("rolename".to_owned())
871            .color(0x12_34_56)
872            .hoist()
873            .id(Id::new(2))
874            .mentionable()
875            .permissions(Permissions::empty())
876            .position(1)
877            .build()
878            .unwrap();
879
880        assert_eq!(
881            fields,
882            RoleFields {
883                color: Some(0x12_34_56),
884                hoist: Some(true),
885                id: Id::new(2),
886                mentionable: Some(true),
887                name: String::from("rolename"),
888                permissions: Some(Permissions::empty()),
889                position: Some(1),
890            }
891        );
892    }
893
894    #[test]
895    fn voice_fields() {
896        assert!(matches!(
897            VoiceFieldsBuilder::new(String::new()).build().unwrap_err().kind(),
898            VoiceFieldsErrorType::NameTooShort { name }
899            if name.is_empty()
900        ));
901
902        assert_eq!(
903            voice(),
904            VoiceFields {
905                bitrate: Some(96_000),
906                id: Id::new(1),
907                kind: ChannelType::GuildVoice,
908                name: String::from("voicename"),
909                permission_overwrites: Some(vec![PermissionOverwrite {
910                    allow: Some(perms()),
911                    deny: Some(Permissions::empty()),
912                    id: Id::new(2),
913                    kind: PermissionOverwriteType::Role,
914                }]),
915                parent_id: None,
916                user_limit: Some(40),
917            }
918        );
919    }
920
921    fn text() -> TextFields {
922        TextFieldsBuilder::new("textname".to_owned())
923            .nsfw()
924            .permission_overwrites(vec![overwrite()])
925            .rate_limit_per_user(4_000)
926            .topic("a topic".to_owned())
927            .build()
928            .unwrap()
929    }
930
931    #[test]
932    fn text_fields() {
933        assert!(matches!(
934            TextFieldsBuilder::new(String::new()).build().unwrap_err().kind(),
935            TextFieldsErrorType::NameTooShort { name }
936            if name.is_empty()
937        ));
938
939        assert_eq!(
940            text(),
941            TextFields {
942                id: Id::new(1),
943                kind: ChannelType::GuildText,
944                name: String::from("textname"),
945                nsfw: Some(true),
946                permission_overwrites: Some(vec![PermissionOverwrite {
947                    allow: Some(perms()),
948                    deny: Some(Permissions::empty()),
949                    id: Id::new(2),
950                    kind: PermissionOverwriteType::Role
951                }]),
952                parent_id: None,
953                rate_limit_per_user: Some(4_000),
954                topic: Some(String::from("a topic")),
955            }
956        );
957    }
958
959    fn category() -> CategoryFieldsBuilder {
960        CategoryFieldsBuilder::new("category".to_owned())
961            .add_text(text())
962            .add_voice(voice())
963    }
964
965    #[test]
966    fn category_fields() {
967        assert!(matches!(
968            CategoryFieldsBuilder::new(String::new()).build(Id::new(4)).unwrap_err().kind(),
969            CategoryFieldsErrorType::NameTooShort { name }
970            if name.is_empty()
971        ));
972
973        let fields = category();
974        let channels = GuildChannelFieldsBuilder::new().add_category_builder(fields);
975
976        assert_eq!(
977            channels.build().unwrap(),
978            vec![
979                GuildChannelFields::Category(CategoryFields {
980                    id: Id::new(2),
981                    kind: ChannelType::GuildCategory,
982                    name: String::from("category"),
983                    permission_overwrites: None,
984                }),
985                GuildChannelFields::Text(TextFields {
986                    id: Id::new(1),
987                    kind: ChannelType::GuildText,
988                    name: String::from("textname"),
989                    nsfw: Some(true),
990                    permission_overwrites: Some(vec![PermissionOverwrite {
991                        allow: Some(
992                            Permissions::CONNECT
993                                | Permissions::SPEAK
994                                | Permissions::SEND_TTS_MESSAGES
995                        ),
996                        deny: Some(Permissions::empty()),
997                        id: Id::new(2),
998                        kind: PermissionOverwriteType::Role,
999                    }]),
1000                    parent_id: Some(Id::new(2)),
1001                    rate_limit_per_user: Some(4_000),
1002                    topic: Some(String::from("a topic")),
1003                }),
1004                GuildChannelFields::Voice(VoiceFields {
1005                    bitrate: Some(96_000),
1006                    id: Id::new(1),
1007                    kind: ChannelType::GuildVoice,
1008                    name: String::from("voicename"),
1009                    permission_overwrites: Some(vec![PermissionOverwrite {
1010                        allow: Some(
1011                            Permissions::CONNECT
1012                                | Permissions::SPEAK
1013                                | Permissions::SEND_TTS_MESSAGES
1014                        ),
1015                        deny: Some(Permissions::empty()),
1016                        id: Id::new(2),
1017                        kind: PermissionOverwriteType::Role,
1018                    }]),
1019                    parent_id: Some(Id::new(2)),
1020                    user_limit: Some(40),
1021                }),
1022            ]
1023        );
1024    }
1025
1026    #[test]
1027    fn channels() {
1028        let channels = GuildChannelFieldsBuilder::new()
1029            .add_text(text())
1030            .add_voice(voice());
1031
1032        assert_eq!(
1033            channels.build().unwrap(),
1034            vec![
1035                GuildChannelFields::Text(TextFields {
1036                    id: Id::new(1),
1037                    kind: ChannelType::GuildText,
1038                    name: String::from("textname"),
1039                    nsfw: Some(true),
1040                    permission_overwrites: Some(vec![PermissionOverwrite {
1041                        allow: Some(
1042                            Permissions::CONNECT
1043                                | Permissions::SPEAK
1044                                | Permissions::SEND_TTS_MESSAGES
1045                        ),
1046                        deny: Some(Permissions::empty()),
1047                        id: Id::new(2),
1048                        kind: PermissionOverwriteType::Role,
1049                    }]),
1050                    parent_id: None,
1051                    rate_limit_per_user: Some(4_000),
1052                    topic: Some(String::from("a topic")),
1053                }),
1054                GuildChannelFields::Voice(VoiceFields {
1055                    bitrate: Some(96_000),
1056                    id: Id::new(1),
1057                    kind: ChannelType::GuildVoice,
1058                    name: String::from("voicename"),
1059                    permission_overwrites: Some(vec![PermissionOverwrite {
1060                        allow: Some(
1061                            Permissions::CONNECT
1062                                | Permissions::SPEAK
1063                                | Permissions::SEND_TTS_MESSAGES
1064                        ),
1065                        deny: Some(Permissions::empty()),
1066                        id: Id::new(2),
1067                        kind: PermissionOverwriteType::Role,
1068                    }]),
1069                    parent_id: None,
1070                    user_limit: Some(40),
1071                }),
1072            ]
1073        );
1074    }
1075}