rspace_traits/ops/
apply.rs

1/*
2    Appellation: apply <module>
3    Created At: 2025.12.24:17:20:29
4    Contrib: @FL03
5*/
6/// [`Apply`] defines an interface for objects capable of _applying_ the given function onto
7/// itself or its elements to produce some output.
8pub trait Apply<Rhs> {
9    type Output;
10
11    fn apply(&self, rhs: Rhs) -> Self::Output;
12}
13/// The [`ApplyOnce`] trait defines an interface for objects capable of consuming themselves
14/// to apply the given function onto themselves or their elements to produce some output.
15pub trait ApplyOnce<Rhs> {
16    type Output;
17
18    fn apply_once(self, rhs: Rhs) -> Self::Output;
19}
20/// The [`ApplyMut`] trait defines an interface for objects capable of mutably borrowing themselves
21/// to apply the given function onto themselves or their elements to produce some output.
22pub trait ApplyMut<Rhs> {
23    type Output;
24
25    fn apply_mut(&mut self, rhs: Rhs) -> Self::Output;
26}
27
28pub trait TryApply<Rhs> {
29    type Output;
30    type Error;
31
32    fn try_apply(&self, rhs: Rhs) -> Result<Self::Output, Self::Error>;
33}
34
35pub trait TryApplyOnce<Rhs> {
36    type Output;
37    type Error;
38
39    fn try_apply_once(self, rhs: Rhs) -> Result<Self::Output, Self::Error>;
40}
41
42pub trait TryApplyMut<Rhs> {
43    type Output;
44    type Error;
45
46    fn try_apply_mut(&mut self, rhs: Rhs) -> Result<Self::Output, Self::Error>;
47}
48
49/*
50 ************* Implementations *************
51*/
52impl<A, X, Y> TryApply<X> for A
53where
54    A: Apply<X, Output = Y>,
55{
56    type Output = A::Output;
57    type Error = core::convert::Infallible;
58
59    fn try_apply(&self, rhs: X) -> Result<Self::Output, Self::Error> {
60        Ok(self.apply(rhs))
61    }
62}
63
64impl<A, X, Y> TryApplyOnce<X> for A
65where
66    A: ApplyOnce<X, Output = Y>,
67{
68    type Output = A::Output;
69    type Error = core::convert::Infallible;
70
71    fn try_apply_once(self, rhs: X) -> Result<Self::Output, Self::Error> {
72        Ok(self.apply_once(rhs))
73    }
74}
75
76impl<A, X, Y> TryApplyMut<X> for A
77where
78    A: ApplyMut<X, Output = Y>,
79{
80    type Output = A::Output;
81    type Error = core::convert::Infallible;
82
83    fn try_apply_mut(&mut self, rhs: X) -> Result<Self::Output, Self::Error> {
84        Ok(self.apply_mut(rhs))
85    }
86}
87
88impl<U, V, F> ApplyOnce<F> for Option<U>
89where
90    F: FnOnce(U) -> V,
91{
92    type Output = Option<V>;
93
94    fn apply_once(self, rhs: F) -> Self::Output {
95        self.map(rhs)
96    }
97}
98
99impl<U, V, F> Apply<F> for Option<U>
100where
101    F: Fn(&U) -> V,
102{
103    type Output = Option<V>;
104
105    fn apply(&self, rhs: F) -> Self::Output {
106        self.as_ref().map(rhs)
107    }
108}
109
110impl<U, V, F> ApplyMut<F> for Option<U>
111where
112    F: FnMut(&mut U) -> V,
113{
114    type Output = Option<V>;
115
116    fn apply_mut(&mut self, rhs: F) -> Self::Output {
117        self.as_mut().map(rhs)
118    }
119}
120
121impl<const N: usize, U, V, F> Apply<F> for [U; N]
122where
123    F: Fn(&U) -> V,
124{
125    type Output = [V; N];
126
127    fn apply(&self, rhs: F) -> Self::Output {
128        core::array::from_fn(|i| rhs(&self[i]))
129    }
130}
131
132#[cfg(all(feature = "alloc", feature = "nightly"))]
133mod impl_alloc {
134    use super::Apply;
135    use alloc::allocator::Allocator;
136    use alloc::boxed::Box;
137    use alloc::vec::Vec;
138
139    impl<U, V, F, A> Apply<F> for Box<U, A>
140    where
141        A: Allocator,
142        F: Fn(&U) -> V,
143    {
144        type Output = Box<V>;
145
146        fn apply(&self, rhs: F) -> Self::Output {
147            Box::new(rhs(self.as_ref()))
148        }
149    }
150
151    impl<U, V, F, A> Apply<F> for Vec<U, A>
152    where
153        A: Allocator,
154        F: Fn(&U) -> V,
155    {
156        type Output = Vec<V, A>;
157
158        fn apply(&self, rhs: F) -> Self::Output {
159            self.iter().map(rhs).collect()
160        }
161    }
162}
163#[cfg(all(feature = "alloc", not(feature = "nightly")))]
164mod impl_alloc {
165    use super::Apply;
166    use alloc::boxed::Box;
167    use alloc::vec::Vec;
168
169    impl<U, V, F> Apply<F> for Box<U>
170    where
171        F: Fn(&U) -> V,
172    {
173        type Output = Box<V>;
174
175        fn apply(&self, rhs: F) -> Self::Output {
176            Box::new(rhs(self.as_ref()))
177        }
178    }
179
180    impl<U, V, F> Apply<F> for Vec<U>
181    where
182        F: Fn(&U) -> V,
183    {
184        type Output = Vec<V>;
185
186        fn apply(&self, rhs: F) -> Self::Output {
187            self.iter().map(rhs).collect()
188        }
189    }
190}