#![doc = include_str!("../README.md")]
#![allow(clippy::needless_return)]
#![warn(clippy::cast_sign_loss)]
#![warn(clippy::cast_possible_truncation)]
#![warn(clippy::cast_possible_wrap)]
#![warn(clippy::clone_on_ref_ptr)]
#![warn(clippy::cognitive_complexity)]
#![warn(clippy::default_numeric_fallback)]
#![warn(clippy::float_cmp_const)]
#![warn(clippy::implicit_hasher)]
#![warn(clippy::implicit_saturating_sub)]
#![warn(clippy::imprecise_flops)]
#![warn(clippy::large_types_passed_by_value)]
#![warn(clippy::macro_use_imports)]
#![warn(clippy::manual_ok_or)]
#![warn(clippy::missing_const_for_fn)]
#![warn(clippy::needless_pass_by_value)]
#![warn(clippy::non_ascii_literal)]
#![warn(clippy::semicolon_if_nothing_returned)]
#![warn(clippy::suboptimal_flops)]
#![warn(clippy::todo)]
#![warn(clippy::trivially_copy_pass_by_ref)]
#![warn(clippy::type_repetition_in_bounds)]
#![warn(clippy::unreadable_literal)]
#![warn(clippy::unseparated_literal_suffix)]
#![warn(clippy::unused_self)]
#![warn(clippy::unnecessary_wraps)]
#![warn(clippy::missing_errors_doc)]
#![warn(missing_docs)]
#![forbid(unsafe_code)]
#![doc(html_root_url = "https://docs.rs/lattice_qcd_rs-procedural_macro/0.2.1")]
#[cfg(test)]
mod test;
use proc_macro::TokenStream;
use quote::quote;
const MAX_DIM: usize = 127;
#[proc_macro]
pub fn implement_direction_list(_item: TokenStream) -> TokenStream {
let mut implem = Vec::with_capacity(MAX_DIM);
for i in 1_usize..=MAX_DIM {
let mut array_direction = Vec::with_capacity(MAX_DIM);
let mut array_direction_positives = Vec::with_capacity(MAX_DIM);
for j in 0..i {
array_direction.push(quote! {
Direction{index_dir: #j, is_positive: true},
Direction{index_dir: #j, is_positive: false}
});
array_direction_positives.push(quote! {
Direction{index_dir: #j, is_positive: true}
});
}
let u_dir_ident = syn::Ident::new(&format!("U{}_DIR", i), proc_macro2::Span::call_site());
let u_dir_pos_ident =
syn::Ident::new(&format!("U{}_DIR_POS", i), proc_macro2::Span::call_site());
let s = quote! {
const #u_dir_ident: [Direction<#i>; #i * 2] = [ #(#array_direction),* ];
const #u_dir_pos_ident: [Direction<#i>; #i] = [ #(#array_direction_positives),* ];
impl DirectionList for Direction<#i> {
#[inline]
fn directions() -> & 'static [Self] {
&#u_dir_ident
}
#[inline]
fn positive_directions() -> & 'static [Self] {
&#u_dir_pos_ident
}
}
};
implem.push(s);
}
let final_stream = quote! {
#(#implem)*
};
final_stream.into()
}
const MAX_DIM_FROM_IMPLEM: usize = 10;
#[proc_macro]
pub fn implement_direction_from(_item: TokenStream) -> TokenStream {
let mut implem = vec![quote! {
use std::convert::TryFrom;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[non_exhaustive]
pub enum DirectionConversionError {
IndexOutOfBound,
}
impl std::fmt::Display for DirectionConversionError{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::IndexOutOfBound => write!(f, "the index is out of bound, the direction axis does not exist in the lower space dimension"),
}
}
}
impl std::error::Error for DirectionConversionError {}
}];
for i in 1_usize..MAX_DIM_FROM_IMPLEM {
for j in i + 1..=MAX_DIM_FROM_IMPLEM {
implem.push(quote! {
impl From<Direction<#i>> for Direction<#j> {
fn from(from: Direction<#i>) -> Self {
Self::new(from.index(), from.is_positive()).unwrap()
}
}
impl From<&Direction<#i>> for Direction<#j> {
fn from(from: &Direction<#i>) -> Self {
Self::new(from.index(), from.is_positive()).unwrap()
}
}
impl TryFrom<Direction<#j>> for Direction<#i> {
type Error = DirectionConversionError;
fn try_from(from: Direction<#j>) -> Result<Self, Self::Error> {
Self::new(from.index(), from.is_positive())
.ok_or(DirectionConversionError::IndexOutOfBound)
}
}
impl TryFrom<&Direction<#j>> for Direction<#i> {
type Error = DirectionConversionError;
fn try_from(from: &Direction<#j>) -> Result<Self, Self::Error> {
Self::new(from.index(), from.is_positive())
.ok_or(DirectionConversionError::IndexOutOfBound)
}
}
});
}
}
let final_stream = quote! {
#(#implem)*
};
final_stream.into()
}