diff --git a/assyst-core/src/command/arguments.rs b/assyst-core/src/command/arguments.rs index 16e9617..4d0afe4 100644 --- a/assyst-core/src/command/arguments.rs +++ b/assyst-core/src/command/arguments.rs @@ -13,6 +13,7 @@ use twilight_model::id::Id; use twilight_util::builder::command::{AttachmentBuilder, IntegerBuilder, NumberBuilder, StringBuilder}; use crate::assyst::Assyst; +use crate::commit_if_ok; use crate::downloader::{self, ABSOLUTE_INPUT_FILE_SIZE_LIMIT_BYTES}; use crate::gateway_handler::message_parser::error::{ErrorSeverity, GetErrorSeverity}; @@ -502,21 +503,12 @@ impl ParseArgument for ImageUrl { }; } - handle!( - ctxt.commit_if_ok(async |v| ImageUrl::from_mention_raw_message(v).await) - .await - ); - handle!( - ctxt.commit_if_ok(async |v| ImageUrl::from_url_argument_raw_message(v).await) - .await - ); - handle!(ctxt.commit_if_ok(async |v| ImageUrl::from_attachment(v).await).await); - handle!(ctxt.commit_if_ok(async |v| ImageUrl::from_reply(v).await).await); - handle!( - ctxt.commit_if_ok(async |v| ImageUrl::from_emoji_raw_message(v).await) - .await - ); - handle!(ctxt.commit_if_ok(async |v| ImageUrl::from_sticker(v).await).await); + handle!(commit_if_ok!(ctxt, ImageUrl::from_mention_raw_message)); + handle!(commit_if_ok!(ctxt, ImageUrl::from_url_argument_raw_message)); + handle!(commit_if_ok!(ctxt, ImageUrl::from_attachment)); + handle!(commit_if_ok!(ctxt, ImageUrl::from_reply)); + handle!(commit_if_ok!(ctxt, ImageUrl::from_emoji_raw_message)); + handle!(commit_if_ok!(ctxt, ImageUrl::from_sticker)); handle!(ImageUrl::from_channel_history(ctxt.cx.assyst(), ctxt.cx.data.message.channel_id).await); Err(TagParseError::NoImageFound) } @@ -547,18 +539,9 @@ impl ParseArgument for ImageUrl { }; } - handle!( - ctxt.commit_if_ok(async |v| ImageUrl::from_mention_command_option(v).await) - .await - ); - handle!( - ctxt.commit_if_ok(async |v| ImageUrl::from_url_argument_command_option(v).await) - .await - ); - handle!( - ctxt.commit_if_ok(async |v| ImageUrl::from_emoji_command_option(v).await) - .await - ); + handle!(commit_if_ok!(ctxt, ImageUrl::from_mention_command_option)); + handle!(commit_if_ok!(ctxt, ImageUrl::from_url_argument_command_option)); + handle!(commit_if_ok!(ctxt, ImageUrl::from_emoji_command_option)); handle!(ImageUrl::from_channel_history(ctxt.cx.assyst(), ctxt.cx.data.message.channel_id).await); Err(TagParseError::NoImageFound) } diff --git a/assyst-core/src/command/mod.rs b/assyst-core/src/command/mod.rs index 32ad610..0b5e69b 100644 --- a/assyst-core/src/command/mod.rs +++ b/assyst-core/src/command/mod.rs @@ -235,19 +235,27 @@ impl<'a, T: Clone> ParseCtxt<'a, T> { args: self.args.clone(), } } +} - /// Calls the function with a fork of this context (allowing some arbitrary mutations) - /// and only actually applies the changes made to the fork if it returns `Ok`. - pub async fn commit_if_ok(&mut self, f: F) -> Result - where - F: async FnOnce(&mut ParseCtxt<'a, T>) -> Result, - { - let mut fork: ParseCtxt<'a, T> = self.fork(); - let res = f(&mut fork).await?; - *self = fork; - Ok(res) - } +/// Calls the function with a fork of this context (allowing some arbitrary mutations) +/// and only actually applies the changes made to the fork if it returns `Ok`. +/// +/// This used to be a function, however due to compiler bugs and the inability to properly express +/// this pattern with bounds, this was ultimately just made into a macro where no such bounds need +/// to be specified. +#[macro_export] +macro_rules! commit_if_ok { + ($ctxt:expr, $f:expr) => {{ + let ctxt: &mut crate::command::ParseCtxt<'_, _> = $ctxt; + let mut fork = ctxt.fork(); + let res = ($f)(&mut fork).await; + if res.is_ok() { + *ctxt = fork; + } + res + }}; } + impl<'a> ParseCtxt<'a, RawMessageArgsIter<'a>> { pub fn new(ctxt: CommandCtxt<'a>, args: &'a str) -> Self { Self {