Function docsearch::start_search

source ·
pub fn start_search(name: &str, version: Version) -> SearchPage<'_>
Expand description

Search for the given crate name and optionally a fixed version. This is the main entry point to retrieve an Index and further query that index for SimplePaths.

Example

Download the index for the anyhow crate and get the docs.rs link for the anyhow::Result item.

use anyhow::Result;
use docsearch::{SimplePath, Version};

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
    // First parse the search query into a `SimplePath`. This ensures the query is actually
    // usable and allows to provide additional info.
    let query = "anyhow::Result".parse::<SimplePath>().unwrap();

    // Initiate a new search. It allows to not depend on a specific HTTP crate and instead
    // pass the task to the developer (that's you).
    let state = docsearch::start_search(query.crate_name(), Version::Latest);
    // First, download the HTML page content to find the URL to the search index.
    let content = download_url(state.url()).await?;

    // Now try to find the the link to the actual search index.
    let state = state.find_index(&content)?;
    // Next, download the search index content.
    let content = download_url(state.url()).await?;

    // Lastly, transform the search index content into an `Index` instance, containing all
    // information to create webpage links to an item within the scope of the requested crate.
    let index = state.transform_index(&content)?;

    // Now we can use the index to query for our initial item.
    let link = index.find_link(&query).unwrap();

    // And print out the resolved web link to it.
    println!("{link}");

    Ok(())
}

/// Simple helper function to download any HTTP page with `reqwest`, using a normal GET request.
async fn download_url(url: &str) -> Result<String> {
    reqwest::Client::builder()
        .redirect(reqwest::redirect::Policy::limited(10))
        .build()?
        .get(url)
        .send()
        .await?
        .error_for_status()?
        .text()
        .await
        .map_err(Into::into)
}