#![warn(
absolute_paths_not_starting_with_crate,
anonymous_parameters,
bare_trait_objects,
box_pointers,
deprecated_in_future,
elided_lifetimes_in_paths,
ellipsis_inclusive_range_patterns,
explicit_outlives_requirements,
keyword_idents,
macro_use_extern_crate,
missing_copy_implementations,
missing_debug_implementations,
missing_docs,
missing_doc_code_examples,
private_doc_tests,
question_mark_macro_sep,
trivial_casts,
trivial_numeric_casts,
unreachable_pub,
unsafe_code,
unstable_features,
unused_extern_crates,
unused_import_braces,
unused_labels,
unused_lifetimes,
unused_qualifications,
unused_results,
clippy::cargo,
clippy::nursery,
clippy::pedantic,
clippy::restriction
)]
#![allow(
clippy::suspicious_op_assign_impl,
clippy::suspicious_arithmetic_impl,
clippy::fallible_impl_from, // Above lints are not always correct; issues should be detected by tests or other lints.
clippy::implicit_return, // Omitting the return keyword is idiomatic Rust code.
clippy::missing_inline_in_public_items, // Generally not bad and there are issues with derived traits.
)]
#![no_std]
#![recursion_limit = "256"]
extern crate proc_macro;
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{parse_macro_input, DeriveInput, Ident};
#[proc_macro_derive(ComponentOps)]
pub fn derive_component_ops(item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as DeriveInput);
let name = &input.ident;
let element_ops = element_ops(name);
TokenStream::from(quote! {
#element_ops
impl<Rhs: Element> ::core::ops::BitOr<Rhs> for #name {
type Output = Rec;
fn bitor(self, rhs: Rhs) -> Self::Output {
self.alternate(&rhs)
}
}
impl ::core::ops::BitOr<#name> for char {
type Output = Rec;
fn bitor(self, rhs: #name) -> Self::Output {
self.alternate(&rhs)
}
}
})
}
#[proc_macro_derive(AtomOps)]
pub fn derive_atom_ops(item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as DeriveInput);
let name = &input.ident;
let element_ops = element_ops(name);
TokenStream::from(quote! {
#element_ops
impl<Rhs: Atom> ::core::ops::BitOr<Rhs> for #name {
type Output = Ch;
fn bitor(self, rhs: Rhs) -> Self::Output {
self.union(&rhs)
}
}
impl ::core::ops::BitOr<Rec> for #name {
type Output = Rec;
fn bitor(self, rhs: Rec) -> Self::Output {
self.alternate(&rhs)
}
}
impl ::core::ops::BitOr<&str> for #name {
type Output = Rec;
fn bitor(self, rhs: &str) -> Self::Output {
self.alternate(&rhs)
}
}
impl ::core::ops::BitOr<String> for #name {
type Output = Rec;
fn bitor(self, rhs: String) -> Self::Output {
self.alternate(&rhs)
}
}
impl ::core::ops::BitOr<#name> for char {
type Output = Ch;
fn bitor(self, rhs: #name) -> Self::Output {
self.union(&rhs)
}
}
})
}
fn element_ops(name: &Ident) -> TokenStream2 {
quote! {
impl<Rhs: Element> ::core::ops::Add<Rhs> for #name {
type Output = Rec;
fn add(self, rhs: Rhs) -> Self::Output {
self.concatenate(&rhs)
}
}
impl<Rhs: Element> PartialEq<Rhs> for #name {
fn eq(&self, other: &Rhs) -> bool {
self.is_equal(other)
}
}
impl ::core::ops::Add<#name> for char {
type Output = Rec;
fn add(self, rhs: #name) -> Self::Output {
self.concatenate(&rhs)
}
}
impl PartialEq<#name> for char {
fn eq(&self, other: &#name) -> bool {
self.is_equal(other)
}
}
impl ::core::ops::Add<#name> for &str {
type Output = Rec;
fn add(self, rhs: #name) -> Self::Output {
self.concatenate(&rhs)
}
}
impl ::core::ops::BitOr<#name> for &str {
type Output = Rec;
fn bitor(self, rhs: #name) -> Self::Output {
self.alternate(&rhs)
}
}
impl PartialEq<#name> for &str {
fn eq(&self, other: &#name) -> bool {
self.is_equal(other)
}
}
impl ::core::ops::Add<#name> for String {
type Output = Rec;
fn add(self, rhs: #name) -> Self::Output {
self.concatenate(&rhs)
}
}
impl ::core::ops::BitOr<#name> for String {
type Output = Rec;
fn bitor(self, rhs: #name) -> Self::Output {
self.alternate(&rhs)
}
}
impl PartialEq<#name> for String {
fn eq(&self, other: &#name) -> bool {
self.is_equal(other)
}
}
}
}