use syn::{
parenthesized,
parse::{Parse, ParseStream},
punctuated::Punctuated,
Expr, Ident, Path, Result, Token,
};
use crate::errors::{duplicate_arg_error, unknown_arg_error};
const KEY_GEN_CALLER: &str = "gen_caller";
const KEY_NAMESPACE: &str = "namespace";
#[derive(Debug, Default)]
pub struct DefInterfaceArgs {
pub gen_caller: bool,
pub namespace: Option<String>,
}
impl Parse for DefInterfaceArgs {
fn parse(input: ParseStream) -> Result<Self> {
let mut arg = DefInterfaceArgs::default();
while !input.is_empty() {
let ident: Ident = input.parse()?;
match ident.to_string().as_str() {
KEY_GEN_CALLER => {
if arg.gen_caller {
return Err(duplicate_arg_error(&ident));
}
arg.gen_caller = true;
}
KEY_NAMESPACE => {
if arg.namespace.is_some() {
return Err(duplicate_arg_error(&ident));
}
input.parse::<Token![=]>()?;
let ns_ident: Ident = input.parse()?;
arg.namespace = Some(ns_ident.to_string());
}
_ => {
return Err(unknown_arg_error(&ident));
}
}
if !input.is_empty() {
input.parse::<Token![,]>()?;
}
}
Ok(arg)
}
}
#[derive(Debug, Default)]
pub struct ImplInterfaceArgs {
pub namespace: Option<String>,
}
impl Parse for ImplInterfaceArgs {
fn parse(input: ParseStream) -> Result<Self> {
let mut arg = ImplInterfaceArgs::default();
while !input.is_empty() {
let ident: Ident = input.parse()?;
match ident.to_string().as_str() {
KEY_NAMESPACE => {
if arg.namespace.is_some() {
return Err(duplicate_arg_error(&ident));
}
input.parse::<Token![=]>()?;
let ns_ident: Ident = input.parse()?;
arg.namespace = Some(ns_ident.to_string());
}
_ => {
return Err(unknown_arg_error(&ident));
}
}
if !input.is_empty() {
input.parse::<Token![,]>()?;
}
}
Ok(arg)
}
}
pub struct CallInterface {
pub namespace: Option<String>,
pub path: Path,
pub args: Punctuated<Expr, Token![,]>,
}
impl Parse for CallInterface {
fn parse(input: ParseStream) -> Result<Self> {
let mut namespace = None;
let content;
let mut path: Path = input.parse()?;
if let Some(ident) = path.get_ident() {
if ident == KEY_NAMESPACE {
input.parse::<Token![=]>()?;
let ns_ident: Ident = input.parse()?;
namespace = Some(ns_ident.to_string());
input.parse::<Token![,]>()?;
path = input.parse()?;
}
}
let args = if input.peek(Token![,]) {
input.parse::<Token![,]>()?;
input.parse_terminated(Expr::parse, Token![,])?
} else if !input.is_empty() {
parenthesized!(content in input);
content.parse_terminated(Expr::parse, Token![,])?
} else {
Punctuated::new()
};
Ok(CallInterface {
namespace,
path,
args,
})
}
}