vaidcord 0.2.0

High-performance Discord framework: routers, middleware, resilient gateway and full voice transport
Documentation
use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::sync::Arc;

use crate::error::Error;
use crate::models::Message;

#[derive(Clone, Default)]
pub struct ExtractBag {
    by_type: HashMap<TypeId, Arc<dyn Any + Send + Sync>>,
    by_name: HashMap<&'static str, Arc<dyn Any + Send + Sync>>,
}

impl ExtractBag {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn insert<T: Send + Sync + 'static>(&mut self, value: T) {
        self.by_type.insert(TypeId::of::<T>(), Arc::new(value));
    }

    pub fn insert_named<T: Send + Sync + 'static>(&mut self, name: &'static str, value: T) {
        self.by_name.insert(name, Arc::new(value));
    }

    pub fn get<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
        self.by_type
            .get(&TypeId::of::<T>())
            .and_then(|value| Arc::clone(value).downcast::<T>().ok())
    }

    pub fn get_named<T: Send + Sync + 'static>(&self, name: &'static str) -> Option<Arc<T>> {
        self.by_name
            .get(name)
            .and_then(|value| Arc::clone(value).downcast::<T>().ok())
    }

    pub fn merge(&mut self, other: ExtractBag) {
        self.by_type.extend(other.by_type);
        self.by_name.extend(other.by_name);
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Bot {
    pub token: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Command {
    pub name: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Args {
    pub raw: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Content {
    pub raw: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Captures {
    pub values: Vec<String>,
}

pub trait FromHandlerArg<E>: Sized + Send + 'static {
    fn from_handler_arg(bot: &Bot, event: &E, bag: &ExtractBag) -> Result<Self, Error>;
}

impl FromHandlerArg<Message> for Bot {
    fn from_handler_arg(bot: &Bot, _event: &Message, _bag: &ExtractBag) -> Result<Self, Error> {
        Ok(bot.clone())
    }
}

impl FromHandlerArg<Message> for Message {
    fn from_handler_arg(_bot: &Bot, event: &Message, _bag: &ExtractBag) -> Result<Self, Error> {
        Ok(event.clone())
    }
}

impl FromHandlerArg<Message> for Args {
    fn from_handler_arg(_bot: &Bot, _event: &Message, bag: &ExtractBag) -> Result<Self, Error> {
        bag.get::<Args>()
            .map(|value| (*value).clone())
            .ok_or_else(|| Error::MissingExtractor("Args"))
    }
}

impl FromHandlerArg<Message> for Command {
    fn from_handler_arg(_bot: &Bot, _event: &Message, bag: &ExtractBag) -> Result<Self, Error> {
        bag.get::<Command>()
            .map(|value| (*value).clone())
            .ok_or_else(|| Error::MissingExtractor("Command"))
    }
}

impl FromHandlerArg<Message> for Content {
    fn from_handler_arg(_bot: &Bot, event: &Message, _bag: &ExtractBag) -> Result<Self, Error> {
        Ok(Self {
            raw: event.content.clone(),
        })
    }
}

impl<T> FromHandlerArg<Message> for Option<T>
where
    T: FromHandlerArg<Message>,
{
    fn from_handler_arg(bot: &Bot, event: &Message, bag: &ExtractBag) -> Result<Self, Error> {
        Ok(T::from_handler_arg(bot, event, bag).ok())
    }
}