summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib.rs82
-rw-r--r--varihappy-macros/src/lib.rs23
2 files changed, 60 insertions, 45 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 6d93428..b7b58ba 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,8 +1,11 @@
use varihappy_macros::{
- repeat, tuple_expr_reverse, tuple_new, tuple_reverse, tuple_trait_def, type_to_field_access,
+ repeat, tuple_expr_reverse, tuple_len, tuple_new, tuple_reverse, tuple_trait_def,
+ type_to_field_access,
};
pub trait Tuple {
+ const LEN: usize;
+
type AsRef<'a>: Tuple
where
Self: 'a;
@@ -26,6 +29,15 @@ pub trait Tuple1: Tuple {
fn into_rest(self) -> Self::Rest;
}
+pub trait ArrayTupleOrEmpty<T>: Tuple {}
+
+pub trait ArrayTuple: Tuple {
+ type Item;
+}
+
+impl<T> ArrayTupleOrEmpty<T> for () {}
+impl<I, T: ArrayTuple<Item = I>> ArrayTupleOrEmpty<T> for T {}
+
impl Tuple for () {
type AsRef<'a>
= ()
@@ -38,49 +50,13 @@ impl Tuple for () {
type Reversed = ();
+ const LEN: usize = 0;
+
fn as_ref(&self) -> Self::AsRef<'_> {}
fn as_mut(&mut self) -> Self::AsMut<'_> {}
fn rev(self) -> Self::Reversed {}
}
-impl<A> Tuple for (A,) {
- type AsRef<'a>
- = (&'a A,)
- where
- Self: 'a;
- type AsMut<'a>
- = (&'a mut A,)
- where
- Self: 'a;
- type Reversed = (A,);
-
- fn as_ref(&self) -> Self::AsRef<'_> {
- (&self.0,)
- }
-
- fn as_mut(&mut self) -> Self::AsMut<'_> {
- (&mut self.0,)
- }
-
- fn rev(self) -> Self::Reversed {
- (self.0,)
- }
-}
-
-impl<A> Tuple1 for (A,) {
- type Item0 = A;
- type Rest = ();
-
- fn into_0(self) -> Self::Item0 {
- self.0
- }
- fn split_into(self) -> (Self::Item0, Self::Rest) {
- (self.0, ())
- }
-
- fn into_rest(self) -> Self::Rest {}
-}
-
macro_rules! tuple_apply {
(($($letter: ident,)*), $other: ident) => {
$other!(($($letter,)*))
@@ -119,6 +95,7 @@ macro_rules! tuple_expr_mut {
macro_rules! tuple_expr_rest {
($this: ident, (A, $($letter: ident,)*)) => {
+ #[allow(unused_variables, clippy::unused_unit)]
{
let this = $this;
($(type_to_field_access!($letter),)*)
@@ -138,6 +115,8 @@ macro_rules! tuple_expr_split {
macro_rules! impl_tuple_inner {
(($($letter: ident,)*)) => {
impl<$($letter),*> Tuple for ($($letter,)*) {
+ const LEN: usize = tuple_len!(($($letter,)*));
+
type AsRef<'a> = ($(&'a $letter,)*) where Self: 'a;
type AsMut<'a> = ($(&'a mut $letter,)*) where Self: 'a;
type Reversed = tuple_apply!(($($letter,)*), tuple_reverse);
@@ -213,5 +192,26 @@ macro_rules! tuple_trait {
};
}
-repeat!(64, impl_tuple);
-repeat!(64, tuple_trait);
+macro_rules! t {
+ ($_t:tt) => {
+ T
+ };
+}
+
+macro_rules! impl_array_tuple_inner {
+ (($($letter: ident,)*)) => {
+ impl<T> ArrayTuple for ($(t!($letter),)*) {
+ type Item = T;
+ }
+ };
+}
+
+macro_rules! impl_array_tuple {
+ ($number: literal) => {
+ tuple_new! { $number, impl_array_tuple_inner }
+ };
+}
+
+repeat!(1..64, impl_tuple);
+repeat!(2..64, tuple_trait);
+repeat!(1..64, impl_array_tuple);
diff --git a/varihappy-macros/src/lib.rs b/varihappy-macros/src/lib.rs
index 3931899..3b1cc29 100644
--- a/varihappy-macros/src/lib.rs
+++ b/varihappy-macros/src/lib.rs
@@ -1,11 +1,11 @@
extern crate proc_macro;
use proc_macro::TokenStream;
-use proc_macro2::{Ident, Literal, Span};
+use proc_macro2::{Ident, Literal};
use quote::{format_ident, quote};
-use syn::LitInt;
use unsynn::{
Comma, CommaDelimitedVec, Cons, Either, GroupContaining, IParse, LiteralInteger, TokenIter,
+ unsynn,
};
fn number_to_type(mut number: u128) -> String {
@@ -169,11 +169,19 @@ pub fn type_to_field_access(input: TokenStream) -> TokenStream {
#[proc_macro]
pub fn repeat(input: TokenStream) -> TokenStream {
+ unsynn! {
+ struct RangeLiteral {
+ start: LiteralInteger,
+ dotdot: unsynn::DotDot,
+ end: LiteralInteger,
+ }
+ }
+
let input: proc_macro2::TokenStream = input.into();
let mut token_iter = TokenIter::new(input);
- let ast: Cons<LiteralInteger, Comma, unsynn::Ident> = token_iter.parse().unwrap();
+ let ast: Cons<RangeLiteral, Comma, unsynn::Ident> = token_iter.parse().unwrap();
- let numbers = (2..=ast.first.value()).map(Literal::u128_unsuffixed);
+ let numbers = (ast.first.start.value()..ast.first.end.value()).map(Literal::u128_unsuffixed);
let macro_name = ast.third;
quote! { #(#macro_name!(#numbers);)* }.into()
}
@@ -197,3 +205,10 @@ pub fn tuple_trait_def(input: TokenStream) -> TokenStream {
quote! { #ident! { trait #trait_name for #other_trait { type #item_type; fn #item_fn; }} }
.into()
}
+
+#[proc_macro]
+pub fn tuple_len(input: TokenStream) -> TokenStream {
+ let tuple = syn::parse_macro_input!(input as syn::TypeTuple);
+ let len = Literal::usize_unsuffixed(tuple.elems.len());
+ quote! { #len }.into()
+}