rustdoc_index/
search_index.rs1use crate::Error;
2use std::{
3 path::{Path, PathBuf},
4 process::Command
5};
6
7pub fn ls_search_index(dir: &Path) -> Result<Option<PathBuf>, Error> {
9 let search_index: Option<_> = dir.read_dir()?.find_map(|e| -> Option<_> {
10 let e = e.ok()?;
11 let name = e.file_name().into_string().ok()?;
12 name.starts_with("search-index").then(|| e.path())
13 });
14 Ok(search_index)
15}
16
17pub fn find_std() -> Result<Option<PathBuf>, Error> {
18 let output = Command::new("rustup").args(&["doc", "--path"]).output()?;
19 let out = unsafe { String::from_utf8_unchecked(output.stdout) };
20 let file = PathBuf::from(out);
21 let dir = match file.parent() {
22 Some(dir) => dir,
23 None => return Ok(None)
24 };
25 ls_search_index(dir)
26}
27
28pub fn find_local(current_dir: Option<PathBuf>) -> Result<Option<PathBuf>, Error> {
29 let meta = match metadata(current_dir) {
30 Ok(x) => x,
31 Err(_) => return Ok(None)
32 };
33 let dir = meta.target_directory.join_os("doc");
34 if !dir.is_dir() {
35 return Ok(None);
36 }
37 ls_search_index(&dir)
38}
39
40pub async fn search_indexes(current_dir: Option<PathBuf>) -> Result<Vec<PathBuf>, Error> {
41 let async_find_std = tokio::spawn(async { find_std() });
42 let async_find_local = tokio::spawn(async { find_local(current_dir) });
43 let (std, local) = tokio::join!(async_find_std, async_find_local);
44 let mut res = Vec::with_capacity(2);
45 if let Some(std) = std?? {
46 res.push(std);
47 }
48 if let Some(local) = local?? {
49 res.push(local);
50 }
51 Ok(res)
52}
53
54fn metadata(current_dir: Option<PathBuf>) -> Result<cargo_metadata::Metadata, Error> {
55 let mut cmd = cargo_metadata::MetadataCommand::new();
56 if let Some(d) = current_dir {
57 cmd.current_dir(d);
58 }
59 cmd.no_deps();
60 cmd.other_options(vec![String::from("--offline")]);
61 Ok(cmd.exec()?)
62}