teloxide-macros 0.4.0

The teloxide's procedural macros
Documentation
use crate::{
    attr::{Attr, BotCommandAttribute},
    command_enum::CommandEnum,
    fields_parse::ParserType,
    rename_rules::rename_by_rule,
};

pub struct Command {
    pub prefix: Option<String>,
    pub description: Option<String>,
    pub parser: Option<ParserType>,
    pub name: String,
    pub renamed: bool,
}

impl Command {
    pub fn try_from(attrs: &[Attr], name: &str) -> Result<Self, String> {
        let attrs = parse_attrs(attrs)?;
        let mut new_name = name.to_string();
        let mut renamed = false;

        let prefix = attrs.prefix;
        let description = attrs.description;
        let rename = attrs.rename;
        let parser = attrs.parser;
        if let Some(rename_rule) = rename {
            new_name = rename_by_rule(name, &rename_rule);
            renamed = true;
        }
        Ok(Self { prefix, description, parser, name: new_name, renamed })
    }

    pub fn get_matched_value(&self, global_parameters: &CommandEnum) -> String {
        let prefix = if let Some(prefix) = &self.prefix {
            prefix
        } else if let Some(prefix) = &global_parameters.prefix {
            prefix
        } else {
            "/"
        };
        if let Some(rule) = &global_parameters.rename_rule {
            String::from(prefix) + &rename_by_rule(&self.name, rule.as_str())
        } else {
            String::from(prefix) + &self.name
        }
    }
}

pub struct CommandAttrs {
    pub(crate) prefix: Option<String>,
    pub(crate) description: Option<String>,
    pub(crate) rename: Option<String>,
    pub(crate) parser: Option<ParserType>,
    pub(crate) separator: Option<String>,
}

pub fn parse_attrs(attrs: &[Attr]) -> Result<CommandAttrs, String> {
    let mut prefix = None;
    let mut description = None;
    let mut rename_rule = None;
    let mut parser = None;
    let mut separator = None;

    for attr in attrs {
        match attr.name() {
            BotCommandAttribute::Prefix => prefix = Some(attr.value()),
            BotCommandAttribute::Description => {
                description = Some(attr.value())
            }
            BotCommandAttribute::RenameRule => rename_rule = Some(attr.value()),
            BotCommandAttribute::CustomParser => {
                parser = Some(ParserType::parse(&attr.value()))
            }
            BotCommandAttribute::Separator => separator = Some(attr.value()),
        }
    }

    Ok(CommandAttrs {
        prefix,
        description,
        rename: rename_rule,
        parser,
        separator,
    })
}