pipe_trait/
lib.rs

1#![doc = include_str!("doc.md")]
2#![no_std]
3use core::{
4    borrow::{Borrow, BorrowMut},
5    ops::{Deref, DerefMut},
6};
7
8/// All sized types implement this trait.
9pub trait Pipe {
10    /// Apply `f` to `self`.
11    ///
12    /// ```
13    /// # #[derive(Debug, PartialEq, Eq)]
14    /// # struct Foo(i32);
15    /// # fn double(x: i32) -> i32 { x * 2 }
16    /// # use pipe_trait::*;
17    /// assert_eq!(
18    ///     12.pipe(double).pipe(Foo),
19    ///     Foo(double(12)),
20    /// )
21    /// ```
22    #[inline]
23    fn pipe<Return, Function>(self, f: Function) -> Return
24    where
25        Self: Sized,
26        Function: FnOnce(Self) -> Return,
27    {
28        f(self)
29    }
30
31    /// Apply `f` to `&self`.
32    ///
33    /// ```
34    /// # use pipe_trait::*;
35    /// #[derive(Debug, PartialEq, Eq)]
36    /// struct Foo(i32);
37    /// let a = Foo(12);
38    /// let b = a
39    ///     .pipe_ref(|a| a.0) // a is not moved
40    ///     .pipe(Foo);
41    /// assert_eq!(a, b); // a is used again
42    /// ```
43    #[inline]
44    fn pipe_ref<'a, Return, Function>(&'a self, f: Function) -> Return
45    where
46        Function: FnOnce(&'a Self) -> Return,
47    {
48        f(self)
49    }
50
51    /// Apply `f` to `&mut self`.
52    ///
53    /// ```
54    /// # use pipe_trait::*;
55    /// #[derive(Debug, PartialEq, Eq)]
56    /// struct Foo(i32, i32);
57    /// let mut a = Foo(0, 0);
58    /// a.pipe_mut(|a| a.0 = 12);
59    /// a.pipe_mut(|a| a.1 = 34);
60    /// assert_eq!(a, Foo(12, 34));
61    /// ```
62    #[inline]
63    fn pipe_mut<'a, Return, Function>(&'a mut self, f: Function) -> Return
64    where
65        Function: FnOnce(&'a mut Self) -> Return,
66    {
67        f(self)
68    }
69
70    /// Apply `f` to `&self` where `f` takes a single parameter of type `Param`
71    /// and `Self` implements trait [`AsRef<Param>`].
72    ///
73    /// ```
74    /// # use pipe_trait::*;
75    /// fn uppercase(x: &str) -> String {
76    ///   x.to_uppercase()
77    /// }
78    /// let x: String = "abc".to_string();
79    /// let y: String = x.pipe_as_ref(uppercase);
80    /// assert_eq!(y, "ABC");
81    /// ```
82    #[inline]
83    fn pipe_as_ref<'a, Param, Return, Function>(&'a self, f: Function) -> Return
84    where
85        Self: AsRef<Param>,
86        Param: ?Sized + 'a,
87        Function: FnOnce(&'a Param) -> Return,
88    {
89        f(self.as_ref())
90    }
91
92    /// Apply `f` to `&mut self` where `f` takes a single parameter of type `Param`
93    /// and `Self` implements trait [`AsMut<Param>`].
94    ///
95    /// ```
96    /// # use pipe_trait::*;
97    /// fn modify(target: &mut [i32]) {
98    ///   target[0] = 123;
99    /// }
100    /// let mut vec: Vec<i32> = vec![0, 1, 2, 3];
101    /// vec.pipe_as_mut(modify);
102    /// assert_eq!(vec, vec![123, 1, 2, 3]);
103    /// ```
104    #[inline]
105    fn pipe_as_mut<'a, Param, Return, Function>(&'a mut self, f: Function) -> Return
106    where
107        Self: AsMut<Param>,
108        Param: ?Sized + 'a,
109        Function: FnOnce(&'a mut Param) -> Return,
110    {
111        f(self.as_mut())
112    }
113
114    /// Apply `f` to `&self` where `f` takes a single parameter of type `Param`
115    /// and `Self` implements trait `Deref<Target = Param>`.
116    ///
117    /// ```
118    /// # use pipe_trait::*;
119    /// fn uppercase(x: &str) -> String {
120    ///   x.to_uppercase()
121    /// }
122    /// let x: String = "abc".to_string();
123    /// let y: String = x.pipe_deref(uppercase);
124    /// assert_eq!(y, "ABC");
125    /// ```
126    #[inline]
127    fn pipe_deref<'a, Param, Return, Function>(&'a self, f: Function) -> Return
128    where
129        Self: Deref<Target = Param>,
130        Param: ?Sized + 'a,
131        Function: FnOnce(&'a Param) -> Return,
132    {
133        f(self)
134    }
135
136    /// Apply `f` to `&mut self` where `f` takes a single parameter of type `Param`
137    /// and `Self` implements trait [`DerefMut<Target = Param>`].
138    ///
139    /// ```
140    /// # use pipe_trait::*;
141    /// fn modify(target: &mut [i32]) {
142    ///   target[0] = 123;
143    /// }
144    /// let mut vec: Vec<i32> = vec![0, 1, 2, 3];
145    /// vec.pipe_deref_mut(modify);
146    /// assert_eq!(vec, vec![123, 1, 2, 3]);
147    /// ```
148    #[inline]
149    fn pipe_deref_mut<'a, Param, Return, Function>(&'a mut self, f: Function) -> Return
150    where
151        Self: DerefMut<Target = Param>,
152        Param: ?Sized + 'a,
153        Function: FnOnce(&'a mut Param) -> Return,
154    {
155        f(self)
156    }
157
158    /// Apply `f` to `&self` where `f` takes a single parameter of type `Param`
159    /// and `Self` implements trait [`Borrow<Param>`].
160    ///
161    /// ```
162    /// # use pipe_trait::*;
163    /// fn uppercase(x: &str) -> String {
164    ///   x.to_uppercase()
165    /// }
166    /// let x: String = "abc".to_string();
167    /// let y: String = x.pipe_borrow(uppercase);
168    /// assert_eq!(y, "ABC");
169    /// ```
170    #[inline]
171    fn pipe_borrow<'a, Param, Return, Function>(&'a self, f: Function) -> Return
172    where
173        Self: Borrow<Param>,
174        Param: ?Sized + 'a,
175        Function: FnOnce(&'a Param) -> Return,
176    {
177        f(self.borrow())
178    }
179
180    /// Apply `f` to `&mut self` where `f` takes a single parameter of type `Param`
181    /// and `Self` implements trait [`BorrowMut<Param>`].
182    ///
183    /// ```
184    /// # use pipe_trait::*;
185    /// fn modify(target: &mut [i32]) {
186    ///   target[0] = 123;
187    /// }
188    /// let mut vec: Vec<i32> = vec![0, 1, 2, 3];
189    /// vec.pipe_borrow_mut(modify);
190    /// assert_eq!(vec, vec![123, 1, 2, 3]);
191    /// ```
192    #[inline]
193    fn pipe_borrow_mut<'a, Param, Return, Function>(&'a mut self, f: Function) -> Return
194    where
195        Self: BorrowMut<Param>,
196        Param: ?Sized + 'a,
197        Function: FnOnce(&'a mut Param) -> Return,
198    {
199        f(self.borrow_mut())
200    }
201}
202
203impl<X> Pipe for X {}
204
205#[cfg(test)]
206mod tests;