Crate docsrs

Source
Expand description

§docsrs

docsrs is a Rust crate for retrieving, parsing, and indexing rustdoc JSON files, enabling fuzzy searching of Rust documentation content with a type-safe pipeline approach.

Whether you’re building a custom documentation browser, writing a Rust LSP plugin, creating documentation analysis tools, or just need to programmatically explore docs — docsrs gives you structured access to items and metadata in a searchable form.

§Features

The crate uses a type-state pattern to ensure compile-time safety when processing documentation through different stages:

  • default - Core functionality for loading and parsing JSON files
  • decompress - Adds support for decompressing zstd-compressed files
  • fetch - Enables fetching compressed documentation directly from docs.rs

§Quick Start

§Basic Usage with Local JSON

use docsrs::Doc;

// Load and parse a local JSON documentation file
let doc = Doc::from_json("path/to/docs.json")?
    .parse()?
    .build_search_index();

// Search for items
let results = doc.search("HashMap", Some(10));
for item in results.unwrap_or_default() {
    println!("{}: {}", item.name, item.path.join("::"));
}

§Fetching from docs.rs (requires fetch feature)

use docsrs::Doc;

// Fetch, decompress, parse, and index documentation from docs.rs
let doc = Doc::from_docs("serde", "latest")?
    .fetch()?
    .decompress()?
    .parse()?
    .build_search_index();

// Search for serialization-related items
let results = doc.search("Serialize", Some(5));

§Working with Compressed Files (requires decompress feature)

use docsrs::Doc;

// Load and decompress a local zstd file
let doc = Doc::from_zst("docs/tokio.json.zst")?
    .decompress()?
    .parse()?
    .build_search_index();

let results = doc.search("tokio::spawn", None);

§Type-State Pipeline

The crate uses a type-state pattern to ensure you process documentation in the correct order:

Flow:
  Remote ── fetch() ─→ Compressed ── decompress() ─→ RawJson ── parse() ─→ Parsed ── build_search_index() ─→ Indexed
               ↑                ↑                         ↑
        from_docs()      from_zst()                from_json()

Each state represents a different stage in the documentation processing pipeline:

  • Remote - Documentation URL ready to be fetched from docs.rs
  • Compressed - Downloaded or loaded compressed documentation data
  • RawJson - Decompressed JSON data in bytes
  • Parsed - Parsed documentation AST with structured data
  • Indexed - Documentation with built search index for fuzzy matching

§Search Capabilities

The fuzzy search functionality supports:

  • Fully qualified paths: "std::collections::HashMap"
  • Partial matches: "vec push" matches Vec::push
  • Case-insensitive: "hashmap" matches HashMap
  • Methods and functions: "tokio::spawn" finds the spawn function
  • Ranked results: Results are sorted by relevance score

§Item Information

Each search result provides comprehensive information:

let results = doc.search("HashMap::new", Some(1));
if let Some(items) = results {
    for item in items {
        println!("Name: {}", item.name);
        println!("Path: {}", item.path.join("::"));
        println!("Docs: {}", item.docs.as_deref().unwrap_or("No docs"));
        println!("Deprecated: {}", item.deprecation.is_some());
    }
}

§Error Handling

All operations return Result<T, Error> where Error covers:

  • HTTP errors when fetching from docs.rs
  • File I/O errors when reading local files
  • JSON parsing errors for malformed documentation
  • URL parsing errors for invalid docs.rs URLs

§Performance Considerations

  • Memory usage: Large crates like std can use significant memory when indexed
  • Search speed: Fuzzy search is optimized but may be slower on very large indices
  • Parsing time: Initial parsing and indexing can take time for large documentation sets

Consider using search result limits and caching indexed documentation for better performance.

§Examples

§Building a Documentation Browser

use docsrs::Doc;

fn search_docs(query: &str) -> Result<(), Box<dyn std::error::Error>> {
    let doc = Doc::from_docs("tokio", "latest")?
        .fetch()?
        .decompress()?
        .parse()?
        .build_search_index();

    if let Some(results) = doc.search(query, Some(20)) {
        for item in results {
            println!("{}", item.path.join("::"));
            if let Some(docs) = &item.docs {
                println!("  {}", docs.lines().next().unwrap_or(""));
            }
        }
    }
    Ok(())
}

§Analyzing Documentation Coverage

use docsrs::Doc;

fn analyze_coverage(crate_name: &str) -> Result<(), Box<dyn std::error::Error>> {
    let doc = Doc::from_docs(crate_name, "latest")?
        .fetch()?
        .decompress()?
        .parse()?
        .build_search_index();

    let all_items = doc.search("", None).unwrap_or_default();
    let documented = all_items.iter().filter(|item| item.docs.is_some()).count();
     
    println!("Total items: {}", all_items.len());
    println!("Documented: {}", documented);
    println!("Coverage: {:.1}%", (documented as f64 / all_items.len() as f64) * 100.0);
     
    Ok(())
}

This was generated by Claude Sonnet 4, because:

  • I’m really bad at writing documentation (everything would be very short one-liners)
  • I’m lazy
  • I don’t have the nerves to write a documentation this long

The code was written by me

Structs§

Compressed
Represents compressed documentation data in zstd format.
Doc
A generic wrapper for documentation data in different processing states.
Indexed
Represents indexed documentation data with fuzzy search capabilities.
Item
Represents a single documentation item with all its metadata and content.
Parsed
Represents parsed documentation data with a structured AST.
RawJson
Represents raw JSON documentation data in bytes.
Remote
Represents a remote documentation source that can be fetched from docs.rs.

Enums§

Error
Errors that can occur during documentation processing