rocket_ws

Macro Stream

Source
macro_rules! Stream {
    () => { ... };
    ($l:lifetime) => { ... };
    ($channel:ident => $($token:tt)*) => { ... };
}
Expand description

Type and expression macro for async WebSocket Message streams.

This macro can be used both where types are expected or where expressions are expected.

§Type Position

When used in a type position, the macro invoked as Stream['r] expands to:

The lifetime need not be specified as 'r. For instance, Stream['request] is valid and expands as expected:

As a convenience, when the macro is invoked as Stream![], the lifetime defaults to 'static. That is, Stream![] is equivalent to Stream!['static].

§Expression Position

When invoked as an expression, the macro behaves similarly to Rocket’s stream! macro. Specifically, it supports yield and for await syntax. It is invoked as follows:

use rocket_ws as ws;

#[get("/")]
fn echo(ws: ws::WebSocket) -> ws::Stream![] {
    ws::Stream! { ws =>
        for await message in ws {
            yield message?;
            yield "foo".into();
            yield vec![1, 2, 3, 4].into();
        }
    }
}

It enjoins the following type requirements:

  • The type of ws must be WebSocket. ws can be any ident.
  • The type of yielded expressions (expr in yield expr) must be Message.
  • The Err type of expressions short-circuited with ? must be Error.

The macro takes any series of statements and expands them into an expression of type impl Stream<Item = Result<T>>, a stream that yields elements of type Result<T>. It automatically converts yielded items of type T into Ok(T). It supports any Rust statement syntax with the following extensions:

  • ? short-circuits stream termination on Err

    The type of the error value must be Error.

  • yield expr

    Yields the result of evaluating expr to the caller (the stream consumer) wrapped in Ok.

    expr must be of type T.

  • for await x in stream { .. }

    awaits the next element in stream, binds it to x, and executes the block with the binding.

    stream must implement Stream<Item = T>; the type of x is T.

§Examples

Borrow from the request. Send a single message and close:

use rocket_ws as ws;

#[get("/hello/<user>")]
fn ws_hello(ws: ws::WebSocket, user: &str) -> ws::Stream!['_] {
    ws::Stream! { ws =>
        yield user.into();
    }
}

Borrow from the request with explicit lifetime:

use rocket_ws as ws;

#[get("/hello/<user>")]
fn ws_hello<'r>(ws: ws::WebSocket, user: &'r str) -> ws::Stream!['r] {
    ws::Stream! { ws =>
        yield user.into();
    }
}

Emit several messages and short-circuit if the client sends a bad message:

use rocket_ws as ws;

#[get("/")]
fn echo(ws: ws::WebSocket) -> ws::Stream![] {
    ws::Stream! { ws =>
        for await message in ws {
            for i in 0..5u8 {
                yield i.to_string().into();
            }

            yield message?;
        }
    }
}