[Solved] Confusion in closures syntax

#1

Hello,
I found a piece of code in actix-net, that is a little strange to me, I think that does not describe directly in rust’s book.

actix_server::build()
    .bind(
        // configure service pipeline
        "basic", "0.0.0.0:8443",
        move || {
            let num = num.clone();
            let acceptor = acceptor.clone();
            (move |stream| {                  // <- Where is Origin of stream's variable?
            SslAcceptorExt::accept_async(&acceptor, stream)
                .map_err(|e| println!("Openssl error: {}", e))
        })
        // convert closure to a `NewService`
        .into_new_service()

I can not understand how stream was defined, I checked bind method definition, but I couldn’t understand stream’s origin.

#2

Bind returns a closure that returns a closure. Stream is a function argument.

.bind(name, addr, callback) and the callback is return callback2 and callback2 is fn callback2(stream) {}.

1 Like
#3

Actix itself listens for connections. Each time someone connects, it calls your |stream| closure.

I think the exact line where the connection is accepted, creating a TcpStream, is here. From there, the connection has to be handed off to a worker and pass through a lot of generic code before your closure is finally called here; but all of that is internal to Actix.


Note that the code you found is indented in a very confusing way. It looks like .into_new_service() is outside the outer closure, but it is actually inside. Here’s what it looks like after running rustfmt.

Also, the example code isn’t a complete program that would compile by itself. See examples/basic.rs in the same repository for complete code.

3 Likes
#4

So many thanks, I understood very well :pray::pray: .

1 Like