diff --git a/afl/src/tuples.rs b/afl/src/tuples.rs
new file mode 100644
index 0000000000..2972a9723e
--- /dev/null
+++ b/afl/src/tuples.rs
@@ -0,0 +1,156 @@
+use tuple_list::TupleList;
+use tuple_list::tuple_list;
+use core::any::{TypeId, Any};
+
+pub trait HasLen {
+ fn len(&self) -> usize;
+}
+
+impl HasLen for () {
+ fn len(&self) -> usize { 0 }
+}
+
+impl
HasLen for (Head, Tail) where
+ Tail: TupleList + HasLen,
+{
+ fn len(&self) -> usize {
+ 1 + self.1.len()
+ }
+}
+
+pub trait MatchFirstType {
+ fn match_first_type(&self) -> Option<&T>;
+}
+
+impl MatchFirstType for () {
+ fn match_first_type(&self) -> Option<&T> { None }
+}
+
+impl MatchFirstType for (Head, Tail) where
+ Head: 'static,
+ Tail: TupleList + MatchFirstType,
+{
+ fn match_first_type(&self) -> Option<&T> {
+ if TypeId::of::() == TypeId::of::() {
+ unsafe { (&self.0 as *const _ as *const T).as_ref() }
+ } else {
+ self.1.match_first_type::()
+ }
+ }
+}
+
+pub trait MatchType {
+ fn match_type(&self, f: fn(t: &T));
+}
+
+impl MatchType for () {
+ fn match_type(&self, f: fn(t: &T)) { () }
+}
+
+impl MatchType for (Head, Tail) where
+ Head: 'static,
+ Tail: TupleList + MatchType,
+{
+ fn match_type(&self, f: fn(t: &T)) {
+ if TypeId::of::() == TypeId::of::() {
+ f(unsafe { (&self.0 as *const _ as *const T).as_ref() }.unwrap());
+ }
+ self.1.match_type::(f);
+ }
+}
+
+pub trait Named {
+ fn name(&self) -> &'static str;
+}
+
+pub trait MatchNameAndType {
+ fn match_name_type(&self, name: &'static str) -> Option<&T>;
+}
+
+impl MatchNameAndType for () {
+ fn match_name_type(&self, name: &'static str) -> Option<&T> { None }
+}
+
+impl MatchNameAndType for (Head, Tail) where
+ Head: 'static + Named,
+ Tail: TupleList + MatchNameAndType,
+{
+ fn match_name_type(&self, name: &'static str) -> Option<&T> {
+ if TypeId::of::() == TypeId::of::() && name == self.0.name() {
+ unsafe { (&self.0 as *const _ as *const T).as_ref() }
+ } else {
+ self.1.match_name_type::(name)
+ }
+ }
+}
+
+pub trait Prepend: TupleList {
+ type PreprendResult: TupleList;
+
+ fn prepend(self, value: T) -> (T, Self::PreprendResult);
+}
+
+/// Implement prepend for tuple list.
+impl Prepend for Tail where Tail: TupleList {
+ type PreprendResult = Self;
+
+ fn prepend(self, value: T) -> (T, Self::PreprendResult) {
+ (value, self)
+ }
+}
+
+pub trait Append: TupleList {
+ type AppendResult: TupleList;
+
+ fn append(self, value: T) -> Self::AppendResult;
+}
+
+/// Implement append for an empty tuple list.
+impl Append for () {
+ type AppendResult = (T, ());
+
+ fn append(self, value: T) -> Self::AppendResult { (value, ()) }
+}
+
+/// Implement append for non-empty tuple list.
+impl Append for (Head, Tail) where
+ Self: TupleList,
+ Tail: Append,
+ (Head, Tail::AppendResult): TupleList,
+{
+ type AppendResult = (Head, Tail::AppendResult);
+
+ fn append(self, value: T) -> Self::AppendResult {
+ let (head, tail) = self;
+ return (head, tail.append(value));
+ }
+}
+
+/*
+
+// Define trait and implement it for several primitive types.
+trait PlusOne {
+ fn plus_one(&mut self);
+}
+impl PlusOne for i32 { fn plus_one(&mut self) { *self += 1; } }
+impl PlusOne for String { fn plus_one(&mut self) { self.push('1'); } }
+
+// Now we have to implement trait for an empty tuple,
+// thus defining initial condition.
+impl PlusOne for () {
+ fn plus_one(&mut self) {}
+}
+
+// Now we can implement trait for a non-empty tuple list,
+// thus defining recursion and supporting tuple lists of arbitrary length.
+impl PlusOne for (Head, Tail) where
+ Head: PlusOne,
+ Tail: PlusOne + TupleList,
+{
+ fn plus_one(&mut self) {
+ self.0.plus_one();
+ self.1.plus_one();
+ }
+}
+
+*/