fn_traits/fns/
compose_fn.rs1use crate::{Fn, FnMut, FnOnce};
2
3#[derive(Clone, Copy, Default)]
5pub struct ComposeFn<F, G> {
6 lhs: F,
7 rhs: G,
8}
9
10impl<Args, F, G> FnOnce<Args> for ComposeFn<F, G>
11where
12 F: FnOnce<(G::Output,)>,
13 G: FnOnce<Args>,
14{
15 type Output = F::Output;
16
17 fn call_once(self, args: Args) -> Self::Output {
18 self.lhs.call_once((self.rhs.call_once(args),))
19 }
20}
21
22impl<Args, F, G> FnMut<Args> for ComposeFn<F, G>
23where
24 F: FnMut<(G::Output,)>,
25 G: FnMut<Args>,
26{
27 type Output = F::Output;
28
29 fn call_mut(&mut self, args: Args) -> Self::Output {
30 self.lhs.call_mut((self.rhs.call_mut(args),))
31 }
32}
33
34impl<Args, F, G> Fn<Args> for ComposeFn<F, G>
35where
36 F: Fn<(G::Output,)>,
37 G: Fn<Args>,
38{
39 type Output = F::Output;
40
41 fn call(&self, args: Args) -> Self::Output {
42 self.lhs.call((self.rhs.call(args),))
43 }
44}
45
46pub fn compose<F, G>(lhs: F, rhs: G) -> ComposeFn<F, G> {
49 ComposeFn { lhs, rhs }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::super::tests::{
55 into_std_fn, into_std_fn_2, into_std_fn_mut, into_std_fn_mut_2, into_std_fn_once, into_std_fn_once_2,
56 };
57 use super::ComposeFn;
58 use crate::fns::option_some_fn::OptionSomeFn;
59
60 #[test]
61 fn test_compose() {
62 let f = super::compose(|x: u32| x + 1, |x: u32| x * 2);
63
64 assert_eq!(into_std_fn_once(Clone::clone(&f))(2), 5);
65 assert_eq!(into_std_fn_mut(Clone::clone(&f))(2), 5);
66 assert_eq!(into_std_fn(Clone::clone(&f))(2), 5);
67
68 let g = super::compose(|x: u32| x + 1, |x: u32, y: u32| x * y);
69
70 assert_eq!(into_std_fn_once_2(Clone::clone(&g))(2, 3), 7);
71 assert_eq!(into_std_fn_mut_2(Clone::clone(&g))(2, 3), 7);
72 assert_eq!(into_std_fn_2(Clone::clone(&g))(2, 3), 7);
73 }
74
75 #[test]
76 fn test_compose_default() {
77 let f = ComposeFn::<OptionSomeFn, OptionSomeFn>::default();
78
79 assert_eq!(into_std_fn_once(Clone::clone(&f))(2), Some(Some(2)));
80 assert_eq!(into_std_fn_mut(Clone::clone(&f))(2), Some(Some(2)));
81 assert_eq!(into_std_fn(Clone::clone(&f))(2), Some(Some(2)));
82 }
83}