rouste 0.1.5

Generic and declarative URI based router written with insane Rust macros.
Documentation
# What is it?

Rouste is a generic and declarative URI based router written with insane Rust macros.

The basic idea is to generate a router in a convenient way with two macros:

1. `route!(pattern => handler)`: declare routes that associate a pattern to a handler
2. `route_with![routes]`: generate the router from a list of routes. The router is a function from a URI (path and query
   string) to a "maybe something" type that will try to match the route corresponding to the given URI and execute the
   associated handler

Rouste is generic in the sense that routes can capture any value from the URI and they can return any value as long as
every handler of the same router return the same type.

# Getting started

Add rouste dependency in Cargo.toml:

```
rouste = "0.1.3"
```

## Declaring a route

Declare a route with the `route!` macro. This macro has two parameters: a pattern and a handler. If the pattern matches
the URI, the handler will be executed. The pattern can capture data from the URI for the handler. Data can be captured
from URI segments and query parameters. Uncaptured data are represented by a Rust identifier in the pattern and captured
data are represented by a token tree of the form `(identifier: type)` where type implements the `FromStr` trait.

The following route will try to match the root or an empty URI and call `handler_default`:

```rust
route!(/ => handle_default)
```

```rust
fn handle_default() {}
```

This route will match an URI of the form "/say/my/name" where name can be any string. The handler must have a only one
parameter which is a `String`:

```rust
route!(/say/my/(name: String) => print_name)
```

```rust
fn print_name(name: String) {
    println!("{}, you're goddamn right", name);
}
```

As query parameters are optional, they are captured and passed as `Option`s. A query parameter can be in the form KEY or
KEY=VALUE. A KEY only query parameter is denoted by a Rust identifier and when captured its value is unit `()`:

```rust
route!(/fibonacci/(n: usize)?(f0: u32)&(f1: u32)&log => fibonacci)
```

```rust
fn fibonacci(n: usize, maybe_f0: Option<u32>, maybe_f1: Option<u32>, maybe_log: Option<()>) -> u32 {
    let f0 = maybe_f0.unwrap_or(0);
    let f1 = maybe_f1.unwrap_or(1);
    let mut fibo_number: Vec<u32> = vec![f0, f1];

    for i in 0 ..= n {
        if maybe_log.is_some() {
            println!("{}", fibo_number[i]);
        }
        let current = fibo_number[i];
        let next = fibo_number[i + 1];
        fibo_number.push(current + next);
    }
    
    fibo_number[n]
}
```

## Declaring a router

A router is defined by a list of routes. Handlers must have the same return type:

```rust
fn handle_default() -> u32 {
    fibonacci(0)
}

fn fibonacci(n: u32) -> u32 {
    match n {
        0 => 0,
        1 => 1,
        n => fibonacci(n - 1) + fibonacci(n - 2)
    }
}

fn main() {
    let fibonacci_router = route_with![ route!(/ => handle_default)
                                      , route!(/(n: u32) => fibonacci)
                                      ];

    assert_eq!(fibonacci_router("/"), Some(0));
    assert_eq!(fibonacci_router("/invalid"), None);
    assert_eq!(fibonacci_router("/0"), Some(0));
    assert_eq!(fibonacci_router("/1"), Some(1));
    assert_eq!(fibonacci_router("/10"), Some(55));
}
```