summaryrefslogtreecommitdiff
path: root/varihappy-macros/src/lib.rs
blob: 522d333866bc86f880d16e1de9b02de2bbf152c5 (plain)
extern crate proc_macro;

use proc_macro::TokenStream;
use proc_macro2::{Ident, Literal, Span};
use quote::quote;
use syn::{Field, LitInt};

#[proc_macro]
pub fn concat_idents(input: TokenStream) -> TokenStream {
	let mut buffer = String::new();
	for token in input {
		buffer.push_str(&token.to_string());
	}

	let mut stream = proc_macro2::TokenStream::new();
	stream.extend([Ident::new(&buffer, Span::call_site())]);
	stream.into()
}

#[proc_macro]
pub fn number_to_generic(input: TokenStream) -> TokenStream {
	let number = syn::parse_macro_input!(input as LitInt);
	let number: u128 = number.base10_parse().expect("a number 0..=u128::MAX");

	let identifier = Ident::new(
		match number {
			0 => "A",
			1 => "B",
			2 => "C",
			3 => "D",
			4 => "E",
			5 => "F",
			6 => "G",
			7 => "H",
			8 => "I",
			9 => "J",
			10 => "K",
			11 => "L",
			12 => "M",
			13 => "N",
			14 => "O",
			15 => "P",
			16 => "Q",
			17 => "R",
			18 => "S",
			19 => "T",
			20 => "U",
			21 => "V",
			22 => "W",
			23 => "X",
			24 => "Y",
			25 => "Z",
			_ => panic!("Expected a number less than 26"),
		},
		Span::call_site(),
	);

	quote! { #identifier }.into()
}

#[proc_macro]
pub fn tuple_type_len(input: TokenStream) -> TokenStream {
	let number = syn::parse_macro_input!(input as LitInt);
	let number: u128 = number.base10_parse().expect("a number 0..=u128::MAX");

	let num = 0..number;
	quote! { (#(::varihappy_macros::number_to_generic!(#num),)*) }.into()
}

#[proc_macro]
pub fn tuple_type_ref(input: TokenStream) -> TokenStream {
	let number = syn::parse_macro_input!(input as LitInt);
	let number: u128 = number.base10_parse().expect("a number 0..=u128::MAX");

	let num = 0..number;
	quote! { (#(&'a ::varihappy_macros::number_to_generic!(#num),)*) }.into()
}

#[proc_macro]
pub fn tuple_type_mut(input: TokenStream) -> TokenStream {
	let number = syn::parse_macro_input!(input as LitInt);
	let number: u128 = number.base10_parse().expect("a number 0..=u128::MAX");

	let num = 0..number;
	quote! { (#(&'a mut ::varihappy_macros::number_to_generic!(#num),)*) }.into()
}

#[proc_macro]
pub fn reverse_tuple_type(input: TokenStream) -> TokenStream {
	let number = syn::parse_macro_input!(input as LitInt);
	let number: u128 = number.base10_parse().expect("a number 0..=u128::MAX");

	let num = (0..number).rev();
	quote! { (#(::varihappy_macros::number_to_generic!(#num),)*) }.into()
}

#[proc_macro]
pub fn tuple_type_len_rest(input: TokenStream) -> TokenStream {
	let number = syn::parse_macro_input!(input as LitInt);
	let number: u128 = number.base10_parse().expect("a number 0..=u128::MAX");

	let num = 1..number;
	quote! { (#(::varihappy_macros::number_to_generic!(#num),)*) }.into()
}

#[proc_macro]
pub fn tuple_expr_ref(input: TokenStream) -> TokenStream {
	let number = syn::parse_macro_input!(input as LitInt);
	let number: u128 = number.base10_parse().expect("a number 0..=u128::MAX");

	let num = (0..number).map(Literal::u128_unsuffixed);
	quote! { (#(&self.#num,)*) }.into()
}

#[proc_macro]
pub fn tuple_expr_mut(input: TokenStream) -> TokenStream {
	let number = syn::parse_macro_input!(input as LitInt);
	let number: u128 = number.base10_parse().expect("a number 0..=u128::MAX");

	let num = (0..number).map(Literal::u128_unsuffixed);
	quote! { (#(&mut self.#num,)*) }.into()
}

#[proc_macro]
pub fn reverse_expr_type(input: TokenStream) -> TokenStream {
	let number = syn::parse_macro_input!(input as LitInt);
	let number: u128 = number.base10_parse().expect("a number 0..=u128::MAX");

	let num = (0..number).rev().map(Literal::u128_unsuffixed);
	quote! { (#(self.#num,)*) }.into()
}

#[proc_macro]
pub fn tuple_expr_len_rest(input: TokenStream) -> TokenStream {
	let number = syn::parse_macro_input!(input as LitInt);
	let number: u128 = number.base10_parse().expect("a number 0..=u128::MAX");

	let num = (1..number).map(Literal::u128_unsuffixed);
	quote! { (#(self.#num,)*) }.into()
}