From 058e15f547c66fad9fd47db7e2603679b919d33a Mon Sep 17 00:00:00 2001 From: Addison Crump Date: Tue, 28 May 2024 18:11:41 +0200 Subject: [PATCH] Implement tuple mapping (#2247) * implement tuple mapping * docs, clippy magic * clippy >:( * rename for clarity --- libafl_bolts/src/tuples.rs | 66 +++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/libafl_bolts/src/tuples.rs b/libafl_bolts/src/tuples.rs index 282124111e..5f304ffe39 100644 --- a/libafl_bolts/src/tuples.rs +++ b/libafl_bolts/src/tuples.rs @@ -740,6 +740,43 @@ where } } +/// Trait for structs which are capable of mapping a given type to another. +pub trait MappingFunctor { + /// The result of the mapping operation. + type Output; + + /// The actual mapping operation. + fn apply(&mut self, from: T) -> Self::Output; +} + +/// Map all entries in a tuple to another type, dependent on the tail type. +pub trait Map { + /// The result of the mapping operation. + type MapResult; + + /// Perform the mapping! + fn map(self, mapper: M) -> Self::MapResult; +} + +impl Map for (Head, Tail) +where + M: MappingFunctor, + Tail: Map, +{ + type MapResult = (M::Output, Tail::MapResult); + + fn map(self, mut mapper: M) -> Self::MapResult { + let head = mapper.apply(self.0); + (head, self.1.map(mapper)) + } +} + +impl Map for () { + type MapResult = (); + + fn map(self, _mapper: M) -> Self::MapResult {} +} + /// Iterate over a tuple, executing the given `expr` for each element. #[macro_export] #[allow(clippy::items_after_statements)] @@ -856,9 +893,11 @@ impl PlusOne for (Head, Tail) where #[cfg(test)] mod test { + use tuple_list::{tuple_list, tuple_list_type}; + #[cfg(feature = "alloc")] use crate::ownedref::OwnedMutSlice; - use crate::tuples::type_eq; + use crate::tuples::{type_eq, Map, MappingFunctor}; #[test] #[allow(unused_qualifications)] // for type name tests @@ -902,4 +941,29 @@ mod test { crate::ownedref::OwnedMutSlice, >()); } + + #[test] + fn test_mapper() { + struct W(T); + struct MyMapper; + + impl MappingFunctor for MyMapper { + type Output = W; + + fn apply(&mut self, from: T) -> Self::Output { + W(from) + } + } + + struct A; + struct B; + struct C; + + let orig = tuple_list!(A, B, C); + let mapped = orig.map(MyMapper); + + // this won't compile if the mapped type is not correct + #[allow(clippy::no_effect_underscore_binding)] + let _type_assert: tuple_list_type!(W, W, W) = mapped; + } }