Coverage Report

Created: 2025-10-10 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tap-1.0.1/src/pipe.rs
Line
Count
Source
1
/*! # Universal Suffix Calls
2
3
This module provides a single trait, `Pipe`, which provides a number of methods
4
useful for placing functions in suffix position. The most common method, `pipe`,
5
forwards a value `T` into any function `T -> R`, returning `R`. The other
6
methods all apply some form of borrowing to the value before passing the borrow
7
into the piped function. These are of less value, but provided to maintain a
8
similar API to the `tap` module’s methods, and for convenience in the event that
9
you do have a use for them.
10
11
This module is as much of a [UFCS] method syntax that can be provided as a
12
library, rather than in the language grammar.
13
14
[UFCS]: https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax
15
!*/
16
17
use core::{
18
  borrow::{Borrow, BorrowMut},
19
  ops::{Deref, DerefMut},
20
};
21
22
/** Provides universal suffix-position call syntax for any function.
23
24
This trait provides methods that allow any closure or free function to be placed
25
as a suffix-position call, by writing them as
26
27
```rust
28
# use tap::pipe::Pipe;
29
# let receiver = 5;
30
fn not_a_method(x: i32) -> u8 { x as u8 }
31
receiver.pipe(not_a_method);
32
```
33
34
Piping into functions that take more than one argument still requires writing a
35
closure with ordinary function-call syntax. This is after all only a library,
36
not a syntax transformation:
37
38
```rust
39
use tap::pipe::Pipe;
40
fn add(x: i32, y: i32) -> i32 { x + y }
41
42
let out = 5.pipe(|x| add(x, 10));
43
assert_eq!(out, 15);
44
```
45
46
Like tapping, piping is useful for cases where you want to write a sequence of
47
processing steps without introducing many intermediate bindings, and your steps
48
contain functions which are not eligible for dot-call syntax.
49
50
The main difference between piping and tapping is that tapping always returns
51
the value that was passed into the tap, while piping forwards the value into the
52
effect function, and returns the output of evaluating the effect function with
53
the value. Piping is a transformation, not merely an inspection or modification.
54
**/
55
pub trait Pipe {
56
  /// Pipes by value. This is generally the method you want to use.
57
  ///
58
  /// # Examples
59
  ///
60
  /// ```rust
61
  /// use tap::pipe::Pipe;
62
  ///
63
  /// fn triple(x: i32) -> i64 {
64
  ///   x as i64 * 3
65
  /// }
66
  ///
67
  /// assert_eq!(
68
  ///   10.pipe(triple),
69
  ///   30,
70
  /// );
71
  /// ```
72
  #[inline(always)]
73
4.15M
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
4.15M
  where
75
4.15M
    Self: Sized,
76
4.15M
    R: Sized,
77
  {
78
4.15M
    func(self)
79
4.15M
  }
Unexecuted instantiation: <bitvec::ptr::span::BitSpanError<u8> as tap::pipe::Pipe>::pipe::<core::result::Result<&mut bitvec::slice::BitSlice<u8, bitvec::order::Msb0>, bitvec::ptr::span::BitSpanError<u8>>, core::result::Result<&mut bitvec::slice::BitSlice<u8, bitvec::order::Msb0>, bitvec::ptr::span::BitSpanError<u8>>::Err>
Unexecuted instantiation: <bitvec::ptr::span::BitSpanError<u8> as tap::pipe::Pipe>::pipe::<core::result::Result<&bitvec::slice::BitSlice<u8, bitvec::order::Msb0>, bitvec::ptr::span::BitSpanError<u8>>, core::result::Result<&bitvec::slice::BitSlice<u8, bitvec::order::Msb0>, bitvec::ptr::span::BitSpanError<u8>>::Err>
Unexecuted instantiation: <usize as tap::pipe::Pipe>::pipe::<bitvec::ptr::span::BitSpanError<u8>, bitvec::ptr::span::BitSpanError<u8>::TooLong>
Unexecuted instantiation: <usize as tap::pipe::Pipe>::pipe::<usize, <bitvec::slice::BitSlice<u8> as bitvec::field::BitField>::load_le<usize>::{closure#0}>
<usize as tap::pipe::Pipe>::pipe::<usize, <bitvec::slice::BitSlice<u8, bitvec::order::Msb0> as bitvec::field::BitField>::load_be<usize>::{closure#0}>
Line
Count
Source
73
105k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
105k
  where
75
105k
    Self: Sized,
76
105k
    R: Sized,
77
  {
78
105k
    func(self)
79
105k
  }
<u128 as tap::pipe::Pipe>::pipe::<u128, <bitvec::slice::BitSlice<u8, bitvec::order::Msb0> as bitvec::field::BitField>::load_be<u128>::{closure#0}>
Line
Count
Source
73
39.1k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
39.1k
  where
75
39.1k
    Self: Sized,
76
39.1k
    R: Sized,
77
  {
78
39.1k
    func(self)
79
39.1k
  }
<u128 as tap::pipe::Pipe>::pipe::<u128, <bitvec::slice::BitSlice<u8, bitvec::order::Msb0> as bitvec::field::BitField>::load_le<u128>::{closure#0}>
Line
Count
Source
73
2.83k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
2.83k
  where
75
2.83k
    Self: Sized,
76
2.83k
    R: Sized,
77
  {
78
2.83k
    func(self)
79
2.83k
  }
<u16 as tap::pipe::Pipe>::pipe::<u16, <bitvec::slice::BitSlice<u8, bitvec::order::Msb0> as bitvec::field::BitField>::load_be<u16>::{closure#0}>
Line
Count
Source
73
2.57k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
2.57k
  where
75
2.57k
    Self: Sized,
76
2.57k
    R: Sized,
77
  {
78
2.57k
    func(self)
79
2.57k
  }
Unexecuted instantiation: <wyz::comu::Address<wyz::comu::Const, u8> as tap::pipe::Pipe>::pipe::<&u8, <bitvec::domain::PartialElement<wyz::comu::Const, u8, bitvec::order::Lsb0>>::load_value::{closure#0}>
<wyz::comu::Address<wyz::comu::Const, u8> as tap::pipe::Pipe>::pipe::<&u8, <bitvec::domain::PartialElement<wyz::comu::Const, u8, bitvec::order::Msb0>>::load_value::{closure#0}>
Line
Count
Source
73
179k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
179k
  where
75
179k
    Self: Sized,
76
179k
    R: Sized,
77
  {
78
179k
    func(self)
79
179k
  }
<core::ptr::non_null::NonNull<core::cell::Cell<u8>> as tap::pipe::Pipe>::pipe::<wyz::comu::Address<wyz::comu::Frozen<wyz::comu::Mut>, core::cell::Cell<u8>>, <wyz::comu::Address<wyz::comu::Frozen<wyz::comu::Mut>, core::cell::Cell<u8>>>::new>
Line
Count
Source
73
35.6k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
35.6k
  where
75
35.6k
    Self: Sized,
76
35.6k
    R: Sized,
77
  {
78
35.6k
    func(self)
79
35.6k
  }
<core::ptr::non_null::NonNull<bitvec::access::BitSafeU8> as tap::pipe::Pipe>::pipe::<wyz::comu::Address<wyz::comu::Mut, bitvec::access::BitSafeU8>, <wyz::comu::Address<wyz::comu::Mut, bitvec::access::BitSafeU8>>::new>
Line
Count
Source
73
105k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
105k
  where
75
105k
    Self: Sized,
76
105k
    R: Sized,
77
  {
78
105k
    func(self)
79
105k
  }
<core::ptr::non_null::NonNull<u8> as tap::pipe::Pipe>::pipe::<wyz::comu::Address<wyz::comu::Mut, u8>, <wyz::comu::Address<wyz::comu::Mut, u8>>::new>
Line
Count
Source
73
536k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
536k
  where
75
536k
    Self: Sized,
76
536k
    R: Sized,
77
  {
78
536k
    func(self)
79
536k
  }
<core::ptr::non_null::NonNull<u8> as tap::pipe::Pipe>::pipe::<wyz::comu::Address<wyz::comu::Const, u8>, <wyz::comu::Address<wyz::comu::Const, u8>>::new>
Line
Count
Source
73
596k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
596k
  where
75
596k
    Self: Sized,
76
596k
    R: Sized,
77
  {
78
596k
    func(self)
79
596k
  }
<*mut core::cell::Cell<u8> as tap::pipe::Pipe>::pipe::<core::option::Option<core::ptr::non_null::NonNull<core::cell::Cell<u8>>>, <core::ptr::non_null::NonNull<core::cell::Cell<u8>>>::new>
Line
Count
Source
73
35.6k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
35.6k
  where
75
35.6k
    Self: Sized,
76
35.6k
    R: Sized,
77
  {
78
35.6k
    func(self)
79
35.6k
  }
<*mut bitvec::access::BitSafeU8 as tap::pipe::Pipe>::pipe::<*mut bitvec::access::BitSafeU8, <wyz::comu::Address<wyz::comu::Mut, bitvec::access::BitSafeU8>>::offset::{closure#0}>
Line
Count
Source
73
105k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
105k
  where
75
105k
    Self: Sized,
76
105k
    R: Sized,
77
  {
78
105k
    func(self)
79
105k
  }
<*mut bitvec::access::BitSafeU8 as tap::pipe::Pipe>::pipe::<core::option::Option<core::ptr::non_null::NonNull<bitvec::access::BitSafeU8>>, <core::ptr::non_null::NonNull<bitvec::access::BitSafeU8>>::new>
Line
Count
Source
73
105k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
105k
  where
75
105k
    Self: Sized,
76
105k
    R: Sized,
77
  {
78
105k
    func(self)
79
105k
  }
<*mut u8 as tap::pipe::Pipe>::pipe::<*mut u8, <wyz::comu::Address<wyz::comu::Mut, u8>>::cast<u8>::{closure#0}>
Line
Count
Source
73
230k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
230k
  where
75
230k
    Self: Sized,
76
230k
    R: Sized,
77
  {
78
230k
    func(self)
79
230k
  }
<*mut u8 as tap::pipe::Pipe>::pipe::<*mut u8, <wyz::comu::Address<wyz::comu::Const, u8>>::cast<u8>::{closure#0}>
Line
Count
Source
73
182k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
182k
  where
75
182k
    Self: Sized,
76
182k
    R: Sized,
77
  {
78
182k
    func(self)
79
182k
  }
Unexecuted instantiation: <*mut u8 as tap::pipe::Pipe>::pipe::<*mut u8, <wyz::comu::Address<wyz::comu::Mut, u8>>::wrapping_offset::{closure#0}>
<*mut u8 as tap::pipe::Pipe>::pipe::<*mut u8, <wyz::comu::Address<wyz::comu::Mut, u8>>::add::{closure#0}>
Line
Count
Source
73
196k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
196k
  where
75
196k
    Self: Sized,
76
196k
    R: Sized,
77
  {
78
196k
    func(self)
79
196k
  }
<*mut u8 as tap::pipe::Pipe>::pipe::<*mut u8, <wyz::comu::Address<wyz::comu::Mut, u8>>::offset::{closure#0}>
Line
Count
Source
73
110k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
110k
  where
75
110k
    Self: Sized,
76
110k
    R: Sized,
77
  {
78
110k
    func(self)
79
110k
  }
Unexecuted instantiation: <*mut u8 as tap::pipe::Pipe>::pipe::<*mut u8, <wyz::comu::Address<wyz::comu::Const, u8>>::wrapping_offset::{closure#0}>
<*mut u8 as tap::pipe::Pipe>::pipe::<*mut u8, <wyz::comu::Address<wyz::comu::Const, u8>>::add::{closure#0}>
Line
Count
Source
73
173k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
173k
  where
75
173k
    Self: Sized,
76
173k
    R: Sized,
77
  {
78
173k
    func(self)
79
173k
  }
<*mut u8 as tap::pipe::Pipe>::pipe::<*mut u8, <wyz::comu::Address<wyz::comu::Const, u8>>::offset::{closure#0}>
Line
Count
Source
73
240k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
240k
  where
75
240k
    Self: Sized,
76
240k
    R: Sized,
77
  {
78
240k
    func(self)
79
240k
  }
<*mut u8 as tap::pipe::Pipe>::pipe::<core::option::Option<core::ptr::non_null::NonNull<u8>>, <core::ptr::non_null::NonNull<u8>>::new>
Line
Count
Source
73
1.13M
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
1.13M
  where
75
1.13M
    Self: Sized,
76
1.13M
    R: Sized,
77
  {
78
1.13M
    func(self)
79
1.13M
  }
<*mut u8 as tap::pipe::Pipe>::pipe::<*mut core::cell::Cell<u8>, <wyz::comu::Address<wyz::comu::Frozen<wyz::comu::Mut>, u8>>::cast<core::cell::Cell<u8>>::{closure#0}>
Line
Count
Source
73
35.6k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
35.6k
  where
75
35.6k
    Self: Sized,
76
35.6k
    R: Sized,
77
  {
78
35.6k
    func(self)
79
35.6k
  }
80
81
  /// Borrows `self` and passes that borrow into the pipe function.
82
  ///
83
  /// # Examples
84
  ///
85
  /// ```rust
86
  /// use tap::pipe::Pipe;
87
  ///
88
  /// fn fold(v: &Vec<i32>) -> i32 {
89
  ///   v.iter().copied().sum()
90
  /// }
91
  /// let vec = vec![1, 2, 3, 4, 5];
92
  /// let sum = vec.pipe_ref(fold);
93
  /// assert_eq!(sum, 15);
94
  /// assert_eq!(vec.len(), 5);
95
  /// ```
96
  #[inline(always)]
97
  fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
98
  where
99
    R: 'a + Sized,
100
  {
101
    func(self)
102
  }
103
104
  /// Mutably borrows `self` and passes that borrow into the pipe function.
105
  ///
106
  /// # Examples
107
  ///
108
  /// ```rust
109
  /// use tap::pipe::Pipe;
110
  ///
111
  /// let mut vec = vec![false, true];
112
  /// let last = vec
113
  ///   .pipe_ref_mut(Vec::pop)
114
  ///   .pipe(Option::unwrap);
115
  /// assert!(last);
116
  /// ```
117
  ///
118
  /// Both of these functions are eligible for method-call syntax, and should
119
  /// not be piped. Writing out non-trivial examples for these is a lot of
120
  /// boilerplate.
121
  #[inline(always)]
122
  fn pipe_ref_mut<'a, R>(
123
    &'a mut self,
124
    func: impl FnOnce(&'a mut Self) -> R,
125
  ) -> R
126
  where
127
    R: 'a + Sized,
128
  {
129
    func(self)
130
  }
131
132
  /// Borrows `self`, then passes `self.borrow()` into the pipe function.
133
  ///
134
  /// # Examples
135
  ///
136
  /// ```rust
137
  /// use std::borrow::Cow;
138
  /// use tap::pipe::Pipe;
139
  ///
140
  /// let len = Cow::<'static, str>::from("hello, world")
141
  ///   .pipe_borrow(str::len);
142
  /// assert_eq!(len, 12);
143
  /// ```
144
  #[inline(always)]
145
  fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
146
  where
147
    Self: Borrow<B>,
148
    B: 'a + ?Sized,
149
    R: 'a + Sized,
150
  {
151
    func(Borrow::<B>::borrow(self))
152
  }
153
154
  /// Mutably borrows `self`, then passes `self.borrow_mut()` into the pipe
155
  /// function.
156
  ///
157
  /// ```rust
158
  /// use tap::pipe::Pipe;
159
  ///
160
  /// let mut txt = "hello, world".to_string();
161
  /// let ptr = txt
162
  ///   .pipe_borrow_mut(str::as_mut_ptr);
163
  /// ```
164
  ///
165
  /// This is a very contrived example, but the `BorrowMut` trait has almost
166
  /// no implementors in the standard library, and of the implementations
167
  /// available, there are almost no methods that fit this API.
168
  #[inline(always)]
169
  fn pipe_borrow_mut<'a, B, R>(
170
    &'a mut self,
171
    func: impl FnOnce(&'a mut B) -> R,
172
  ) -> R
173
  where
174
    Self: BorrowMut<B>,
175
    B: 'a + ?Sized,
176
    R: 'a + Sized,
177
  {
178
    func(BorrowMut::<B>::borrow_mut(self))
179
  }
180
181
  /// Borrows `self`, then passes `self.as_ref()` into the pipe function.
182
  #[inline(always)]
183
  fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
184
  where
185
    Self: AsRef<U>,
186
    U: 'a + ?Sized,
187
    R: 'a + Sized,
188
  {
189
    func(AsRef::<U>::as_ref(self))
190
  }
191
192
  /// Mutably borrows `self`, then passes `self.as_mut()` into the pipe
193
  /// function.
194
  #[inline(always)]
195
  fn pipe_as_mut<'a, U, R>(
196
    &'a mut self,
197
    func: impl FnOnce(&'a mut U) -> R,
198
  ) -> R
199
  where
200
    Self: AsMut<U>,
201
    U: 'a + ?Sized,
202
    R: 'a + Sized,
203
  {
204
    func(AsMut::<U>::as_mut(self))
205
  }
206
207
  /// Borrows `self`, then passes `self.deref()` into the pipe function.
208
  #[inline(always)]
209
  fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
210
  where
211
    Self: Deref<Target = T>,
212
    T: 'a + ?Sized,
213
    R: 'a + Sized,
214
  {
215
    func(Deref::deref(self))
216
  }
217
218
  /// Mutably borrows `self`, then passes `self.deref_mut()` into the pipe
219
  /// function.
220
  #[inline(always)]
221
  fn pipe_deref_mut<'a, T, R>(
222
    &'a mut self,
223
    func: impl FnOnce(&'a mut T) -> R,
224
  ) -> R
225
  where
226
    Self: DerefMut + Deref<Target = T>,
227
    T: 'a + ?Sized,
228
    R: 'a + Sized,
229
  {
230
    func(DerefMut::deref_mut(self))
231
  }
232
}
233
234
impl<T> Pipe for T where T: ?Sized {}