tranquil/resolve/
integer.rs

1use serenity::{
2    async_trait,
3    builder::CreateApplicationCommandOption,
4    model::application::{
5        command::CommandOptionType, interaction::application_command::CommandDataOptionValue,
6    },
7};
8
9use crate::l10n::L10n;
10
11use super::{resolve_option, Resolve, ResolveContext, ResolveError, ResolveResult};
12
13pub const DISCORD_MIN_INTEGER: i64 = -9007199254740991;
14pub const DISCORD_MAX_INTEGER: i64 = 9007199254740991;
15
16macro_rules! impl_resolve_for_integer {
17    ($($t:ty),* $(,)?) => { $(
18        #[async_trait]
19        impl Resolve for $t {
20            const KIND: CommandOptionType = CommandOptionType::Integer;
21
22            fn describe(option: &mut CreateApplicationCommandOption, _l10n: &L10n) {
23                if let Ok(min) = i64::try_from(<$t>::MIN) {
24                    option.min_int_value(min.max(DISCORD_MIN_INTEGER));
25                }
26                if let Ok(max) = i64::try_from(<$t>::MAX) {
27                    option.max_int_value(max.min(DISCORD_MAX_INTEGER));
28                }
29            }
30
31            async fn resolve(ctx: ResolveContext) -> ResolveResult<Self> {
32                match resolve_option(ctx.option)? {
33                    CommandDataOptionValue::Integer(value) => {
34                        Ok(<$t>::try_from(value)?)
35                    }
36                    _ => Err(ResolveError::InvalidType),
37                }
38            }
39        }
40    )* };
41}
42
43impl_resolve_for_integer!(i8, i16, i32, i128, isize, u8, u16, u32, u64, u128, usize);
44
45macro_rules! impl_resolve_for_bounded_integer {
46    ($( $t:ty => $b:ident ),* $(,)?) => { $(
47        #[async_trait]
48        impl<const MIN: $t, const MAX: $t> Resolve for bounded_integer::$b<MIN, MAX> {
49            const KIND: CommandOptionType = CommandOptionType::Integer;
50
51            fn describe(option: &mut CreateApplicationCommandOption, _l10n: &L10n) {
52                if let Ok(min) = i64::try_from(<$t>::MIN) {
53                    option.min_int_value(min.max(DISCORD_MIN_INTEGER));
54                }
55                if let Ok(max) = i64::try_from(<$t>::MAX) {
56                    option.max_int_value(max.min(DISCORD_MAX_INTEGER));
57                }
58            }
59
60            async fn resolve(ctx: ResolveContext) -> ResolveResult<Self> {
61                match resolve_option(ctx.option)? {
62                    CommandDataOptionValue::Integer(value) => Self::new(
63                        <$t>::try_from(value)?,
64                    )
65                    .ok_or(ResolveError::IntegerRangeError),
66                    _ => Err(ResolveError::InvalidType),
67                }
68            }
69        }
70    )* };
71}
72
73impl_resolve_for_bounded_integer! {
74    i8 => BoundedI8,
75    i16 => BoundedI16,
76    i32 => BoundedI32,
77    i64 => BoundedI64,
78    i128 => BoundedI128,
79    isize => BoundedIsize,
80    u8 => BoundedU8,
81    u16 => BoundedU16,
82    u32 => BoundedU32,
83    u64 => BoundedU64,
84    u128 => BoundedU128,
85    usize => BoundedUsize,
86}