Coverage Report

Created: 2026-11-12 07:09

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.14M
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
4.14M
  where
75
4.14M
    Self: Sized,
76
4.14M
    R: Sized,
77
  {
78
4.14M
    func(self)
79
4.14M
  }
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
104k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
104k
  where
75
104k
    Self: Sized,
76
104k
    R: Sized,
77
  {
78
104k
    func(self)
79
104k
  }
<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.0k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
39.0k
  where
75
39.0k
    Self: Sized,
76
39.0k
    R: Sized,
77
  {
78
39.0k
    func(self)
79
39.0k
  }
<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
4.01k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
4.01k
  where
75
4.01k
    Self: Sized,
76
4.01k
    R: Sized,
77
  {
78
4.01k
    func(self)
79
4.01k
  }
<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
3.61k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
3.61k
  where
75
3.61k
    Self: Sized,
76
3.61k
    R: Sized,
77
  {
78
3.61k
    func(self)
79
3.61k
  }
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
181k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
181k
  where
75
181k
    Self: Sized,
76
181k
    R: Sized,
77
  {
78
181k
    func(self)
79
181k
  }
<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
33.0k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
33.0k
  where
75
33.0k
    Self: Sized,
76
33.0k
    R: Sized,
77
  {
78
33.0k
    func(self)
79
33.0k
  }
<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
104k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
104k
  where
75
104k
    Self: Sized,
76
104k
    R: Sized,
77
  {
78
104k
    func(self)
79
104k
  }
<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
531k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
531k
  where
75
531k
    Self: Sized,
76
531k
    R: Sized,
77
  {
78
531k
    func(self)
79
531k
  }
<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
600k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
600k
  where
75
600k
    Self: Sized,
76
600k
    R: Sized,
77
  {
78
600k
    func(self)
79
600k
  }
<*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
33.0k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
33.0k
  where
75
33.0k
    Self: Sized,
76
33.0k
    R: Sized,
77
  {
78
33.0k
    func(self)
79
33.0k
  }
<*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
104k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
104k
  where
75
104k
    Self: Sized,
76
104k
    R: Sized,
77
  {
78
104k
    func(self)
79
104k
  }
<*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
104k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
104k
  where
75
104k
    Self: Sized,
76
104k
    R: Sized,
77
  {
78
104k
    func(self)
79
104k
  }
<*mut u8 as tap::pipe::Pipe>::pipe::<*mut u8, <wyz::comu::Address<wyz::comu::Mut, u8>>::cast<u8>::{closure#0}>
Line
Count
Source
73
227k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
227k
  where
75
227k
    Self: Sized,
76
227k
    R: Sized,
77
  {
78
227k
    func(self)
79
227k
  }
<*mut u8 as tap::pipe::Pipe>::pipe::<*mut u8, <wyz::comu::Address<wyz::comu::Const, u8>>::cast<u8>::{closure#0}>
Line
Count
Source
73
184k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
184k
  where
75
184k
    Self: Sized,
76
184k
    R: Sized,
77
  {
78
184k
    func(self)
79
184k
  }
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
195k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
195k
  where
75
195k
    Self: Sized,
76
195k
    R: Sized,
77
  {
78
195k
    func(self)
79
195k
  }
<*mut u8 as tap::pipe::Pipe>::pipe::<*mut u8, <wyz::comu::Address<wyz::comu::Mut, u8>>::offset::{closure#0}>
Line
Count
Source
73
108k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
108k
  where
75
108k
    Self: Sized,
76
108k
    R: Sized,
77
  {
78
108k
    func(self)
79
108k
  }
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
174k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
174k
  where
75
174k
    Self: Sized,
76
174k
    R: Sized,
77
  {
78
174k
    func(self)
79
174k
  }
<*mut u8 as tap::pipe::Pipe>::pipe::<*mut u8, <wyz::comu::Address<wyz::comu::Const, u8>>::offset::{closure#0}>
Line
Count
Source
73
241k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
241k
  where
75
241k
    Self: Sized,
76
241k
    R: Sized,
77
  {
78
241k
    func(self)
79
241k
  }
<*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
33.0k
  fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
74
33.0k
  where
75
33.0k
    Self: Sized,
76
33.0k
    R: Sized,
77
  {
78
33.0k
    func(self)
79
33.0k
  }
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 {}