aselect 0.4.0

Opinionated replacement for tokio::select!, avoiding certain pitfalls.
Documentation
# Using aselect

Before reading this, see [part 1](MOTIVATION.md) for a description of the problem being solved.

The following rust code, using the aselect-library, avoids all problems of the previous code.

```rust

async fn run_server(stream: &mut TcpStream) -> Result<()> {
    let (reader, writer) = stream.split();

    let new_power : Option<u8> = None;
    let perform_measurement = false;
    let queued_responses : VecDeque<Response> = VecDeque::new();

    aselect!(
        {
            mutable(new_power, queued_responses, perform_measurement);
            borrowed(reader, writer);
        },
        read(
            {},
            async |_setup, reader| {
                read_command(reader).await
            },
            |cmd| {
                match cmd {
                    Ok(Command::SetPower(power)) => {
                        *new_power = Some(power);
                    }
                    Ok(Command::QueryTemperature) => { // Query temperature
                        *perform_measurement = true;
                    }
                    Err(err) => {
                        return Some(Output::Value(Err(err)));
                    }
                }
                None
            }
        ),
        write(
            {
                queued_responses.pop_front()?
            },
            async |response, writer| {
                write_response(writer, response).await
            },
            |result|{
                if let Err(err) = result {
                    return Some(Output::Value(Err(err)));
                }
                 None
            }
        ),
        set_power(
            {
                new_power.take()?
            },
            async |power|{
                set_heater_power(power)
            },
            |_result|
            {
                None
            }
        ),
        measure(
            {
                if !*perform_measurement {
                    return None;
                }
                *perform_measurement = false;
            },
            async |_setup|{
                measure_temperature().await
            },
            |temperature|
            {
                queued_responses.push_back(Response::Temperature(temperature));
                None
            }
        ),
        alarm(
            {
            },
            async |_setup| {
                wait_temperature_alarm().await
            },
            |temperature|{
                queued_responses.push_back(Response::Temperature(temperature));
                None
            }
        )
    ).await

}
```

Let's go through it part-by-part.

## Shared State

First, we define some state:

```rust
    let new_power : Option<u8> = None;
    let perform_measurement = false;
    let queued_responses : VecDeque<Response> = VecDeque::new();
```

 * `new_power` is an option that is set to whatever new value the heater power has been commanded to, or None if
   no command is active.
 * `perform_measurement` is set to true whenever a measurement has been desired.
 * `queued_responses` contains responses that have been created, but not yet transmitted to the client.


## Macro invocation

Then we invoke the `aselect` macro:

```rust
    aselect!(
        {
            mutable(new_power, queued_responses, perform_measurement);
            borrowed(reader, writer);
        },
    ...
    ).await
```

Here we define `new_power`, `queued_responses` and `perform_measurement` as mutable captures. These
variables can be accessed directly from within the setup and handler blocks (which we'll learn more about below).

We define `reader` and `writer` as "borrowed" captures. This means that they can be borrowed by async blocks. This 
means async blocks that use `reader` and `writer` can capture a reference to these variables in their future.
If two async blocks try to capture the same variable, only the first one will actually run. The reason for this is
that mutable references to the same captured variable cannot be held by two different futures, because of rust's
borrow rules.

Now, let's look at the first select arm (commented):

## Read arm


```rust 
    read(
        {}, //Setup
        async |_setup, reader| { //Async block
            read_command(reader).await
        },
        |cmd| { // Handler
            match cmd {
                Ok(Command::SetPower(power)) => {
                    *new_power = Some(power);
                }
                Ok(Command::QueryTemperature) => { // Query temperature
                    *perform_measurement = true;
                }
                Err(err) => {
                    return Some(Output::Value(Err(err)));
                }
            }
            None
        }
    ),
```
The arm is named `read`, and has three blocks:
 * 
 * setup
 * async
 * handler

The setup is empty. The async block simply calls the async method `read_command`, with the borrowed capture `reader`.
Every "borrowed" capture must be specified in the argument list to an async block. The same capture can be used in
multiple blocks, but only the first enabled such future will actually run.

Finally, the result produced by the async code is given to the handler, which acts on the parsed command.

If the received command i `SetPower`, we set the mutable capture `new_power` to the new desired power value.
If the received command i `QueryTemperature`, we set the mutable capture `perform_measurement` to true.

This block allows us to receive commands, and update our shared state as a result of those commands.
Note that the future created by the `read_command` async method will never be canceled. It thus does not need
to be cancelation safe.

The next block is:

## Write arm

```rust
    write(
        { // Setup
            queued_responses.pop_front()?
        },
        async |response, writer| { // Async block
            write_response(writer, response).await
        },
        |result| { // Handler
            if let Err(err) = result {
                return Some(Output::Value(Err(err)));
            }
             None
        }
    ),

```

We pop the first queued command. If none exists, we return `None`. Returning None from a setup block disables
the async block. If a queued response exists, it will be given as the first parameter to the async block (`response`).
The async block calls the `write_response` async method.

The result of the async block is then given to the handler. If the result is an error, the handler returns an result,
causing the whole `aselect` macro invocation to complete with an error.

The next block is:

## Set Power arm

```rust
    set_power(
        {
            new_power.take()?
        },
        async |power|{
            set_heater_power(power)
        },
        |_result|
        {
            None
        }
    ),
```

If the option `new_power` holds a value, enable the async block and call `set_heater_power`.
Do not return a result.


## Measure arm

```rust
    measure(
        {
            if !*perform_measurement {
                return None;
            }
            *perform_measurement = false;
        },
        async |_setup|{
            measure_temperature().await
        },
        |temperature|
        {
            queued_responses.push_back(Response::Temperature(temperature));
            None
        }
    ),
```

If `perform_measurement` is false, disable the async block. Otherwise execute `measure_temperature().await`.
A response with the produced temperature is added to `queued_responses`.

## Alarm arm

```rust
    alarm(
        {
        },
        async |_setup| {
            wait_temperature_alarm().await
        },
        |temperature|{
            queued_responses.push_back(Response::Temperature(temperature));
            None
        }
    )
```

Run the `wait_temperature_alarm` method. Whenever it completes, add a queued response.

## Conclusion

The code presented here has the following guarantees:

 * All the futures are always polled
 * Futures are never canceled unless an error occurs and we exit the loop

It is still relatively convenient and doesn't require any Mutexes, RefCells or other mechanisms to maintain
shared state. Cancel safety need mostly not be considered, since cancellation doesn't occur during regular use.