added impl_try_from function

This commit is contained in:
p0lunin 2020-02-24 17:37:17 +02:00
parent 5abaeb2c00
commit c238906b69
2 changed files with 32 additions and 10 deletions

View file

@ -2,6 +2,7 @@ use crate::{
attr::{Attr, BotCommandAttribute}, attr::{Attr, BotCommandAttribute},
rename_rules::rename_by_rule, rename_rules::rename_by_rule,
}; };
use crate::enum_attributes::CommandEnum;
pub struct Command { pub struct Command {
pub prefix: Option<String>, pub prefix: Option<String>,
@ -30,6 +31,17 @@ impl Command {
renamed, 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 {
"/"
};
String::from(prefix) + &self.name
}
} }
struct CommandAttrs { struct CommandAttrs {

View file

@ -13,7 +13,7 @@ use crate::{
}; };
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::{quote, ToTokens}; use quote::{quote, ToTokens};
use syn::{parse_macro_input, DeriveInput}; use syn::{parse_macro_input, DeriveInput, Variant};
macro_rules! get_or_return { macro_rules! get_or_return {
($($some:tt)*) => { ($($some:tt)*) => {
@ -58,7 +58,6 @@ pub fn derive_telegram_command_enum(tokens: TokenStream) -> TokenStream {
} }
} }
let variant_ident = variants.iter().map(|variant| &variant.ident);
let variant_name = variant_infos.iter().map(|info| { let variant_name = variant_infos.iter().map(|info| {
if info.renamed { if info.renamed {
info.name.clone() info.name.clone()
@ -96,16 +95,11 @@ pub fn derive_telegram_command_enum(tokens: TokenStream) -> TokenStream {
quote! {} quote! {}
}; };
let fn_try_from = impl_try_parse_command(&variants, &variant_infos, &command_enum);
let expanded = quote! { let expanded = quote! {
impl BotCommand for #ident { impl BotCommand for #ident {
fn try_from(value: &str) -> Option<Self> { #fn_try_from
match value {
#(
#variant_str1 => Some(Self::#variant_ident),
)*
_ => None
}
}
fn descriptions() -> String { fn descriptions() -> String {
std::concat!(#global_description #(#variant_str2, #variant_description, '\n'),*).to_string() std::concat!(#global_description #(#variant_str2, #variant_description, '\n'),*).to_string()
} }
@ -133,6 +127,22 @@ pub fn derive_telegram_command_enum(tokens: TokenStream) -> TokenStream {
TokenStream::from(expanded) TokenStream::from(expanded)
} }
fn impl_try_parse_command(variants: &[&Variant], infos: &[Command], global: &CommandEnum) -> impl ToTokens {
let matching_values = infos.iter().map(|c| c.get_matched_value(global));
let variant_ident = variants.iter().map(|variant| &variant.ident);
quote! {
fn try_from(value: &str) -> Option<Self> {
match value {
#(
#matching_values => Some(Self::#variant_ident),
)*
_ => None
}
}
}
}
fn get_enum_data(input: &DeriveInput) -> Result<&syn::DataEnum, TokenStream> { fn get_enum_data(input: &DeriveInput) -> Result<&syn::DataEnum, TokenStream> {
match &input.data { match &input.data {
syn::Data::Enum(data) => Ok(data), syn::Data::Enum(data) => Ok(data),