Expected `&str`, found enum `Option`

Hello, im trying to pass games_found variable to html parser but i get this error

error[E0308]: mismatched types
  --> src\main.rs:14:41
   |
14 |     let fragment = Html::parse_fragment(games_found);
   |                                         ^^^^^^^^^^^ expected `&str`, found enum `Option`
   |
   = note: expected reference `&str`
                   found enum `Option<()>`

my source code is

use scraper::{Html, Selector};

fn main() {
    search("doom".to_string());
}

fn search(game: String) {
    let games_found = howlongtobeat(game.to_string())
        .map_err(|err| println!("{:?}", err))
        .ok();

    let fragment = Html::parse_fragment(games_found);
    let games = fragment.select(&Selector::parse(".search-results-list").unwrap());
    println!("{:?}", games);
}

#[tokio::main]
async fn howlongtobeat(game: String) -> Result<(), Box<dyn std::error::Error>> {
    let response = reqwest::Client::new()
        .post("https://howlongtobeat.com/search_results?page=1")
        .form(&[
            ("queryString", game.to_string()),
            ("t", "games".to_string()),
            ("sorthead", "popular".to_string()),
            ("sortd", "Normal Order".to_string()),
            ("plat", "".to_string()),
            ("length_type", "main".to_string()),
            ("length_min", "".to_string()),
            ("length_max", "".to_string()),
            ("detail", "0".to_string()),
            ("v", "".to_string()),
            ("f", "".to_string()),
            ("g", "".to_string()),
            ("randomize", "0".to_string()),
        ])
        .header(reqwest::header::USER_AGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36")
        .header("Content-type", "application/x-www-form-urlencoded")
        .header("If-None-Match", "wyzzy")
        .header("Accept", "*/*")
        .header("origin", "https://howlongtobeat.com")
        .header("referer", "https://howlongtobeat.com")
        .send()
        .await?;

    let res_body = response.text().await?;
    return Ok(());
}

There are several errors in your code. I would suggest to reformulate your question, otherwise this will turn into an X-Y problem.

1 Like

The compiler is telling you that Html::parse_fragment() requires a &str, but you gave it something else, an Option<()>.

You are passing games_found as the parameter. So, what type does it have? It starts as the return value of the howlongtobeat function, and, thanks to explicit function signatures, we don't even need to look at its code. We can see that it returns a Result<(), Box<dyn std::error::Error>>.

You pass that to map_err which we expect to transform the second type in the Result, although your use is non-idiomatic. Let's skip that for now, as it's not relevant to the error you are seeing.

You then pass the Result to ok(). From Result in std::result - Rust we can see that ok() converts a Result to an Option, specifically one that wraps the first type inside the Result, which in this case is ().

So the type of games_found is Option<()>. And this is what the compiler found.

I think what you are trying to do is pass the text containing the HTTP response body into parse_fragment but you don't return it from howlongtobeat.

Try changing howlongtobeat() to return a Result<String, Box<dyn std::error::Error>> and ending the function with Ok(res_body).

Then instead of using ok(), use unwrap() which will convert a Result into it's first type (String). (This will panic if the result is an error, so you'll eventually want to look into how to handle both parts of the Result.)

Now, games_found will have type String. You need a &str which is a different type, but fortunately, it is very easy to convert. Calling Html::parse_fragment(&games_found) will pass a &String and the compiler will handle the conversion from &String to &str for you. (You can also be more explicit by using Html::parse_fragment(games_found.as_str()).

3 Likes

Hello, thanks for the explanation, it work. :stuck_out_tongue_winking_eye:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.