How to access the connection object in the inner blocks?

Hi, I am working on the web sockets where I'm using the tokio-tungstenite crate. And once after the socket connection is established, I'm trying to send a request to the server. And that time I'm getting this error "cannot move out of ws_stream, a captured variable in an Fn closure".

use tauri::Manager;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio_tungstenite::{connect_async, tungstenite::protocol::Message};
use url::Url;
use futures_util::{StreamExt, SinkExt};

#[tokio::main]
async fn main() {
        let url = url::Url::parse("wss://127.0.0.1:8000/ws").unwrap();   
        
        println!("Creating connection"); 
        let (ws_stream, _) = connect_async(url).await.expect("Failed to connect");
        println!("WebSocket handshake has been successfully completed \n");    

  tauri::Builder::default()
  
  .setup(|app|{
    app.listen_global("send_request", |_handler| {     
      tauri::async_runtime::spawn (async move { 
        
        let (mut write, read) = ws_stream.split(); 

        write.send(Message::Text(r#"{
         "reqid": 42
        }"#.to_string()+"\n")).await.unwrap();

        println!("Request sent!!!");
        println!("\n\n");
      });
    });

  Ok(())
})

    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

And while running the application, I was getting this error

error[E0507]: cannot move out of `ws_stream`, a captured variable in an `Fn` closure
  --> src\main.rs:29:47
   |
19 |            let (ws_stream, _) = connect_async(url).await.expect("Failed to connect");
   |                 --------- captured outer variable
...
27 |        app.listen_global("send_request", |_handler| {
   |   _______________________________________-
28 |  |
29 |  |       tauri::async_runtime::spawn (async move {
   |  |_______________________________________________^
30 | ||
31 | ||         let (mut write, read) = ws_stream.split();
   | ||                                 ---------
   | ||                                 |
   | ||                                 variable moved due to use in generator
   | ||                                 move occurs because `ws_stream` has type `WebSocketStream<tokio_tungstenite::MaybeTlsStream<tokio::net::TcpStream>>`, which does not implement the `Copy` trait
32 | ||         /* Sending request to the server*/
...  ||
55 | ||         */
56 | ||       });
   | ||_______^ move out of `ws_stream` occurs here
57 |  |     });
   |  |_____- captured by this `Fn` closure

For more information about this error, try `rustc --explain E0507`.

Can someone please let me know how to access the "ws_stream" variable in the inner block?

You should call split outside the setup callback, i.e. before tauri::Builder::default. The reason is that callback will be called many times, but the stream can be split only once.

1 Like

I tried moving the split outside the "setup" callback, but then I'm getting another error.

error[E0507]: cannot move out of `write`, a captured variable in an `Fn` closure
  --> src\main.rs:30:47
   |
23 |            let (mut write, read) = ws_stream.split();
   |                 --------- captured outer variable
...
28 |        app.listen_global("send_request", |_handler| {
   |   _______________________________________-
29 |  |
30 |  |       tauri::async_runtime::spawn (async move {
   |  |_______________________________________________^
31 | ||
32 | ||         /* Sending request to the server*/
33 | ||         println!("Sending Get Config Request to the server");
34 | ||
35 | ||         write.send(Message::Text(r#"{
   | ||         -----
   | ||         |
   | ||         variable moved due to use in generator
   | ||         move occurs because `write` has type `SplitSink<WebSocketStream<tokio_tungstenite::MaybeTlsStream<tokio::net::TcpStream>>, tokio_tungstenite::tungstenite::Message>`, which does not implement the `Copy` trait
...  ||
55 | ||         */
56 | ||       });
   | ||_______^ move out of `write` occurs here
57 |  |     });
   |  |_____- captured by this `Fn` closure

For more information about this error, try `rustc --explain E0507`.

You probably want to make the closure move too (i.e. app.listen_global("send_request", move |_handler| {).