/*! # `tap` – Syntactical Plumb-Lines
Rust permits functions that take a `self` receiver to be written in “dot-call”
suffix position, rather than the more traditional prefix-position function call
syntax. These functions are restricted to `impl [Trait for] Type` blocks, and
functions anywhere else cannot take advantage of this syntax.
This crate provides universally-implemented extension traits that permit smooth
suffix-position calls for a handful of common operations: transparent inspection
or modification (tapping), transformation (piping), and type conversion.
## Tapping
The [`tap`] module provides the [`Tap`], [`TapOptional`], and [`TapFallible`]
traits. Each of these traits provides methods that take and return a value, and
expose it as a borrow to an effect function. They look like this:
```rust
use tap::prelude::*;
# struct Tmp;
# fn make_value() -> Tmp { Tmp }
# impl Tmp { fn process_value(self) {} }
# macro_rules! log { ($msg:literal, $val:ident) => {{}}; }
let end = make_value()
.tap(|v| log!("Produced value: {:?}", v))
.process_value();
```
These methods are `self -> Self`, and return the value they received without
any transformation. This enables them to be placed anywhere in a larger
expression witohut changing its shape, or causing any semantic changes to the
code. The effect function receives a borrow of the tapped value, optionally run
through the `Borrow`, `AsRef`, or `Deref` view conversions, for the duration of
its execution.
The effect function cannot return a value, as the tap is incapable of handling
it.
## Piping
The [`pipe`] module provides the [`Pipe`] trait. This trait provides methods
that take and transform a value, returning the result of the transformation.
They look like this:
```rust
use tap::prelude::*;
struct One;
fn start() -> One { One }
struct Two;
fn end(_: One) -> Two { Two }
let val: Two = start().pipe(end);
// without pipes, this would be written as
let _: Two = end(start());
```
These methods are `self -> Other`, and return the value produced by the effect
function. As the methods are always available in suffix position, they can take
as arguments methods that are *not* eligible for dot-call syntax and still place
them as expression suffices. The effect function receives the piped value,
optionally run through the `Borrow`, `AsRef`, or `Deref` view conversions, as
its input, and its output is returned from the pipe.
For `.pipe()`, the input value is *moved* into the pipe and the effect function,
so the effect function *cannot* return a value whose lifetime depends on the
input value. The other pipe methods all borrow the input value, and may return a
value whose lifetime is tied to it.
## Converting
The [`conv`] module provides the [`Conv`] and [`TryConv`] traits. These provide
methods that accept a type parameter on the method name, and forward to the
appropriate `Into` or `TryInto` trait implementation when called. The difference
between `Conv` and `Into` is that `Conv` is declared as `Conv::conv::<T>`, while
`Into` is declared as `Into::<T>::into`. The location of the destination type
parameter makes `.into()` unusable as a non-terminal method call of an
expression, while `.conv::<T>()` can be used as a method call anywhere.
```rust,compile_fail
let upper = "hello, world"
.into()
.tap_mut(|s| s.make_ascii_uppercase());
```
The above snippet is illegal, because the Rust type solver cannot determine the
type of the sub-expression `"hello, world".into()`, and it will not attempt to
search all available `impl Into<X> for str` implementations to find an `X` which
has a
`fn tap_mut({self, &self, &mut self, Box<Self>, Rc<Self>, Arc<Self>}, _) -> Y`
declared, either as an inherent method or in a trait implemented by `X`, to
resolve the expression.
Instead, you can write it as
```rust
use tap::prelude::*;
let upper = "hello, world"
.conv::<String>()
.tap_mut(|s| s.make_ascii_uppercase());
```
The trait implementation is
```rust
pub trait Conv: Sized {
fn conv<T: Sized>(self) -> T
where Self: Into<T> {
self.into()
}
}
```
Each monomorphization of `.conv::<T>()` expands to the appropriate `Into<T>`
implementation, and does nothing else.
[`Conv`]: conv/trait.Conv.html
[`Pipe`]: pipe/trait.Pipe.html
[`Tap`]: tap/trait.Tap.html
[`TapFallible`]: tap/trait.TapFallible.html
[`TapOptional`]: tap/trait.TapOptional.html
[`TryConv`]: conv/trait.TryConv.html
[`conv`]: conv/index.html
[`pipe`]: pipe/index.html
[`tap`]: tap/index.html
!*/
/// Reëxports all traits in one place, for easy import.
// also make traits available at crate root
pub use *;