use crate::fields::FieldParam;
use crate::modifier::Modifier;
use syn::Token;
use syn::parse::discouraged::Speculative;
use syn::parse::{Parse, ParseStream};
use syn::spanned::Spanned;
use syn::{Error, Expr, ExprArray, MetaNameValue, Result};
pub enum AccessorArg {
Includes(Vec<String>),
Excludes(Vec<String>),
Prefix(String),
Pub,
Modifier(Modifier),
Name(String),
FieldParam(FieldParam),
}
impl AccessorArg {
pub fn nv_to_arg(nv: &MetaNameValue) -> Result<Self> {
match nv
.path
.get_ident()
.expect("Wrong name. Expected identifier")
.to_string()
.as_str()
{
"includes" => Ok(AccessorArg::Includes(AccessorArg::brackets_to_vec(
&nv.value,
)?)),
"excludes" => Ok(AccessorArg::Excludes(AccessorArg::brackets_to_vec(
&nv.value,
)?)),
"prefix" => Ok(AccessorArg::Prefix(AccessorArg::ident_to_string(
&nv.value,
)?)),
"name" => Ok(AccessorArg::Name(AccessorArg::ident_to_string(&nv.value)?)),
_ => Result::Err(Error::new(nv.span(), "Unknown arg name")),
}
}
pub fn brackets_to_vec(brackets: &Expr) -> Result<Vec<String>> {
if let Expr::Array(ExprArray { elems, .. }) = brackets {
let res = elems
.iter()
.map(|e| {
if let Expr::Path(path) = e {
path.path
.get_ident()
.expect("Could not parse value")
.to_string()
} else {
"".to_string()
}
})
.collect::<Vec<_>>();
return Result::Ok(res);
};
Err(Error::new(
brackets.span(),
"Wrong expressing. Expected array",
))
}
pub fn ident_to_string(expr: &Expr) -> Result<String> {
if let Expr::Path(path) = expr {
Ok(path.path.get_ident().expect("Expected ident").to_string())
} else {
Err(Error::new(
expr.span(),
"Could not parse arg value. Excpected ident",
))
}
}
}
impl Parse for AccessorArg {
fn parse(input: ParseStream) -> Result<Self> {
let start = input.fork();
if let Ok(modifier) = start.parse::<Modifier>() {
input.advance_to(&start);
return Ok(AccessorArg::Modifier(modifier));
}
let start = input.fork();
if let Ok(_) = start.parse::<Token![pub]>() {
input.advance_to(&start);
return Ok(AccessorArg::Pub);
}
let start = input.fork();
if let Ok(nv) = start.parse::<MetaNameValue>() {
input.advance_to(&start);
return AccessorArg::nv_to_arg(&nv);
}
let start = input.fork();
if let Ok(p) = start.parse::<FieldParam>() {
input.advance_to(&start);
return Ok(AccessorArg::FieldParam(p));
}
let msg = format!(
"Expected one of: Modifier, `pub`, MetaNameValue, FieldParam, but got: {}",
input.to_string()
);
Err(input.error(msg))
}
}