crate_paths_cli_core/backend/rustup/
mod.rs

1pub mod error;
2
3use super::BackendError;
4use crate::error::CoreError;
5use crate::item::ItemEntry;
6use crate::parser;
7use error::RustupBackendError;
8use std::path::PathBuf;
9use std::process::Command;
10
11fn fetch_std_all_items_html(crate_name: &str) -> Result<String, RustupBackendError> {
12    let output = Command::new("rustup")
13        .args(["doc", "--path"])
14        .output()
15        .map_err(RustupBackendError::RustupDocExecution)?;
16
17    if !output.status.success() {
18        return Err(RustupBackendError::RustupDocStatus(
19            output.status.code().unwrap_or(1),
20        ));
21    }
22
23    let doc_path_str = String::from_utf8(output.stdout)?;
24    let trimmed_doc_path_str = doc_path_str.trim();
25
26    let mut doc_root_path = PathBuf::from(trimmed_doc_path_str);
27
28    if doc_root_path.is_file() {
29        if let Some(parent_dir) = doc_root_path.parent() {
30            doc_root_path = parent_dir.to_path_buf();
31        } else {
32            return Err(RustupBackendError::DocPathInvalid(PathBuf::from(
33                trimmed_doc_path_str,
34            )));
35        }
36    }
37
38    if !doc_root_path.is_dir() {
39        return Err(RustupBackendError::DocPathNotFound(doc_root_path));
40    }
41
42    let all_html_path = doc_root_path.join(crate_name).join("all.html");
43
44    if !all_html_path.is_file() {
45        return Err(RustupBackendError::DocFileNotFound(all_html_path));
46    }
47
48    std::fs::read_to_string(&all_html_path)
49        .map_err(|e| RustupBackendError::FileRead(all_html_path, e))
50}
51
52pub fn process(crate_name: &str) -> Result<Vec<ItemEntry>, CoreError> {
53    let html_content = fetch_std_all_items_html(crate_name)
54        .map_err(BackendError::from)
55        .map_err(CoreError::from)?;
56
57    parser::parse_html_to_items(crate_name, &html_content).map_err(CoreError::from)
58}