use darling::FromMeta;
use syn::{
braced, parenthesized,
parse::{Parse, ParseStream},
token, Attribute, Block, FnArg, Generics, Ident, Path, Receiver, Token, Type,
};
#[derive(Clone, Copy, Default, FromMeta, Debug)]
#[darling(default)]
pub struct BinOpArgs {
pub dev_print: bool,
pub commute: bool,
pub refs_clone: bool,
pub derefs: bool,
}
#[derive(Clone, Debug)]
pub struct BinOpOutput {
pub type_token: Token![type],
pub ident: Ident,
pub eq_token: Token![=],
pub ty: Type,
pub semi_token: Token![;],
}
#[derive(Clone, Debug)]
pub struct BinOpFn {
pub attrs: Vec<Attribute>,
pub fn_token: Token![fn],
pub ident: Ident,
pub paren_token: token::Paren,
pub lhs_arg: Receiver,
pub comma_token: Token![,],
pub rhs_arg: FnArg,
pub arrow_token: Token![->],
pub out_ty: Type,
pub block: Block,
}
#[derive(Clone, Debug)]
pub struct BinOpImpl {
pub attrs: Vec<Attribute>,
pub impl_token: Token![impl],
pub generics: Generics,
pub trait_: Path, pub lt_token: Option<Token![<]>,
pub rhs_ty: Type,
pub for_token: Token![for],
pub lhs_ty: Type,
pub brace_token: token::Brace,
pub item_out: BinOpOutput,
pub item_fn: BinOpFn,
}
impl Parse for BinOpOutput {
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(BinOpOutput {
type_token: input.parse()?,
ident: input.parse()?,
eq_token: input.parse()?,
ty: input.parse()?,
semi_token: input.parse()?,
})
}
}
impl Parse for BinOpFn {
fn parse(input: ParseStream) -> syn::Result<Self> {
let content;
Ok(BinOpFn {
attrs: input.call(Attribute::parse_outer)?,
fn_token: input.parse()?,
ident: input.parse()?,
paren_token: parenthesized!(content in input),
lhs_arg: content.parse()?,
comma_token: content.parse()?,
rhs_arg: content.parse()?,
arrow_token: input.parse()?,
out_ty: input.parse()?,
block: input.parse()?,
})
}
}
impl Parse for BinOpImpl {
fn parse(input: ParseStream) -> syn::Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let impl_token = input.parse()?;
let mut generics: Generics = input.parse()?;
let trait_ = input.call(Path::parse_mod_style)?;
let mut lt_token = None;
if input.peek(Token![<]) {
if input.peek2(Token![>]) {
let _: Token![<] = input.parse()?;
let _: Token![>] = input.parse()?;
} else {
lt_token = Some(input.parse()?);
}
}
let rhs_ty;
let for_token;
let lhs_ty: Type;
if lt_token.is_some() {
rhs_ty = input.parse()?;
let _: Token![>] = input.parse()?;
for_token = input.parse()?;
lhs_ty = input.parse()?;
} else {
for_token = input.parse()?;
lhs_ty = input.parse()?;
rhs_ty = lhs_ty.clone();
}
generics.where_clause = input.parse()?;
let content;
let brace_token = braced!(content in input);
let item_out = content.parse()?;
let item_fn = content.parse()?;
Ok(BinOpImpl {
attrs,
impl_token,
generics,
trait_,
lt_token,
rhs_ty,
for_token,
lhs_ty,
brace_token,
item_out,
item_fn,
})
}
}