1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use std::fmt::Debug;

/// Closure strictly separating the captured data from the function, and hence, having two components:
///
/// * `Capture` is any captured data,
/// * `fn(&Capture, In) -> &Out` is the transformation.
///
/// It represents the transformation `In -> &Out`.
///
/// Note that, unlike trait objects of fn-traits, `Capture` auto-implements `Clone` given that captured data is cloneable.
///
/// **Instead of `ClosureRef`; this closure variant is particularly useful when we capture the data by value and return a reference.**
///
/// # Example
///
/// ```rust
/// use orx_closure::Capture;
///
/// struct Person { name: String }
/// let people = [Person { name: "john".to_string() }, Person { name: "doe".to_string() }];
/// // name_of_person_with_id: ClosureRef<[Person; 2], usize, str>
/// let name_of_person_with_id =
///     Capture(people).fun_ref(|ppl, id: usize| ppl[id].name.as_str());
///
/// assert_eq!("john", name_of_person_with_id.call(0));
///
/// // alternatively
/// let fun = name_of_person_with_id.as_fn();
/// assert_eq!("doe", fun(1));
/// ```
#[derive(Clone)]
pub struct ClosureRef<Capture, In, Out: ?Sized> {
    capture: Capture,
    fun: fn(&Capture, In) -> &Out,
}

impl<Capture: Debug, In, Out: ?Sized> Debug for ClosureRef<Capture, In, Out> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ClosureRef")
            .field("capture", &self.capture)
            .finish()
    }
}

impl<Capture, In, Out: ?Sized> ClosureRef<Capture, In, Out> {
    pub(super) fn new(capture: Capture, fun: fn(&Capture, In) -> &Out) -> Self {
        Self { capture, fun }
    }

    /// Calls the closure with the given `input`.
    ///
    /// # Example
    ///
    /// ```rust
    /// use orx_closure::Capture;
    ///
    /// struct Person { name: String }
    /// let people = [Person { name: "john".to_string() }, Person { name: "doe".to_string() }];
    /// // name_of_person_with_id: ClosureRef<[Person; 2], usize, str>
    /// let name_of_person_with_id =
    ///     Capture(people).fun_ref(|ppl, id: usize| ppl[id].name.as_str());
    ///
    /// assert_eq!("john", name_of_person_with_id.call(0));
    /// ```
    #[inline(always)]
    pub fn call(&self, input: In) -> &Out {
        (self.fun)(&self.capture, input)
    }

    /// Consumes the closure and returns back the captured data.
    ///
    /// ```rust
    /// use orx_closure::Capture;
    ///
    /// struct ExpensiveData(Vec<i32>);
    ///
    /// let data = ExpensiveData(vec![10, 11, 12]);
    ///
    /// let get_number = Capture(data).fun_ref(|data, i| &data.0[i]);
    ///
    /// assert_eq!(&10, get_number.call(0));
    /// assert_eq!(&12, get_number.call(2));
    ///
    /// let _data: ExpensiveData = get_number.into_captured_data();
    /// ```
    pub fn into_captured_data(self) -> Capture {
        self.capture
    }

    /// Returns the closure as an `impl Fn(In) -> &Out` struct, allowing the convenience
    ///
    /// * to avoid the `call` method,
    /// * or pass the closure to functions accepting a function generic over the `Fn`.
    ///
    /// ```rust
    /// use orx_closure::Capture;
    ///
    /// struct Person { name: String }
    /// let people = [Person { name: "john".to_string() }, Person { name: "doe".to_string() }];
    /// // name_of_person_with_id: ClosureRef<[Person; 2], usize, str>
    /// let name_of_person_with_id =
    ///     Capture(people).fun_ref(|ppl, id: usize| ppl[id].name.as_str());
    ///
    /// let fun = name_of_person_with_id.as_fn();
    /// assert_eq!("doe", fun(1));
    /// ```
    pub fn as_fn<'a>(&'a self) -> impl Fn(In) -> &'a Out {
        move |x| self.call(x)
    }
}