logfn 0.1.0

provides the logfn attribute macro for inserting logging code into your function.
Documentation
logfn
===

This crate provides the `logfn` attribute macro for inserting logging code into your function.

This is heavily inspired by [elichai's `log-derive`](https://github.com/elichai/log-derive) crate.

Currently we support 2 types of logging.

- Pre logging
- Post logging

And we have a plan to add `Time logging` and `Count logging` type.

Each `logfn` attribute injects a single logging code. You can put as many `logfn` as you want.

```rust
# use logfn::logfn;
# use std::num::ParseIntError;
#[logfn(Pre, Debug, "{fn} will be executed")]
#[logfn(Post, Debug, "{fn} is executed", if = "Result::is_ok")]
#[logfn(Post, Error, "Error {fn}: {ret:?}", if = "Result::is_err")]
fn atoi(a: &str) -> Result<usize, ParseIntError> {
    usize::from_str_radix(a, 10)
}
```

The detail is documented below.

## Pre logging

The following attribute injects logging code **before** function is called.

```rust
use logfn::logfn;

#[logfn(Pre, Info, "executing {fn}...")]
fn add(a: usize, b: usize) -> usize {
    a + b
}
```

The resulting code will looks like

```rust
fn add(a: usize, b: usize) -> usize {
    log::info!("executing add...");

    {
        a + b
    }
}
```

## Post logging

You also be able to inject logging code **after** function is called.

```rust
use logfn::logfn;

#[logfn(Post, Info, "executed {fn}!")]
fn add(a: usize, b: usize) -> usize {
    a + b
}
```

The resulting code will looks like

```rust
fn add(a: usize, b: usize) -> usize {
    let res = (move || {
        a + b
    })();

    log::info!("executed add!");

    res
}
```

## Conditional logging

You can configure the condition on which logging code is fired.
To do that, please add `if` argument with a path to the function which takes reference to
returned value and returns `true` when you want to fire the logging code.

## Note
Conditional logging is only supported in post logging for now.

```rust
use logfn::logfn;

#[logfn(Post, Warn, "checked add is failed!!", if = "Option::is_none")]
fn checked_add(a: usize, b: usize) -> Option<usize> {
    a.checked_add(b)
}
```

## Message formatting

We support below format patterns.

- "{fn}" interpolates function name
- "{ret:?}" or "{ret}" interpolates returned value

```rust
# use std::num::ParseIntError;
use logfn::logfn;

#[logfn(Post, Error, "Error while {fn}: {ret:?}", if = "Result::is_err")]
fn atoi(s: &str) -> Result<usize, ParseIntError> {
    usize::from_str_radix(s, 10)
}
```

## Async function

Async function is also supported.

```rust
use logfn::logfn;

#[logfn(Post, Debug, "{fn} is executed")]
async fn add_fut(a: usize, b: usize) -> usize {
    a + b
}
```