0

I have a program that does various simple things based on user selection.

fn main() {
    let mut user_input = String::new(); // Initialize variable to store user input
    println!("Select an option:\r\n[1] Get sysinfo\r\n[2] Read/Write File\r\n[3] Download file\r\n[4] Exit"); // Print options
    io::stdin().read_line(&mut user_input).expect("You entered something weird you donkey!"); // Get user input and store in variable
    let int_input = user_input.trim().parse::<i32>().unwrap(); // Convert user input to int (i32 means signed integer 32 bits)
    
    match int_input { // If Else statement
        1 => getsysinfo(), // If int_input == 1, call getsysinfo()
        2 => readwritefile(),
        3 => downloadfile(),
        4 => process::exit(1), // end program
        _ => println!("You didn't choose one of the given options, you donkey!") // input validation
    }
}

My function downloadfile() looks like this, referenced from the Rust cookbook on downloading files.

error_chain! {
    foreign_links {
        Io(std::io::Error);
        HttpRequest(reqwest::Error);
    }
}


async fn downloadfile() -> Result<()> {
    let tmp_dir = Builder::new().prefix("example").tempdir()?;
    let target = "localhost:8000/downloaded.txt";
    let response = reqwest::get(target).await?;

    let mut dest = {
        let fname = response
            .url()
            .path_segments()
            .and_then(|segments| segments.last())
            .and_then(|name| if name.is_empty() { None } else { Some(name) })
            .unwrap_or("tmp.bin");

        println!("File to download: {}", fname);
        let fname = tmp_dir.path().join(fname);
        println!("Will be located under: {:?}", fname);
        File::create(fname)?
    };

    let content = response.text().await?;
    copy(&mut content.as_bytes(), &mut dest)?;

    Ok(())
}

I get the following error:

`match` arms have incompatible types
expected unit type `()`
 found opaque type `impl Future<Output = std::result::Result<(), Error>>`

I presume its because the async function returns a Future type, so how can I make this code work?

  • 4
    Your comments are a fine example of how *not* to use comments. Most are redundant and one is plain wrong. `match` is not an if statement. – Richard Neumann Nov 30 '22 at 07:20
  • @RichardNeumann Thanks for the clarification on match, I understand there are some differences but this program is meant to be read and understood by people who have never seen a single line of Rust code in their life. All they need to know about match is that it works similarly to an if else statement. – hokkaidomelk Nov 30 '22 at 07:28
  • But if you write it like that they will write code like `match x { a => {...}}` and wonder why it gets run even if before that `a != x`... – cafce25 Nov 30 '22 at 09:28

1 Answers1

1

You need to use the block_on function.

Add futures as a dependency in your cargo.toml for the following example to work.

use futures::executor::block_on;

async fn hello() -> String {
    return String::from("Hello world!");
}

fn main() {
    let output = block_on(hello());
    println!("{output}");
}
Ian Ash
  • 1,087
  • 11
  • 23
  • Wow, with `futures` it is easier than with `tokio::runtime` https://stackoverflow.com/a/75766292/8111346 – kolserdav Mar 17 '23 at 10:14