use std::collections::VecDeque;
use proc_macro2::Span;
use syn::{
parse::{Parse, ParseStream},
Ident, LitStr, Token,
};
#[derive(Debug, Clone)]
pub enum Param {
Ident(Ident),
LitStr(LitStr),
}
impl TryFrom<&Param> for Ident {
type Error = syn::Error;
fn try_from(value: &Param) -> Result<Self, Self::Error> {
match value {
Param::Ident(value) => Ok(value.clone()),
Param::LitStr(_) => Err(syn::Error::new(
Span::call_site(),
"expect Ident parameter, found LitStr",
)),
}
}
}
impl TryFrom<&Param> for LitStr {
type Error = syn::Error;
fn try_from(value: &Param) -> Result<Self, Self::Error> {
match value {
Param::LitStr(value) => Ok(value.clone()),
Param::Ident(_) => Err(syn::Error::new(
Span::call_site(),
"expect LitStr parameter, found Ident",
)),
}
}
}
impl Parse for Param {
fn parse(input: ParseStream) -> syn::Result<Self> {
input.parse::<Ident>().map_or_else(
|_e| input.parse::<LitStr>().map(|value| Self::LitStr(value)),
|value| Ok(Self::Ident(value)),
)
}
}
#[derive(Debug, Clone)]
pub struct KeyParam {
pub key: Ident,
pub param: Param,
}
impl Parse for KeyParam {
fn parse(input: ParseStream) -> syn::Result<Self> {
let key: Ident = input.parse()?;
let _ = input.parse::<Token!(=)>()?;
let param: Param = input.parse()?;
Ok(Self { key, param })
}
}
#[derive(Debug, Clone)]
pub struct KeyParams(VecDeque<KeyParam>);
impl Iterator for KeyParams {
type Item = KeyParam;
fn next(&mut self) -> Option<Self::Item> {
self.0.pop_front()
}
}
impl Parse for KeyParams {
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(Self(
input
.parse_terminated(KeyParam::parse, Token!(,))?
.into_iter()
.collect(),
))
}
}