Implement tuple mapping (#2247)

* implement tuple mapping

* docs, clippy magic

* clippy >:(

* rename for clarity
This commit is contained in:
Addison Crump 2024-05-28 18:11:41 +02:00 committed by GitHub
parent 65af5a7f78
commit 058e15f547
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -740,6 +740,43 @@ where
}
}
/// Trait for structs which are capable of mapping a given type to another.
pub trait MappingFunctor<T> {
/// 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<M> {
/// The result of the mapping operation.
type MapResult;
/// Perform the mapping!
fn map(self, mapper: M) -> Self::MapResult;
}
impl<Head, Tail, M> Map<M> for (Head, Tail)
where
M: MappingFunctor<Head>,
Tail: Map<M>,
{
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<M> Map<M> 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<Head, Tail> 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<u32>,
>());
}
#[test]
fn test_mapper() {
struct W<T>(T);
struct MyMapper;
impl<T> MappingFunctor<T> for MyMapper {
type Output = W<T>;
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<A>, W<B>, W<C>) = mapped;
}
}