#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
extern crate proc_macro;
use proc_macro::TokenStream;
use std::str::FromStr;
use syn::DeriveInput;
#[proc_macro_derive(WithStdError)]
pub fn error_with_std_error(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let expanded = quote! {
impl std::error::Error for #name {}
};
TokenStream::from(expanded)
}
#[proc_macro_derive(IsDefaultCheck)]
pub fn check_is_default(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let expanded = quote! {
impl crate::IsDefault for #name {}
};
TokenStream::from(expanded)
}
#[proc_macro_derive(IntegrityChecks)]
pub fn check_integrity_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let expanded = quote! {
impl crate::CheckFileIntegrity for #name {}
};
TokenStream::from(expanded)
}
#[proc_macro_derive(ArrayDefaults)]
pub fn defaults_as_array_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let expanded = quote! {
impl<const N: usize> Defaults<[Self; N]> for #name {
fn defaults() -> [Self; N] where Self: Default {
from_fn(|_| Self::default())
}
}
};
TokenStream::from(expanded)
}
#[proc_macro_derive(BoxedBigArrayDefaults)]
pub fn defaults_as_array_boxed_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let expanded = quote! {
impl<const N: usize> Defaults<Box<Array<Self, N>>> for #name {
fn defaults() -> Box<Array<Self, N>> where Self: Defaults<[Self; N]> {
Box::new(Array(
<Self as Defaults<[Self; N]>>::defaults()
))
}
}
};
TokenStream::from(expanded)
}
#[proc_macro_attribute]
pub fn enum_try_from_u32_to_unsigned_types(_attr: TokenStream, item: TokenStream) -> TokenStream {
let mut s = item.to_string();
for t in ["&u32", "u16", "&u16", "u8", "&u8"] {
s += &*item.to_string().replace("u32", t);
s += "\n";
}
TokenStream::from_str(&s).unwrap()
}
#[proc_macro_attribute]
pub fn enum_try_from_i32_to_signed_types(_attr: TokenStream, item: TokenStream) -> TokenStream {
let mut s = item.to_string();
for t in ["&i32", "i16", "&i16", "i8", "&i8"] {
s += &*item.to_string().replace("i32", t);
s += "\n";
}
TokenStream::from_str(&s).unwrap()
}
#[proc_macro_derive(IntoUnsigneds)]
pub fn into_enum_unsigned_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let expanded = quote! {
impl Into<u8> for #name { fn into(self) -> u8 { self as u8 } }
impl Into<u16> for #name { fn into(self) -> u16 { self as u16 } }
impl Into<u32> for #name { fn into(self) -> u32 { self as u32 } }
};
TokenStream::from(expanded)
}
#[proc_macro_derive(IntoSigneds)]
pub fn into_enum_signed_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let expanded = quote! {
impl Into<i8> for #name { fn into(self) -> i8 { self as i8 } }
impl Into<i16> for #name { fn into(self) -> i16 { self as i16 } }
impl Into<i32> for #name { fn into(self) -> i32 { self as i32 } }
};
TokenStream::from(expanded)
}
#[proc_macro_derive(AsRefDerive)]
pub fn asref_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let expanded = quote! {
impl AsRef<#name> for #name {
fn as_ref(&self) -> &#name {
self
}
}
};
TokenStream::from(expanded)
}
#[proc_macro_derive(AsMutDerive)]
pub fn asmut_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let expanded = quote! {
impl AsMut<#name> for #name {
fn as_mut(&mut self) -> &mut #name {
self
}
}
};
TokenStream::from(expanded)
}
#[proc_macro_derive(ContainerArrayMethods)]
pub fn container_type_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let non_arr_name = name.to_string().replace("Array", "");
let into_name = name.to_string() + "IntoIter";
let expanded = quote! {
impl std::ops::Index<usize> for #name {
type Output = non_arr_name;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
impl std::ops::IndexMut<usize> for #name {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.0[index]
}
}
impl Default for #name {
fn default() -> Self {
Self(non_arr_name::defaults())
}
}
impl #name {
pub fn iter(&self) -> Iter<'_, non_arr_name> {
self.0.iter()
}
pub fn iter_mut(&mut self) -> IterMut<'_, non_arr_name> {
self.0.iter_mut()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn reversed(&self) -> Self {
let mut x = self.0.clone();
x.reverse();
Self(x)
}
pub fn reverse(&mut self) -> () {
self.0.reverse()
}
}
impl IntoIterator for #name {
type Item = non_arr_name;
#[doc(hidden)]
type IntoIter = into_name;
fn into_iter(self) -> Self::IntoIter {
into_name {
non_arr_name: self,
index: 0
}
}
}
#[doc(hidden)]
pub struct into_name {
non_arr_name: #name,
index: usize,
}
#[doc(hidden)]
impl Iterator for into_name {
type Item = non_arr_name;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.non_arr_name.len() {
Some(self.non_arr_name[self.index].clone())
} else {None}
}
}
};
TokenStream::from_str(
&expanded
.to_string()
.replace("non_arr_name", &non_arr_name)
.replace("into_name", &into_name),
)
.unwrap()
}