ruma-bot

git clone git://archive.git.mtrnord.blog/MTRNord/ruma-bot.git
Log | Files | Refs

commit c148d48597648bca8b97bc550d55d35a1fb5899e
parent 77bbd2f7ae2f5eda963d5fff76d8eb049ffaae44
Author: Jonas Platte <jplatte+git@posteo.de>
Date:   Sun, 21 Jul 2019 11:58:35 +0200

Add anymap for state handling

Diffstat:
MCargo.toml | 3+++
Mmacro/src/lib.rs | 4++++
Msrc/lib.rs | 36++++++++++++++++++++++++++++++------
Asrc/state.rs | 28++++++++++++++++++++++++++++
Mtests/echo.rs | 2+-
5 files changed, 66 insertions(+), 7 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.0" authors = ["Jonas Platte <jplatte+git@posteo.de>"] edition = "2018" +[dependencies] +anymap = "0.12.1" + [dependencies.ruma-bot-macro] path = "macro" diff --git a/macro/src/lib.rs b/macro/src/lib.rs @@ -31,6 +31,10 @@ pub fn command_handler(args: TokenStream, input: TokenStream) -> TokenStream { fn commands(&self) -> &'static [&'static str] { &[#(#commands),*] } + + fn get_fn(&self) -> Box<dyn ruma_bot::CommandHandlerFn> { + unimplemented!() + } } }) } diff --git a/src/lib.rs b/src/lib.rs @@ -10,17 +10,27 @@ use std::{collections::HashMap, sync::Arc}; +use anymap::any::Any; +type AnyMap = anymap::Map<dyn Any + Send + Sync>; + pub use ruma_bot_macro::command_handler; -/// An `async fn` annotated with `#[ruma_bot::command_handler] +mod state; + +/// A function (usually `async`) annotated with `#[ruma_bot::command_handler] pub trait CommandHandler { /// The command(s) this function handles fn commands(&self) -> &'static [&'static str]; + + fn get_fn(&self) -> Box<dyn CommandHandlerFn>; +} + +pub trait CommandHandlerFn: Send + Sync { + //fn } -#[derive(Clone)] pub struct BotBuilder { - handlers: HashMap<&'static str, &'static dyn CommandHandler>, + handlers: HashMap<&'static str, Box<dyn CommandHandlerFn>>, } impl BotBuilder { @@ -31,9 +41,9 @@ impl BotBuilder { } /// Register a command handler - pub fn register(mut self, handler: &'static dyn CommandHandler) -> Self { + pub fn register(mut self, handler: impl CommandHandler) -> Self { for command in handler.commands() { - let _old_value = self.handlers.insert(command, handler); + let _old_value = self.handlers.insert(command, handler.get_fn()); // TODO: Log a warning if _old_value is Some } @@ -43,12 +53,14 @@ impl BotBuilder { pub fn build(self) -> Bot { Bot { handlers: Arc::new(self.handlers), + state: AnyMap::new(), } } } pub struct Bot { - handlers: Arc<HashMap<&'static str, &'static dyn CommandHandler>>, + handlers: Arc<HashMap<&'static str, Box<dyn CommandHandlerFn>>>, + state: AnyMap, } impl Bot { @@ -56,3 +68,15 @@ impl Bot { Ok(()) } } + +#[allow(dead_code)] +mod compile_tests { + use super::Bot; + + fn send_sync() { + fn assert_send<T: Send>() {} + fn assert_sync<T: Send>() {} + assert_send::<Bot>(); + assert_sync::<Bot>(); + } +} diff --git a/src/state.rs b/src/state.rs @@ -0,0 +1,28 @@ +use std::{ + fmt::{self, Debug}, + ops::Deref, +}; + +struct State<T: Send + Sync> { + inner: T, +} + +impl<T> Debug for State<T> +where + T: Debug + Send + Sync, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.inner) + } +} + +impl<T> Deref for State<T> +where + T: Send + Sync, +{ + type Target = T; + + fn deref(&self) -> &T { + &self.inner + } +} diff --git a/tests/echo.rs b/tests/echo.rs @@ -7,5 +7,5 @@ async fn help() {} #[tokio::main] async fn main() { - let bot = BotBuilder::new().register(&help).build(); + let bot = BotBuilder::new().register(help).build(); }