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(); + } +} + +*/