use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::{Error, Lit, Path, Result};
use super::attribute::{ParseAttribute, ParseSpanned};
#[derive(Clone)]
pub struct FunctionPath(Path);
impl ParseAttribute for FunctionPath {
fn parse_attribute(input: Lit) -> Result<Self> {
let Lit::Str(lit) = input else {
return Err(Error::new_spanned(input, "expected string literal"));
};
let path = lit.parse_with(Path::parse_mod_style)?;
Ok(Self(path))
}
}
impl ToTokens for FunctionPath {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens)
}
}
#[derive(Clone, Debug)]
pub struct CommandName(String);
impl ParseAttribute for CommandName {
fn parse_attribute(input: Lit) -> Result<Self> {
let spanned: ParseSpanned<String> = ParseAttribute::parse_attribute(input)?;
let value = spanned.inner.trim();
match value.chars().count() {
1..=32 => (),
_ => return Err(spanned.error("name must be between 1 and 32 characters")),
}
for char in value.chars() {
if !char.is_alphanumeric() && char != '-' && char != '_' {
return Err(spanned.error(format!(
"name must only contain word characters, found invalid character `{char}`"
)));
}
if char.to_lowercase().to_string() != char.to_string() {
return Err(spanned.error(format!(
"name must be in lowercase, found invalid character `{char}`"
)));
}
}
Ok(Self(value.to_owned()))
}
}
impl ToTokens for CommandName {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens)
}
}
impl From<CommandName> for String {
fn from(value: CommandName) -> Self {
value.0
}
}
#[derive(Clone, Debug)]
pub struct CommandDescription(String);
impl ParseAttribute for CommandDescription {
fn parse_attribute(input: Lit) -> Result<Self> {
let spanned: ParseSpanned<String> = ParseAttribute::parse_attribute(input)?;
let value = spanned.inner.trim();
match value.chars().count() {
1..=100 => (),
_ => return Err(spanned.error("description must be between 1 and 100 characters")),
}
Ok(Self(value.to_owned()))
}
}
impl ToTokens for CommandDescription {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens)
}
}
impl From<CommandDescription> for String {
fn from(value: CommandDescription) -> Self {
value.0
}
}
#[derive(Clone, Debug)]
pub struct ChoiceName(String);
impl ParseAttribute for ChoiceName {
fn parse_attribute(input: Lit) -> Result<Self> {
let spanned: ParseSpanned<String> = ParseAttribute::parse_attribute(input)?;
let value = spanned.inner.trim();
match value.chars().count() {
1..=100 => (),
_ => return Err(spanned.error("name must be between 1 and 100 characters")),
}
Ok(Self(value.to_owned()))
}
}
impl ToTokens for ChoiceName {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens);
}
}
impl From<ChoiceName> for String {
fn from(value: ChoiceName) -> Self {
value.0
}
}