1/*! # Universal Suffix Calls23This module provides a single trait, `Pipe`, which provides a number of methods4useful for placing functions in suffix position. The most common method, `pipe`,5forwards a value `T` into any function `T -> R`, returning `R`. The other6methods all apply some form of borrowing to the value before passing the borrow7into the piped function. These are of less value, but provided to maintain a8similar API to the `tap` module’s methods, and for convenience in the event that9you do have a use for them.1011This module is as much of a [UFCS] method syntax that can be provided as a12library, rather than in the language grammar.1314[UFCS]: https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax15!*/1617usecore::{18borrow::{Borrow, BorrowMut},19ops::{Deref, DerefMut},20};2122/** Provides universal suffix-position call syntax for any function.2324This trait provides methods that allow any closure or free function to be placed25as a suffix-position call, by writing them as2627```rust28# use tap::pipe::Pipe;29# let receiver = 5;30fn not_a_method(x: i32) -> u8 { x as u8 }31receiver.pipe(not_a_method);32```3334Piping into functions that take more than one argument still requires writing a35closure with ordinary function-call syntax. This is after all only a library,36not a syntax transformation:3738```rust39use tap::pipe::Pipe;40fn add(x: i32, y: i32) -> i32 { x + y }4142let out = 5.pipe(|x| add(x, 10));43assert_eq!(out, 15);44```4546Like tapping, piping is useful for cases where you want to write a sequence of47processing steps without introducing many intermediate bindings, and your steps48contain functions which are not eligible for dot-call syntax.4950The main difference between piping and tapping is that tapping always returns51the value that was passed into the tap, while piping forwards the value into the52effect function, and returns the output of evaluating the effect function with53the value. Piping is a transformation, not merely an inspection or modification.54**/55pub traitPipe {56/// Pipes by value. This is generally the method you want to use.57///58/// # Examples59///60/// ```rust61/// use tap::pipe::Pipe;62///63/// fn triple(x: i32) -> i64 {64/// x as i64 * 365/// }66///67/// assert_eq!(68/// 10.pipe(triple),69/// 30,70/// );71/// ```72#[inline(always)]73fnpipe<R>(self, func:implFnOnce(Self) -> R) -> R74where75Self: Sized,76R: Sized,77{78func(self)79}8081/// Borrows `self` and passes that borrow into the pipe function.82///83/// # Examples84///85/// ```rust86/// 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)]97fnpipe_ref<'a, R>(&'aself, func:implFnOnce(&'aSelf) -> R) -> R98where99R:'a+ Sized,100{101func(self)102}103104/// Mutably borrows `self` and passes that borrow into the pipe function.105///106/// # Examples107///108/// ```rust109/// use tap::pipe::Pipe;110///111/// let mut vec = vec![false, true];112/// let last = vec113/// .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 should119/// not be piped. Writing out non-trivial examples for these is a lot of120/// boilerplate.121#[inline(always)]122fnpipe_ref_mut<'a, R>(123&'amutself,124func:implFnOnce(&'amutSelf) -> R,125) -> R126where127R:'a+ Sized,128{129func(self)130}131132/// Borrows `self`, then passes `self.borrow()` into the pipe function.133///134/// # Examples135///136/// ```rust137/// 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)]145fnpipe_borrow<'a, B, R>(&'aself, func:implFnOnce(&'aB) -> R) -> R146where147Self: Borrow<B>,148B:'a+?Sized,149R:'a+ Sized,150{151func(Borrow::<B>::borrow(self))152}153154/// Mutably borrows `self`, then passes `self.borrow_mut()` into the pipe155/// function.156///157/// ```rust158/// use tap::pipe::Pipe;159///160/// let mut txt = "hello, world".to_string();161/// let ptr = txt162/// .pipe_borrow_mut(str::as_mut_ptr);163/// ```164///165/// This is a very contrived example, but the `BorrowMut` trait has almost166/// no implementors in the standard library, and of the implementations167/// available, there are almost no methods that fit this API.168#[inline(always)]169fnpipe_borrow_mut<'a, B, R>(170&'amutself,171func:implFnOnce(&'amutB) -> R,172) -> R173where174Self: BorrowMut<B>,175B:'a+?Sized,176R:'a+ Sized,177{178func(BorrowMut::<B>::borrow_mut(self))179}180181/// Borrows `self`, then passes `self.as_ref()` into the pipe function.182#[inline(always)]183fnpipe_as_ref<'a, U, R>(&'aself, func:implFnOnce(&'aU) -> R) -> R184where185Self: AsRef<U>,186U:'a+?Sized,187R:'a+ Sized,188{189func(AsRef::<U>::as_ref(self))190}191192/// Mutably borrows `self`, then passes `self.as_mut()` into the pipe193/// function.194#[inline(always)]195fnpipe_as_mut<'a, U, R>(196&'amutself,197func:implFnOnce(&'amutU) -> R,198) -> R199where200Self: AsMut<U>,201U:'a+?Sized,202R:'a+ Sized,203{204func(AsMut::<U>::as_mut(self))205}206207/// Borrows `self`, then passes `self.deref()` into the pipe function.208#[inline(always)]209fnpipe_deref<'a, T, R>(&'aself, func:implFnOnce(&'aT) -> R) -> R210where211Self: Deref<Target = T>,212T:'a+?Sized,213R:'a+ Sized,214{215func(Deref::deref(self))216}217218/// Mutably borrows `self`, then passes `self.deref_mut()` into the pipe219/// function.220#[inline(always)]221fnpipe_deref_mut<'a, T, R>(222&'amutself,223func:implFnOnce(&'amutT) -> R,224) -> R225where226Self: DerefMut + Deref<Target = T>,227T:'a+?Sized,228R:'a+ Sized,229{230func(DerefMut::deref_mut(self))231}232}233234impl<T> PipeforTwhereT:?Sized {}