Skip to main content

tuple_list_ex/
lib.rs

1//! Compiletime lists/tuples used throughout the `LibAFL` universe
2#![doc = include_str!("../README.md")]
3/*! */
4#![cfg_attr(feature = "document-features", doc = document_features::document_features!())]
5#![no_std]
6#![cfg_attr(not(test), warn(
7    missing_debug_implementations,
8    missing_docs,
9    //trivial_casts,
10    trivial_numeric_casts,
11    unused_extern_crates,
12    unused_import_braces,
13    unused_qualifications,
14    //unused_results
15))]
16#![cfg_attr(test, deny(
17    missing_debug_implementations,
18    missing_docs,
19    //trivial_casts,
20    trivial_numeric_casts,
21    unused_extern_crates,
22    unused_import_braces,
23    unused_qualifications,
24    unused_must_use,
25    //unused_results
26))]
27#![cfg_attr(
28    test,
29    deny(
30        bad_style,
31        dead_code,
32        improper_ctypes,
33        non_shorthand_field_patterns,
34        overflowing_literals,
35        path_statements,
36        patterns_in_fns_without_body,
37        unconditional_recursion,
38        unused,
39        unused_allocation,
40        unused_comparisons,
41        unused_parens,
42        while_true
43    )
44)]
45
46#[cfg(feature = "std")]
47#[macro_use]
48extern crate std;
49#[cfg(feature = "alloc")]
50#[doc(hidden)]
51pub extern crate alloc;
52
53#[cfg(feature = "alloc")]
54use alloc::{borrow::Cow, vec::Vec};
55use core::{any::TypeId, mem::transmute};
56#[cfg(feature = "alloc")]
57use core::{
58    any::type_name,
59    fmt::{Debug, Formatter},
60    marker::PhantomData,
61    ops::{Deref, DerefMut, Index, IndexMut},
62};
63
64#[cfg(feature = "alloc")]
65use libafl_core::Named;
66#[cfg(feature = "serde")]
67use serde::{Deserialize, Serialize};
68pub use tuple_list::{TupleList, tuple_list, tuple_list_type};
69
70#[cfg(feature = "alloc")]
71use crate::seal::StackedExtract;
72
73/// Returns if the type `T` is equal to `U`, ignoring lifetimes.
74#[must_use]
75pub fn type_eq<T: ?Sized, U: ?Sized>() -> bool {
76    typeid::of::<T>() == typeid::of::<U>()
77}
78
79/// Borrow each member of the tuple
80pub trait SplitBorrow<'a> {
81    /// The Resulting [`TupleList`], of an [`SplitBorrow::borrow()`] call
82    type SplitBorrowResult;
83    /// The Resulting [`TupleList`], of an [`SplitBorrow::borrow_mut()`] call
84    type SplitBorrowMutResult;
85
86    /// Return a tuple of borrowed references
87    fn borrow(&'a self) -> Self::SplitBorrowResult;
88    /// Return a tuple of borrowed mutable references
89    fn borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult;
90}
91
92impl<'a> SplitBorrow<'a> for () {
93    type SplitBorrowResult = ();
94    type SplitBorrowMutResult = ();
95
96    fn borrow(&'a self) -> Self::SplitBorrowResult {}
97
98    fn borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult {}
99}
100
101impl<'a, Head, Tail> SplitBorrow<'a> for (Head, Tail)
102where
103    Head: 'a,
104    Tail: SplitBorrow<'a>,
105{
106    type SplitBorrowResult = (Option<&'a Head>, Tail::SplitBorrowResult);
107    type SplitBorrowMutResult = (Option<&'a mut Head>, Tail::SplitBorrowMutResult);
108
109    fn borrow(&'a self) -> Self::SplitBorrowResult {
110        (Some(&self.0), self.1.borrow())
111    }
112
113    fn borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult {
114        (Some(&mut self.0), self.1.borrow_mut())
115    }
116}
117
118/// Create a [`Vec`] from a tuple list or similar
119/// (We need this trait since we cannot implement `Into` for foreign types)
120#[cfg(feature = "alloc")]
121pub trait IntoVec<T> {
122    /// Convert this into a [`Vec`], reversed.
123    /// (Having this method around makes some implementations more performant)
124    fn into_vec_reversed(self) -> Vec<T>
125    where
126        Self: Sized,
127    {
128        let mut ret = self.into_vec();
129        ret.reverse();
130        ret
131    }
132
133    /// Convert this into a [`Vec`].
134    fn into_vec(self) -> Vec<T>;
135}
136
137#[cfg(feature = "alloc")]
138impl<T> IntoVec<T> for () {
139    #[inline]
140    fn into_vec(self) -> Vec<T> {
141        Vec::new()
142    }
143}
144
145/// Gets the length of the element
146pub trait HasConstLen {
147    /// The length as constant `usize`
148    const LEN: usize;
149}
150
151impl HasConstLen for () {
152    const LEN: usize = 0;
153}
154
155impl<Head, Tail> HasConstLen for (Head, Tail)
156where
157    Tail: HasConstLen,
158{
159    const LEN: usize = 1 + Tail::LEN;
160}
161
162/// Returns the first element with the given type
163pub trait MatchFirstType {
164    /// Returns the first element with the given type as borrow, or [`None`]
165    fn match_first_type<T: 'static>(&self) -> Option<&T>;
166    /// Returns the first element with the given type as mutable borrow, or [`None`]
167    fn match_first_type_mut<T: 'static>(&mut self) -> Option<&mut T>;
168}
169
170impl MatchFirstType for () {
171    fn match_first_type<T: 'static>(&self) -> Option<&T> {
172        None
173    }
174    fn match_first_type_mut<T: 'static>(&mut self) -> Option<&mut T> {
175        None
176    }
177}
178
179impl<Head, Tail> MatchFirstType for (Head, Tail)
180where
181    Head: 'static,
182    Tail: MatchFirstType,
183{
184    fn match_first_type<T: 'static>(&self) -> Option<&T> {
185        if TypeId::of::<T>() == TypeId::of::<Head>() {
186            unsafe { (&raw const self.0 as *const T).as_ref() }
187        } else {
188            self.1.match_first_type::<T>()
189        }
190    }
191
192    fn match_first_type_mut<T: 'static>(&mut self) -> Option<&mut T> {
193        if TypeId::of::<T>() == TypeId::of::<Head>() {
194            unsafe { (&raw mut self.0 as *mut T).as_mut() }
195        } else {
196            self.1.match_first_type_mut::<T>()
197        }
198    }
199}
200
201/// Returns the first element with the given type (dereference mut version)
202pub trait ExtractFirstRefType {
203    /// Returns the first element with the given type as borrow, or [`None`]
204    fn take<'a, T: 'static>(self) -> (Option<&'a T>, Self);
205}
206
207impl ExtractFirstRefType for () {
208    fn take<'a, T: 'static>(self) -> (Option<&'a T>, Self) {
209        tuple_list!(None)
210    }
211}
212
213impl<Head, Tail> ExtractFirstRefType for (Option<&Head>, Tail)
214where
215    Head: 'static,
216    Tail: ExtractFirstRefType,
217{
218    fn take<'a, T: 'static>(mut self) -> (Option<&'a T>, Self) {
219        if TypeId::of::<T>() == TypeId::of::<Head>() {
220            let r = self.0.take();
221            (unsafe { transmute::<Option<&Head>, Option<&T>>(r) }, self)
222        } else {
223            let (r, tail) = self.1.take::<T>();
224            (r, (self.0, tail))
225        }
226    }
227}
228
229impl<Head, Tail> ExtractFirstRefType for (Option<&mut Head>, Tail)
230where
231    Head: 'static,
232    Tail: ExtractFirstRefType,
233{
234    fn take<'a, T: 'static>(mut self) -> (Option<&'a T>, Self) {
235        if TypeId::of::<T>() == TypeId::of::<Head>() {
236            let r = self.0.take();
237            (
238                unsafe { transmute::<Option<&mut Head>, Option<&T>>(r) },
239                self,
240            )
241        } else {
242            let (r, tail) = self.1.take::<T>();
243            (r, (self.0, tail))
244        }
245    }
246}
247
248/// Returns the first element with the given type (dereference mut version)
249pub trait ExtractFirstRefMutType {
250    /// Returns the first element with the given type as borrow, or [`None`]
251    fn take<'a, T: 'static>(self) -> (Option<&'a mut T>, Self);
252}
253
254impl ExtractFirstRefMutType for () {
255    fn take<'a, T: 'static>(self) -> (Option<&'a mut T>, Self) {
256        tuple_list!(None)
257    }
258}
259
260impl<Head, Tail> ExtractFirstRefMutType for (Option<&mut Head>, Tail)
261where
262    Head: 'static,
263    Tail: ExtractFirstRefMutType,
264{
265    fn take<'a, T: 'static>(mut self) -> (Option<&'a mut T>, Self) {
266        if TypeId::of::<T>() == TypeId::of::<Head>() {
267            let r = self.0.take();
268            (
269                unsafe { transmute::<Option<&mut Head>, Option<&mut T>>(r) },
270                self,
271            )
272        } else {
273            let (r, tail) = self.1.take::<T>();
274            (r, (self.0, tail))
275        }
276    }
277}
278
279/// Borrow each member of the tuple
280pub trait SplitBorrowExtractFirstType<'a> {
281    /// The Resulting [`TupleList`], of an [`SplitBorrow::borrow()`] call
282    type SplitBorrowResult: ExtractFirstRefType;
283    /// The Resulting [`TupleList`], of an [`SplitBorrow::borrow_mut()`] call
284    type SplitBorrowMutResult: ExtractFirstRefType + ExtractFirstRefMutType;
285
286    /// Return a tuple of borrowed references
287    fn borrow(&'a self) -> Self::SplitBorrowResult;
288    /// Return a tuple of borrowed mutable references
289    fn borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult;
290}
291
292impl<'a> SplitBorrowExtractFirstType<'a> for () {
293    type SplitBorrowResult = ();
294    type SplitBorrowMutResult = ();
295
296    fn borrow(&'a self) -> Self::SplitBorrowResult {}
297
298    fn borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult {}
299}
300
301impl<'a, Head, Tail> SplitBorrowExtractFirstType<'a> for (Head, Tail)
302where
303    Head: 'static,
304    Tail: SplitBorrowExtractFirstType<'a>,
305{
306    type SplitBorrowResult = (Option<&'a Head>, Tail::SplitBorrowResult);
307    type SplitBorrowMutResult = (Option<&'a mut Head>, Tail::SplitBorrowMutResult);
308
309    fn borrow(&'a self) -> Self::SplitBorrowResult {
310        (Some(&self.0), self.1.borrow())
311    }
312
313    fn borrow_mut(&'a mut self) -> Self::SplitBorrowMutResult {
314        (Some(&mut self.0), self.1.borrow_mut())
315    }
316}
317
318/// Match by type
319pub trait MatchType {
320    /// Match by type and call the passed `f` function with a borrow, if found
321    fn match_type<T: 'static, FN: FnMut(&T)>(&self, f: &mut FN);
322    /// Match by type and call the passed `f` function with a mutable borrow, if found
323    fn match_type_mut<T: 'static, FN: FnMut(&mut T)>(&mut self, f: &mut FN);
324}
325
326impl MatchType for () {
327    /// Match by type and call the passed `f` function with a borrow, if found
328    fn match_type<T: 'static, FN: FnMut(&T)>(&self, _: &mut FN) {}
329    /// Match by type and call the passed `f` function with a mutable borrow, if found
330    fn match_type_mut<T: 'static, FN: FnMut(&mut T)>(&mut self, _: &mut FN) {}
331}
332
333impl<Head, Tail> MatchType for (Head, Tail)
334where
335    Head: 'static,
336    Tail: MatchType,
337{
338    fn match_type<T: 'static, FN: FnMut(&T)>(&self, f: &mut FN) {
339        // Switch this check to https://stackoverflow.com/a/60138532/7658998 when in stable and remove 'static
340        if TypeId::of::<T>() == TypeId::of::<Head>() {
341            f(unsafe { (&raw const self.0 as *const T).as_ref() }.unwrap());
342        }
343        self.1.match_type::<T, FN>(f);
344    }
345
346    fn match_type_mut<T: 'static, FN: FnMut(&mut T)>(&mut self, f: &mut FN) {
347        // Switch this check to https://stackoverflow.com/a/60138532/7658998 when in stable and remove 'static
348        if TypeId::of::<T>() == TypeId::of::<Head>() {
349            f(unsafe { (&raw mut self.0 as *mut T).as_mut() }.unwrap());
350        }
351        self.1.match_type_mut::<T, FN>(f);
352    }
353}
354
355#[cfg(feature = "alloc")]
356/// A named tuple
357pub trait NamedTuple {
358    /// Gets the name of this tuple
359    fn name(&self, index: usize) -> Option<&Cow<'static, str>>;
360
361    /// Gets all the names
362    fn names(&self) -> Vec<Cow<'static, str>>;
363}
364
365#[cfg(feature = "alloc")]
366impl NamedTuple for () {
367    fn name(&self, _index: usize) -> Option<&Cow<'static, str>> {
368        None
369    }
370
371    fn names(&self) -> Vec<Cow<'static, str>> {
372        Vec::new()
373    }
374}
375
376#[cfg(feature = "alloc")]
377impl<Head, Tail> NamedTuple for (Head, Tail)
378where
379    Head: Named,
380    Tail: NamedTuple,
381{
382    fn name(&self, index: usize) -> Option<&Cow<'static, str>> {
383        if index == 0 {
384            Some(self.0.name())
385        } else {
386            self.1.name(index - 1)
387        }
388    }
389
390    fn names(&self) -> Vec<Cow<'static, str>> {
391        let first = self.0.name().clone();
392        let mut last = self.1.names();
393        last.insert(0, first);
394        last
395    }
396}
397
398/// Match for a name and return the value
399#[cfg(feature = "alloc")]
400pub trait MatchName {
401    /// Match for a name and return the borrowed value
402    #[deprecated = "Use `.handle` and either `.get` (fallible access) or `[]` (infallible access) instead"]
403    fn match_name<T>(&self, name: &str) -> Option<&T>;
404    /// Match for a name and return the mut borrowed value
405    #[deprecated = "Use `.handle` and either `.get` (fallible access) or `[]` (infallible access) instead"]
406    fn match_name_mut<T>(&mut self, name: &str) -> Option<&mut T>;
407}
408
409#[cfg(feature = "alloc")]
410impl MatchName for () {
411    fn match_name<T>(&self, _name: &str) -> Option<&T> {
412        None
413    }
414    fn match_name_mut<T>(&mut self, _name: &str) -> Option<&mut T> {
415        None
416    }
417}
418
419#[cfg(feature = "alloc")]
420#[expect(deprecated)]
421impl<Head, Tail> MatchName for (Head, Tail)
422where
423    Head: Named,
424    Tail: MatchName,
425{
426    fn match_name<T>(&self, name: &str) -> Option<&T> {
427        if type_eq::<Head, T>() && name == self.0.name() {
428            unsafe { (&raw const self.0 as *const T).as_ref() }
429        } else {
430            self.1.match_name::<T>(name)
431        }
432    }
433
434    fn match_name_mut<T>(&mut self, name: &str) -> Option<&mut T> {
435        if type_eq::<Head, T>() && name == self.0.name() {
436            unsafe { (&raw mut self.0 as *mut T).as_mut() }
437        } else {
438            self.1.match_name_mut::<T>(name)
439        }
440    }
441}
442
443/// Structs that have a [`Handle`] to reference this element by, in maps.
444/// You should use this when you want to avoid specifying types.
445#[cfg(feature = "alloc")]
446pub trait Handled: Named {
447    /// Return the [`Handle`]
448    fn handle(&self) -> Handle<Self> {
449        Handle {
450            name: Named::name(self).clone(),
451            phantom: PhantomData,
452        }
453    }
454}
455
456#[cfg(feature = "alloc")]
457impl<N> Handled for N where N: Named {}
458
459/// Object with the type T and the name associated with its concrete value
460#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
461#[cfg(feature = "alloc")]
462pub struct Handle<T: ?Sized> {
463    name: Cow<'static, str>,
464    #[cfg_attr(feature = "serde", serde(skip))]
465    phantom: PhantomData<T>,
466}
467
468#[cfg(feature = "alloc")]
469impl<T: ?Sized> Handle<T> {
470    /// Create a new [`Handle`] with the given name.
471    #[must_use]
472    pub fn new(name: Cow<'static, str>) -> Self {
473        Self {
474            name,
475            phantom: PhantomData,
476        }
477    }
478
479    /// Fetch the name of the referenced instance.
480    ///
481    /// We explicitly do *not* implement [`Named`], as this could potentially lead to confusion
482    /// where we make a [`Handle`] of a [`Handle`] as [`Named`] is blanket implemented.
483    #[must_use]
484    pub fn name(&self) -> &Cow<'static, str> {
485        &self.name
486    }
487}
488
489#[cfg(feature = "alloc")]
490impl<T> Clone for Handle<T> {
491    fn clone(&self) -> Self {
492        Self {
493            name: self.name.clone(),
494            phantom: PhantomData,
495        }
496    }
497}
498
499#[cfg(feature = "alloc")]
500impl<T> Debug for Handle<T> {
501    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
502        f.debug_struct("Handle")
503            .field("name", self.name())
504            .field("type", &type_name::<T>())
505            .finish()
506    }
507}
508
509/// Search using `Handle `
510#[cfg(feature = "alloc")]
511pub trait MatchNameRef {
512    /// Search using name and `Handle `
513    fn get<T>(&self, rf: &Handle<T>) -> Option<&T>;
514
515    /// Search using name and `Handle `
516    fn get_mut<T>(&mut self, rf: &Handle<T>) -> Option<&mut T>;
517}
518
519/// Get multiple values using a tuple of handles
520///
521/// # Example
522/// ```ignore
523/// let tuple = tuple_list!(a, b, c);
524/// let handles = tuple_list!(&a_handle, &c_handle);
525/// let tuple_list!(a_ref, c_ref) = tuple.get_all(handles);
526/// ```
527#[cfg(feature = "alloc")]
528pub trait GetAll<HandleTuple> {
529    /// The result type of getting all values
530    type GetAllResult<'a>
531    where
532        Self: 'a;
533
534    /// The result type of getting all mutable values
535    type GetAllMutResult<'a>
536    where
537        Self: 'a;
538
539    /// Get all values from a tuple of handles, the order is preserved
540    fn get_all(&self, handles: HandleTuple) -> Self::GetAllResult<'_>;
541
542    /// Get all mutable values from a tuple of handles, the order is preserved
543    fn get_all_mut(&mut self, handles: HandleTuple) -> Self::GetAllMutResult<'_>;
544}
545
546#[cfg(feature = "alloc")]
547#[expect(deprecated)]
548impl<M> MatchNameRef for M
549where
550    M: MatchName,
551{
552    fn get<T>(&self, rf: &Handle<T>) -> Option<&T> {
553        self.match_name::<T>(&rf.name)
554    }
555
556    fn get_mut<T>(&mut self, rf: &Handle<T>) -> Option<&mut T> {
557        self.match_name_mut::<T>(&rf.name)
558    }
559}
560
561#[cfg(feature = "alloc")]
562impl<Head, Tail> GetAll<()> for (Head, Tail)
563where
564    (Head, Tail): MatchNameRef,
565{
566    type GetAllResult<'a>
567        = ()
568    where
569        Self: 'a;
570
571    type GetAllMutResult<'a>
572        = ()
573    where
574        Self: 'a;
575
576    fn get_all(&self, _handles: ()) -> Self::GetAllResult<'_> {}
577
578    fn get_all_mut(&mut self, _handles: ()) -> Self::GetAllMutResult<'_> {}
579}
580
581/// Returns a mutably borrowed element
582pub trait InnerBorrowMut {
583    /// The type we need borrowed
584    type Borrowed<'a>
585    where
586        Self: 'a;
587
588    /// Returns the borrow
589    fn inner_borrow_mut(&mut self) -> Self::Borrowed<'_>;
590}
591
592#[cfg(feature = "alloc")]
593mod seal {
594    //! The logic in this section enables the [`super::GetAll::get_all_mut`] implementation.
595    //!
596    //! This works by treating tuple lists like queues; first, we convert a mutable ref to a tuple
597    //! list into a tuple list of mutable refs. With this, we then check each member of the tuple
598    //! list against the head of the handle list. If the head doesn't match, we append the head to
599    //! a list of already visited nodes. If the head matches, we extract the head and restart
600    //! traversal _without_ the head by merging the visited list with the tail of the current list.
601    //! If we ever hit the tail of the current list, we pop the top handle off and continue the
602    //! search from the start.
603    //!
604    //! Visualised, you can think of this something like this:
605    //!
606    //! ```text
607    //! handles:    [a, c, e]
608    //! tuple list: [a, b, c, d]
609    //! visited:    []
610    //!
611    //! 'a' matches 'a', so we stash 'a' continue with:
612    //! handles:    [c, e]
613    //! tuple list: [b, c, d]
614    //! visited:    []
615    //!
616    //! 'c' does not match 'b', so we push to the visited list and continue with:
617    //! handles:    [c, e]
618    //! tuple list: [c, d]
619    //! visited:    [b]
620    //!
621    //! 'c' matches; stash 'c', merge visited to list, and continue:
622    //! handles:    [e]
623    //! tuple list: [b, d]
624    //! visited:    []
625    //!
626    //! 'b' and 'd' do not match, so we make it to the base case:
627    //! handles:    [e]
628    //! tuple list: []
629    //! visited:    [b, d]
630    //!
631    //! We set the 'e' match to None, merge visited to list, then continue:
632    //! handles:    []
633    //! tuple list: [b, d]
634    //! visited:    []
635    //!
636    //! Handles is now empty, so we return () (list terminator) and end up with:
637    //! [Some(a), Some(c), None]
638    //! ```
639
640    use libafl_core::Named;
641    use tuple_list::tuple_list;
642
643    use crate::{Handle, InnerBorrowMut, Merge, type_eq};
644
645    impl<Head, Tail> InnerBorrowMut for (Head, Tail)
646    where
647        Tail: InnerBorrowMut,
648    {
649        type Borrowed<'a>
650            = (&'a mut Head, Tail::Borrowed<'a>)
651        where
652            Self: 'a;
653
654        fn inner_borrow_mut(&mut self) -> Self::Borrowed<'_> {
655            (&mut self.0, self.1.inner_borrow_mut())
656        }
657    }
658
659    impl InnerBorrowMut for () {
660        type Borrowed<'a>
661            = ()
662        where
663            Self: 'a;
664
665        fn inner_borrow_mut(&mut self) -> Self::Borrowed<'_> {}
666    }
667
668    pub trait StackedExtract<'a, Handles, Visited> {
669        type Result;
670
671        fn extract(self, handles: Handles, visited: Visited) -> Self::Result;
672    }
673
674    impl<'a, T, HTail, Visited> StackedExtract<'a, (&Handle<T>, HTail), Visited> for ()
675    where
676        Visited: StackedExtract<'a, HTail, ()>,
677        T: 'a,
678    {
679        type Result = (Option<&'a mut T>, Visited::Result);
680
681        fn extract(self, handles: (&Handle<T>, HTail), visited: Visited) -> Self::Result {
682            (None, visited.extract(handles.1, ()))
683        }
684    }
685
686    impl<U, Visited> StackedExtract<'_, (), Visited> for U {
687        type Result = ();
688
689        fn extract(self, _handles: (), _visited: Visited) -> Self::Result {}
690    }
691
692    impl<'a, T, HTail, Head, Tail, Visited> StackedExtract<'a, (&Handle<T>, HTail), Visited>
693        for (&'a mut Head, Tail)
694    where
695        Head: Named,
696        Tail: for<'b> StackedExtract<
697                'a,
698                (&'b Handle<T>, HTail),
699                <Visited as Merge<(&'a mut Head, ())>>::MergeResult,
700                Result = (
701                    Option<&'a mut T>,
702                    <<Visited as Merge<Tail>>::MergeResult as StackedExtract<'a, HTail, ()>>::Result,
703                ),
704            >,
705        Visited: Merge<(&'a mut Head, ())>,
706        Visited: Merge<Tail>,
707        <Visited as Merge<Tail>>::MergeResult: StackedExtract<'a, HTail, ()>,
708        T: 'a,
709    {
710        type Result = (
711            Option<&'a mut T>,
712            <<Visited as Merge<Tail>>::MergeResult as StackedExtract<'a, HTail, ()>>::Result,
713        );
714
715        fn extract(self, handles: (&Handle<T>, HTail), visited: Visited) -> Self::Result {
716            if type_eq::<Head, T>() && &handles.0.name == self.0.name() {
717                (
718                    unsafe { (core::ptr::from_mut(self.0) as *mut T).as_mut() },
719                    visited.merge(self.1).extract(handles.1, ()),
720                )
721            } else {
722                self.1.extract(handles, visited.merge(tuple_list!(self.0)))
723            }
724        }
725    }
726}
727
728#[cfg(feature = "alloc")]
729impl<'b, Head, Tail, T, HandleTail> GetAll<(&'b Handle<T>, HandleTail)> for (Head, Tail)
730where
731    (Head, Tail): MatchNameRef + GetAll<HandleTail> + InnerBorrowMut,
732    for<'a> <(Head, Tail) as InnerBorrowMut>::Borrowed<'a>:
733        StackedExtract<'a, (&'b Handle<T>, HandleTail), ()>,
734    T: 'static,
735{
736    type GetAllResult<'a>
737        = (
738        Option<&'a T>,
739        <(Head, Tail) as GetAll<HandleTail>>::GetAllResult<'a>,
740    )
741    where
742        Self: 'a;
743
744    type GetAllMutResult<'a>
745        = <<(Head, Tail) as InnerBorrowMut>::Borrowed<'a> as StackedExtract<
746        'a,
747        (&'b Handle<T>, HandleTail),
748        (),
749    >>::Result
750    where
751        Self: 'a;
752
753    fn get_all(&self, handles: (&Handle<T>, HandleTail)) -> Self::GetAllResult<'_> {
754        let (head_handle, tail_handles) = handles;
755        let head_result = self.get(head_handle);
756        let tail_result = <(Head, Tail) as GetAll<HandleTail>>::get_all(self, tail_handles);
757        (head_result, tail_result)
758    }
759
760    fn get_all_mut(&mut self, handles: (&'b Handle<T>, HandleTail)) -> Self::GetAllMutResult<'_> {
761        self.inner_borrow_mut().extract(handles, ())
762    }
763}
764
765/// A wrapper type to enable the indexing of [`MatchName`] implementors with `[]`.
766#[cfg(feature = "alloc")]
767#[derive(Debug, Copy, Clone)]
768#[repr(transparent)]
769pub struct RefIndexable<RM, M>(RM, PhantomData<M>);
770
771#[cfg(feature = "alloc")]
772impl<RM, M> From<RM> for RefIndexable<RM, M>
773where
774    RM: Deref<Target = M>,
775{
776    fn from(value: RM) -> Self {
777        RefIndexable(value, PhantomData)
778    }
779}
780
781#[cfg(feature = "alloc")]
782impl<RM, M> Deref for RefIndexable<RM, M>
783where
784    RM: Deref<Target = M>,
785{
786    type Target = RM::Target;
787
788    fn deref(&self) -> &Self::Target {
789        &self.0
790    }
791}
792
793#[cfg(feature = "alloc")]
794impl<RM, M> DerefMut for RefIndexable<RM, M>
795where
796    RM: DerefMut<Target = M>,
797{
798    fn deref_mut(&mut self) -> &mut Self::Target {
799        &mut self.0
800    }
801}
802
803#[cfg(feature = "alloc")]
804impl<T, RM, M> Index<&Handle<T>> for RefIndexable<RM, M>
805where
806    RM: Deref<Target = M>,
807    M: MatchName,
808{
809    type Output = T;
810
811    fn index(&self, index: &Handle<T>) -> &Self::Output {
812        let Some(e) = self.get(index) else {
813            panic!("Could not find entry matching {index:?}")
814        };
815        e
816    }
817}
818
819#[cfg(feature = "alloc")]
820impl<T, RM, M> IndexMut<&Handle<T>> for RefIndexable<RM, M>
821where
822    RM: DerefMut<Target = M>,
823    M: MatchName,
824{
825    fn index_mut(&mut self, index: &Handle<T>) -> &mut Self::Output {
826        let Some(e) = self.get_mut(index) else {
827            panic!("Could not find entry matching {index:?}")
828        };
829        e
830    }
831}
832
833/// Allows prepending of values to a tuple
834pub trait Prepend<T> {
835    /// Prepend a value to this tuple, returning a new tuple with prepended value.
836    #[must_use]
837    fn prepend(self, value: T) -> (T, Self);
838}
839
840/// Implement prepend for tuple list.
841impl<Tail, T> Prepend<T> for Tail {
842    fn prepend(self, value: T) -> (T, Self) {
843        (value, self)
844    }
845}
846
847/// Append to a tuple
848pub trait Append<T>
849where
850    Self: Sized,
851{
852    /// Append Value and return the tuple
853    #[must_use]
854    fn append(self, value: T) -> (Self, T);
855}
856
857/// Implement append for tuple list.
858impl<Head, T> Append<T> for Head {
859    fn append(self, value: T) -> (Self, T) {
860        (self, value)
861    }
862}
863
864/// Merge two `TupleList`
865pub trait Merge<T> {
866    /// The Resulting [`TupleList`], of an [`Merge::merge()`] call
867    type MergeResult;
868
869    /// Merge and return the merged tuple
870    #[must_use]
871    fn merge(self, value: T) -> Self::MergeResult;
872}
873
874/// Implement merge for an empty tuple list.
875impl<T> Merge<T> for () {
876    type MergeResult = T;
877
878    fn merge(self, value: T) -> Self::MergeResult {
879        value
880    }
881}
882
883/// Implement merge for non-empty tuple list.
884impl<Head, Tail, T> Merge<T> for (Head, Tail)
885where
886    Tail: Merge<T>,
887{
888    type MergeResult = (Head, Tail::MergeResult);
889
890    fn merge(self, value: T) -> Self::MergeResult {
891        let (head, tail) = self;
892        (head, tail.merge(value))
893    }
894}
895
896/// Trait for structs which are capable of mapping a given type to another.
897pub trait MappingFunctor<T> {
898    /// The result of the mapping operation.
899    type Output;
900
901    /// The actual mapping operation.
902    fn apply(&mut self, from: T) -> Self::Output;
903}
904
905/// Map all entries in a tuple to another type, dependent on the tail type.
906pub trait Map<M> {
907    /// The result of the mapping operation.
908    type MapResult;
909
910    /// Perform the mapping!
911    fn map(self, mapper: M) -> Self::MapResult;
912}
913
914impl<Head, Tail, M> Map<M> for (Head, Tail)
915where
916    M: MappingFunctor<Head>,
917    Tail: Map<M>,
918{
919    type MapResult = (M::Output, Tail::MapResult);
920
921    fn map(self, mut mapper: M) -> Self::MapResult {
922        let head = mapper.apply(self.0);
923        (head, self.1.map(mapper))
924    }
925}
926
927impl<M> Map<M> for () {
928    type MapResult = ();
929
930    fn map(self, _mapper: M) -> Self::MapResult {}
931}
932
933/// Iterate over a tuple, executing the given `expr` for each element.
934#[macro_export]
935macro_rules! tuple_for_each {
936    ($fn_name:ident, $trait_name:path, $tuple_name:ident, $body:expr) => {
937        mod $fn_name {
938            pub trait ForEach {
939                fn for_each(&self);
940            }
941
942            impl ForEach for () {
943                fn for_each(&self) {}
944            }
945
946            impl<Head, Tail> ForEach for (Head, Tail)
947            where
948                Head: $trait_name,
949                Tail: tuple_list::TupleList + ForEach,
950            {
951                #[allow(clippy::redundant_closure_call)] // macro may be called on a closure or a function
952                fn for_each(&self) {
953                    ($body)(&self.0);
954                    self.1.for_each();
955                }
956            }
957        }
958        {
959            use $fn_name::*;
960
961            $tuple_name.for_each();
962        };
963    };
964}
965
966/// Iterate over a tuple, executing the given `expr` for each element, granting mut access.
967#[macro_export]
968macro_rules! tuple_for_each_mut {
969    ($fn_name:ident, $trait_name:path, $tuple_name:ident, $body:expr) => {
970        mod $fn_name {
971            pub trait ForEachMut {
972                fn for_each_mut(&mut self);
973            }
974
975            impl ForEachMut for () {
976                fn for_each_mut(&mut self) {}
977            }
978
979            impl<Head, Tail> ForEachMut for (Head, Tail)
980            where
981                Head: $trait_name,
982                Tail: tuple_list::TupleList + ForEachMut,
983            {
984                #[allow(clippy::redundant_closure_call)] // macro may be called on a closure or a function
985                fn for_each_mut(&mut self) {
986                    ($body)(&mut self.0);
987                    self.1.for_each_mut();
988                }
989            }
990        }
991        {
992            use $fn_name::*;
993
994            $tuple_name.for_each_mut();
995        };
996    };
997}
998
999/// Maps the types of a mapping with a [`MappingFunctor`]
1000///
1001/// ```rust
1002/// use tuple_list_ex::{Map, MappingFunctor, map_tuple_list_type, tuple_list, tuple_list_type};
1003///
1004/// struct Wrapper<T>(T);
1005/// struct MyMapper;
1006///
1007/// impl<T> MappingFunctor<T> for MyMapper {
1008///     type Output = Wrapper<T>;
1009///
1010///     fn apply(&mut self, from: T) -> <Self as MappingFunctor<T>>::Output {
1011///         Wrapper(from)
1012///     }
1013/// }
1014///
1015/// struct A;
1016/// struct B;
1017/// struct C;
1018///
1019/// type OrigType = tuple_list_type!(A, B, C);
1020/// type MappedType = map_tuple_list_type!(OrigType, MyMapper);
1021/// let orig: OrigType = tuple_list!(A, B, C);
1022/// let _mapped: MappedType = orig.map(MyMapper);
1023/// ```
1024#[macro_export]
1025macro_rules! map_tuple_list_type {
1026    ($Tuple:ty, $Mapper:ty) => {
1027        <$Tuple as $crate::Map<$Mapper>>::MapResult
1028    };
1029}
1030
1031/// Merges the types of two merged [`tuple_list!`]s
1032///
1033/// ```rust
1034/// use tuple_list_ex::{Merge, merge_tuple_list_type, tuple_list, tuple_list_type};
1035///
1036/// struct A;
1037/// struct B;
1038/// struct C;
1039/// struct D;
1040/// struct E;
1041///
1042/// type Lhs = tuple_list_type!(A, B, C);
1043/// type Rhs = tuple_list_type!(D, E);
1044/// type Merged = merge_tuple_list_type!(Lhs, Rhs);
1045///
1046/// let lhs: Lhs = tuple_list!(A, B, C);
1047/// let rhs: Rhs = tuple_list!(D, E);
1048/// let _merged: Merged = lhs.merge(rhs);
1049/// ```
1050#[macro_export]
1051macro_rules! merge_tuple_list_type {
1052   // Base case: when only two types are provided, apply the Merge trait directly
1053   ($Type1:ty) => {
1054        $Type1
1055    };
1056
1057   // Base case: when only two types are provided, apply the Merge trait directly
1058   ($Type1:ty, $Type2:ty) => {
1059        <$Type1 as $crate::Merge<$Type2>>::MergeResult
1060    };
1061
1062    // Recursive case: when more than two types are provided
1063    ($Type1:ty, $Type2:ty, $( $rest:ty ),+) => {
1064        merge_tuple_list_type!(
1065            <$Type1 as $crate::Merge<$Type2>>::MergeResult,
1066            $( $rest ),+
1067        )
1068    };
1069}
1070
1071/*
1072
1073// Define trait and implement it for several primitive types.
1074trait PlusOne {
1075    fn plus_one(&mut self);
1076}
1077impl PlusOne for i32    { fn plus_one(&mut self) { *self += 1; } }
1078impl PlusOne for String { fn plus_one(&mut self) { self.push('1'); } }
1079
1080// Now we have to implement trait for an empty tuple,
1081// thus defining initial condition.
1082impl PlusOne for () {
1083    fn plus_one(&mut self) {}
1084}
1085
1086// Now we can implement trait for a non-empty tuple list,
1087// thus defining recursion and supporting tuple lists of arbitrary length.
1088impl<Head, Tail> PlusOne for (Head, Tail) where
1089    Head: PlusOne,
1090    Tail: PlusOne + TupleList,
1091{
1092    fn plus_one(&mut self) {
1093        self.0.plus_one();
1094        self.1.plus_one();
1095    }
1096}
1097
1098*/
1099
1100#[cfg(test)]
1101mod test {
1102    use core::marker::PhantomData;
1103
1104    #[cfg(feature = "alloc")]
1105    use ownedref::OwnedMutSlice;
1106    use tuple_list::{tuple_list, tuple_list_type};
1107
1108    use crate::{Map, MappingFunctor, Merge, type_eq};
1109
1110    #[test]
1111    // for type name tests
1112    fn test_type_eq_simple() {
1113        // test eq
1114        assert!(type_eq::<u64, u64>());
1115
1116        // test neq
1117        assert!(!type_eq::<u64, usize>());
1118    }
1119
1120    #[test]
1121    fn test_type_eq() {
1122        // An alias for equality testing
1123        type OwnedMutSliceAlias<'a> = OwnedMutSlice<'a, u8>;
1124
1125        // A function for lifetime testing
1126        #[expect(clippy::extra_unused_lifetimes)]
1127        fn test_lifetimes<'a, 'b>() {
1128            assert!(type_eq::<OwnedMutSlice<'a, u8>, OwnedMutSlice<'b, u8>>());
1129            assert!(type_eq::<OwnedMutSlice<'static, u8>, OwnedMutSlice<'a, u8>>());
1130            assert!(type_eq::<OwnedMutSlice<'a, u8>, OwnedMutSlice<'b, u8>>());
1131            assert!(type_eq::<OwnedMutSlice<'a, u8>, OwnedMutSlice<'static, u8>>());
1132            assert!(!type_eq::<OwnedMutSlice<'a, u8>, OwnedMutSlice<'b, i8>>());
1133        }
1134        assert!(type_eq::<OwnedMutSlice<u8>, OwnedMutSliceAlias>());
1135
1136        test_lifetimes();
1137        // test weirder lifetime things
1138        assert!(type_eq::<OwnedMutSlice<u8>, OwnedMutSlice<u8>>());
1139        assert!(!type_eq::<OwnedMutSlice<u8>, OwnedMutSlice<u32>>());
1140    }
1141
1142    #[test]
1143    fn test_mapper() {
1144        struct W<T>(T);
1145
1146        // PhantomData shows how to deal with mappers that have generics
1147        struct ExampleMapper<P>(PhantomData<P>);
1148
1149        impl<T, P> MappingFunctor<T> for ExampleMapper<P> {
1150            type Output = W<T>;
1151
1152            fn apply(&mut self, from: T) -> Self::Output {
1153                W(from)
1154            }
1155        }
1156
1157        struct A;
1158        struct B;
1159        struct C;
1160
1161        type OrigType = tuple_list_type!(A, B, C);
1162        type MappedType = map_tuple_list_type!(OrigType, ExampleMapper<usize>);
1163        let orig: OrigType = tuple_list!(A, B, C);
1164        let _mapped: MappedType = orig.map(ExampleMapper(PhantomData::<usize>));
1165    }
1166
1167    #[test]
1168    fn test_merge() {
1169        struct A;
1170        struct B;
1171        struct C;
1172        struct D;
1173        struct E;
1174
1175        type Lhs = tuple_list_type!(A, B, C);
1176        type Rhs = tuple_list_type!(D, E);
1177        type Merged = merge_tuple_list_type!(Lhs, Rhs);
1178        type IndividuallyMergedPre = merge_tuple_list_type!(
1179            tuple_list_type!(A),
1180            tuple_list_type!(B),
1181            tuple_list_type!(C),
1182            Rhs
1183        );
1184        type IndividuallyMergedPost =
1185            merge_tuple_list_type!(Lhs, tuple_list_type!(D), tuple_list_type!(E));
1186        type MergedCloned = merge_tuple_list_type!(Merged);
1187
1188        let lhs: Lhs = tuple_list!(A, B, C);
1189        let rhs: Rhs = tuple_list!(D, E);
1190        let merged: Merged = lhs.merge(rhs);
1191        let merged: IndividuallyMergedPre = merged;
1192        let merged: IndividuallyMergedPost = merged;
1193        #[allow(clippy::no_effect_underscore_binding)]
1194        let _merged: MergedCloned = merged;
1195    }
1196
1197    /// Function that tests the tuple macros
1198    #[test]
1199    #[cfg(feature = "std")]
1200    fn test_macros() {
1201        let mut t = tuple_list!(1, "a");
1202
1203        tuple_for_each!(f1, core::fmt::Display, t, |x| {
1204            println!("{x}");
1205        });
1206
1207        tuple_for_each_mut!(f2, core::fmt::Display, t, |x| {
1208            println!("{x}");
1209        });
1210    }
1211
1212    #[cfg(feature = "alloc")]
1213    mod get_all {
1214        use alloc::{
1215            borrow::Cow,
1216            string::{String, ToString as _},
1217        };
1218
1219        use tuple_list::{tuple_list, tuple_list_type};
1220
1221        use crate::{GetAll as _, Handle, Handled as _, MatchNameRef, Named};
1222
1223        #[derive(Debug, PartialEq)]
1224        struct MyHandled(String, Cow<'static, str>);
1225        impl Named for MyHandled {
1226            fn name(&self) -> &Cow<'static, str> {
1227                &self.1
1228            }
1229        }
1230
1231        impl MyHandled {
1232            fn new(name: &str) -> Self {
1233                Self(name.to_string(), Cow::Owned(name.to_string()))
1234            }
1235        }
1236
1237        #[expect(clippy::type_complexity)]
1238        fn get_tuple() -> (
1239            tuple_list_type!(MyHandled, MyHandled, MyHandled),
1240            (Handle<MyHandled>, Handle<MyHandled>, Handle<MyHandled>),
1241        ) {
1242            let a = MyHandled::new("a");
1243            let a_handle = a.handle();
1244            let b = MyHandled::new("b");
1245            let b_handle = b.handle();
1246            let c = MyHandled::new("c");
1247            let c_handle = c.handle();
1248            (tuple_list!(a, b, c), (a_handle, b_handle, c_handle))
1249        }
1250
1251        #[test]
1252        fn test_get_all_empty() {
1253            let (tuple, _handles) = get_tuple();
1254            #[expect(clippy::let_unit_value)]
1255            let recovered = tuple.get_all(tuple_list!());
1256            #[allow(clippy::unit_cmp)]
1257            // needs its own scope to make the clippy expect work
1258            {
1259                assert_eq!(recovered, ());
1260            }
1261        }
1262
1263        #[test]
1264        fn test_get_all_one() {
1265            let (tuple, handles) = get_tuple();
1266            let tuple_list!(a_rec) = tuple.get_all(tuple_list!(&handles.0));
1267            assert_eq!(a_rec, Some(&tuple.0));
1268        }
1269
1270        #[test]
1271        fn test_get_all_two() {
1272            let (tuple, handles) = get_tuple();
1273            let tuple_list!(a_rec, b_rec) = tuple.get_all(tuple_list!(&handles.0, &handles.1));
1274            assert_eq!(a_rec, Some(&tuple.0));
1275            assert_eq!(b_rec, Some(&tuple.1.0));
1276        }
1277
1278        #[test]
1279        fn test_get_all_all() {
1280            let (tuple, handles) = get_tuple();
1281            let tuple_list!(a_rec, b_rec, c_rec) =
1282                tuple.get_all(tuple_list!(&handles.0, &handles.1, &handles.2));
1283            assert_eq!(a_rec, Some(&tuple.0));
1284            assert_eq!(b_rec, Some(&tuple.1.0));
1285            assert_eq!(c_rec, Some(&tuple.1.1.0));
1286        }
1287
1288        #[test]
1289        fn test_get_all_reverse() {
1290            let (tuple, handles) = get_tuple();
1291            let tuple_list!(c_rec, b_rec, a_rec) =
1292                tuple.get_all(tuple_list!(&handles.2, &handles.1, &handles.0));
1293            assert_eq!(c_rec, Some(&tuple.1.1.0));
1294            assert_eq!(b_rec, Some(&tuple.1.0));
1295            assert_eq!(a_rec, Some(&tuple.0));
1296        }
1297
1298        #[test]
1299        fn test_get_all_mut_empty() {
1300            let mut tuple = get_tuple().0;
1301            #[expect(clippy::let_unit_value)]
1302            let recovered = tuple.get_all_mut(tuple_list!());
1303            #[allow(clippy::unit_cmp)]
1304            // needs its own scope to make the clippy expect work
1305            {
1306                assert_eq!(recovered, tuple_list!());
1307            }
1308        }
1309
1310        #[test]
1311        fn test_get_all_mut_one() {
1312            let (mut tuple, handles) = get_tuple();
1313            let recovered = tuple.get_all_mut(tuple_list!(&handles.0));
1314            let tuple_list!(a_rec) = recovered;
1315            a_rec.unwrap().0.push_str("_modified_a");
1316            assert_eq!(tuple.get(&handles.0).unwrap().0, "a_modified_a");
1317        }
1318
1319        #[test]
1320        fn test_get_all_mut_two() {
1321            let (mut tuple, handles) = get_tuple();
1322            let tuple_list!(a_rec, b_rec) = tuple.get_all_mut(tuple_list!(&handles.0, &handles.1));
1323            a_rec.unwrap().0.push_str("_modified_a");
1324            b_rec.unwrap().0.push_str("_modified_b");
1325            assert_eq!(tuple.get(&handles.0).unwrap().0, "a_modified_a");
1326            assert_eq!(tuple.get(&handles.1).unwrap().0, "b_modified_b");
1327        }
1328
1329        #[test]
1330        fn test_get_all_mut_all() {
1331            let (mut tuple, handles) = get_tuple();
1332            let tuple_list!(a_rec, b_rec, c_rec) =
1333                tuple.get_all_mut(tuple_list!(&handles.0, &handles.1, &handles.2));
1334            a_rec.unwrap().0.push_str("_modified_a");
1335            b_rec.unwrap().0.push_str("_modified_b");
1336            c_rec.unwrap().0.push_str("_modified_c");
1337            assert_eq!(tuple.get(&handles.0).unwrap().0, "a_modified_a");
1338            assert_eq!(tuple.get(&handles.1).unwrap().0, "b_modified_b");
1339            assert_eq!(tuple.get(&handles.2).unwrap().0, "c_modified_c");
1340        }
1341
1342        #[test]
1343        fn test_get_all_mut_reverse() {
1344            let (mut tuple, handles) = get_tuple();
1345            let tuple_list!(c_rec, b_rec, a_rec) =
1346                tuple.get_all_mut(tuple_list!(&handles.2, &handles.1, &handles.0));
1347            c_rec.unwrap().0.push_str("_modified_c");
1348            b_rec.unwrap().0.push_str("_modified_b");
1349            a_rec.unwrap().0.push_str("_modified_a");
1350            assert_eq!(tuple.get(&handles.0).unwrap().0, "a_modified_a");
1351            assert_eq!(tuple.get(&handles.1).unwrap().0, "b_modified_b");
1352            assert_eq!(tuple.get(&handles.2).unwrap().0, "c_modified_c");
1353        }
1354
1355        #[test]
1356        fn test_get_all_mut_unsafe() {
1357            let (mut tuple, handles) = get_tuple();
1358            let handle_1 = handles.0;
1359            let handle_1_clone = handle_1.clone();
1360
1361            // pass the same handle twice, get two mutable references to the same value
1362            // cannot pattern match to tuple_list, because it cannot deal with mut
1363            let tuple_list!(rec_1, rec_1_clone) =
1364                tuple.get_all_mut(tuple_list!(&handle_1, &handle_1_clone));
1365            assert!(rec_1.is_some());
1366            assert!(rec_1_clone.is_none());
1367        }
1368
1369        #[test]
1370        fn test_preserve_order() {
1371            let a = MyHandled::new("a");
1372            let a_handle = a.handle();
1373            let b = MyHandled::new("a"); // note: same name
1374            let b_handle = b.handle();
1375
1376            let mut tuple = tuple_list!(a, b);
1377
1378            // pass the same handle twice, get two mutable references to the same value
1379            // cannot pattern match to tuple_list, because it cannot deal with mut
1380            let tuple_list!(_rec_a, rec_b) = tuple.get_all_mut(tuple_list!(&a_handle, &b_handle));
1381
1382            rec_b.unwrap().0 = "b".to_string();
1383
1384            let tuple_list!(a, b) = tuple;
1385            assert_eq!(a.0, "a");
1386            assert_eq!(b.0, "b");
1387        }
1388    }
1389}