summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib.rs50
-rw-r--r--varihappy-macros/src/lib.rs24
2 files changed, 65 insertions, 9 deletions
diff --git a/src/lib.rs b/src/lib.rs
index b7b58ba..4ef5359 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,6 +3,8 @@ use varihappy_macros::{
type_to_field_access,
};
+pub use varihappy_macros::array_tuple;
+
pub trait Tuple {
const LEN: usize;
@@ -29,14 +31,21 @@ pub trait Tuple1: Tuple {
fn into_rest(self) -> Self::Rest;
}
-pub trait ArrayTupleOrEmpty<T>: Tuple {}
+pub trait ArrayTuple<T>: Tuple {
+ fn fill(item: T) -> Self
+ where
+ Self: Sized,
+ T: Copy;
+}
-pub trait ArrayTuple: Tuple {
+pub trait NonEmptyArrayTuple: Tuple {
type Item;
-}
-impl<T> ArrayTupleOrEmpty<T> for () {}
-impl<I, T: ArrayTuple<Item = I>> ArrayTupleOrEmpty<T> for T {}
+ fn fill(item: Self::Item) -> Self
+ where
+ Self: Sized,
+ Self::Item: Copy;
+}
impl Tuple for () {
type AsRef<'a>
@@ -57,6 +66,25 @@ impl Tuple for () {
fn rev(self) -> Self::Reversed {}
}
+impl<T> ArrayTuple<T> for () {
+ fn fill(_item: T) -> Self
+ where
+ Self: Sized,
+ T: Copy,
+ {
+ }
+}
+
+impl<I, T: NonEmptyArrayTuple<Item = I>> ArrayTuple<I> for T {
+ fn fill(item: I) -> Self
+ where
+ Self: Sized,
+ I: Copy,
+ {
+ <Self as NonEmptyArrayTuple>::fill(item)
+ }
+}
+
macro_rules! tuple_apply {
(($($letter: ident,)*), $other: ident) => {
$other!(($($letter,)*))
@@ -192,16 +220,20 @@ macro_rules! tuple_trait {
};
}
-macro_rules! t {
- ($_t:tt) => {
- T
+macro_rules! replace {
+ ($_t:tt, $new: tt) => {
+ $new
};
}
macro_rules! impl_array_tuple_inner {
(($($letter: ident,)*)) => {
- impl<T> ArrayTuple for ($(t!($letter),)*) {
+ impl<T> NonEmptyArrayTuple for ($(replace!($letter, T),)*) {
type Item = T;
+
+ fn fill(item: Self::Item) -> Self where T: Copy {
+ ($(replace!($letter, item),)*)
+ }
}
};
}
diff --git a/varihappy-macros/src/lib.rs b/varihappy-macros/src/lib.rs
index 3b1cc29..1d519c2 100644
--- a/varihappy-macros/src/lib.rs
+++ b/varihappy-macros/src/lib.rs
@@ -212,3 +212,27 @@ pub fn tuple_len(input: TokenStream) -> TokenStream {
let len = Literal::usize_unsuffixed(tuple.elems.len());
quote! { #len }.into()
}
+
+struct ArrayTuple {
+ ty: syn::Type,
+ count: syn::LitInt,
+}
+
+impl syn::parse::Parse for ArrayTuple {
+ fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
+ let ty = input.parse()?;
+ input.parse::<syn::Token![;]>()?;
+ let count = input.parse()?;
+
+ Ok(Self { ty, count })
+ }
+}
+
+#[proc_macro]
+pub fn array_tuple(input: TokenStream) -> TokenStream {
+ let ast = syn::parse_macro_input!(input as ArrayTuple);
+
+ let types = (0..ast.count.base10_parse::<u128>().unwrap()).map(|_| ast.ty.clone());
+
+ quote! { (#(#types,)*) }.into()
+}