1#![doc = include_str!("../README.md")]
3#![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_numeric_casts,
11 unused_extern_crates,
12 unused_import_braces,
13 unused_qualifications,
14 ))]
16#![cfg_attr(test, deny(
17 missing_debug_implementations,
18 missing_docs,
19 trivial_numeric_casts,
21 unused_extern_crates,
22 unused_import_braces,
23 unused_qualifications,
24 unused_must_use,
25 ))]
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#[must_use]
75pub fn type_eq<T: ?Sized, U: ?Sized>() -> bool {
76 typeid::of::<T>() == typeid::of::<U>()
77}
78
79pub trait SplitBorrow<'a> {
81 type SplitBorrowResult;
83 type SplitBorrowMutResult;
85
86 fn borrow(&'a self) -> Self::SplitBorrowResult;
88 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#[cfg(feature = "alloc")]
121pub trait IntoVec<T> {
122 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 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
145pub trait HasConstLen {
147 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
162pub trait MatchFirstType {
164 fn match_first_type<T: 'static>(&self) -> Option<&T>;
166 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
201pub trait ExtractFirstRefType {
203 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
248pub trait ExtractFirstRefMutType {
250 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
279pub trait SplitBorrowExtractFirstType<'a> {
281 type SplitBorrowResult: ExtractFirstRefType;
283 type SplitBorrowMutResult: ExtractFirstRefType + ExtractFirstRefMutType;
285
286 fn borrow(&'a self) -> Self::SplitBorrowResult;
288 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
318pub trait MatchType {
320 fn match_type<T: 'static, FN: FnMut(&T)>(&self, f: &mut FN);
322 fn match_type_mut<T: 'static, FN: FnMut(&mut T)>(&mut self, f: &mut FN);
324}
325
326impl MatchType for () {
327 fn match_type<T: 'static, FN: FnMut(&T)>(&self, _: &mut FN) {}
329 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 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 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")]
356pub trait NamedTuple {
358 fn name(&self, index: usize) -> Option<&Cow<'static, str>>;
360
361 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#[cfg(feature = "alloc")]
400pub trait MatchName {
401 #[deprecated = "Use `.handle` and either `.get` (fallible access) or `[]` (infallible access) instead"]
403 fn match_name<T>(&self, name: &str) -> Option<&T>;
404 #[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#[cfg(feature = "alloc")]
446pub trait Handled: Named {
447 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#[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 #[must_use]
472 pub fn new(name: Cow<'static, str>) -> Self {
473 Self {
474 name,
475 phantom: PhantomData,
476 }
477 }
478
479 #[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#[cfg(feature = "alloc")]
511pub trait MatchNameRef {
512 fn get<T>(&self, rf: &Handle<T>) -> Option<&T>;
514
515 fn get_mut<T>(&mut self, rf: &Handle<T>) -> Option<&mut T>;
517}
518
519#[cfg(feature = "alloc")]
528pub trait GetAll<HandleTuple> {
529 type GetAllResult<'a>
531 where
532 Self: 'a;
533
534 type GetAllMutResult<'a>
536 where
537 Self: 'a;
538
539 fn get_all(&self, handles: HandleTuple) -> Self::GetAllResult<'_>;
541
542 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
581pub trait InnerBorrowMut {
583 type Borrowed<'a>
585 where
586 Self: 'a;
587
588 fn inner_borrow_mut(&mut self) -> Self::Borrowed<'_>;
590}
591
592#[cfg(feature = "alloc")]
593mod seal {
594 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#[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
833pub trait Prepend<T> {
835 #[must_use]
837 fn prepend(self, value: T) -> (T, Self);
838}
839
840impl<Tail, T> Prepend<T> for Tail {
842 fn prepend(self, value: T) -> (T, Self) {
843 (value, self)
844 }
845}
846
847pub trait Append<T>
849where
850 Self: Sized,
851{
852 #[must_use]
854 fn append(self, value: T) -> (Self, T);
855}
856
857impl<Head, T> Append<T> for Head {
859 fn append(self, value: T) -> (Self, T) {
860 (self, value)
861 }
862}
863
864pub trait Merge<T> {
866 type MergeResult;
868
869 #[must_use]
871 fn merge(self, value: T) -> Self::MergeResult;
872}
873
874impl<T> Merge<T> for () {
876 type MergeResult = T;
877
878 fn merge(self, value: T) -> Self::MergeResult {
879 value
880 }
881}
882
883impl<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
896pub trait MappingFunctor<T> {
898 type Output;
900
901 fn apply(&mut self, from: T) -> Self::Output;
903}
904
905pub trait Map<M> {
907 type MapResult;
909
910 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#[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)] 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#[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)] 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#[macro_export]
1025macro_rules! map_tuple_list_type {
1026 ($Tuple:ty, $Mapper:ty) => {
1027 <$Tuple as $crate::Map<$Mapper>>::MapResult
1028 };
1029}
1030
1031#[macro_export]
1051macro_rules! merge_tuple_list_type {
1052 ($Type1:ty) => {
1054 $Type1
1055 };
1056
1057 ($Type1:ty, $Type2:ty) => {
1059 <$Type1 as $crate::Merge<$Type2>>::MergeResult
1060 };
1061
1062 ($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#[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 fn test_type_eq_simple() {
1113 assert!(type_eq::<u64, u64>());
1115
1116 assert!(!type_eq::<u64, usize>());
1118 }
1119
1120 #[test]
1121 fn test_type_eq() {
1122 type OwnedMutSliceAlias<'a> = OwnedMutSlice<'a, u8>;
1124
1125 #[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 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 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 #[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 {
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 {
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 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"); let b_handle = b.handle();
1375
1376 let mut tuple = tuple_list!(a, b);
1377
1378 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}