use super::{CrateProvenance, Source};
use crate::{CrateInfo, RustdocData};
use anyhow::Result;
use semver::{Version, VersionReq};
use std::{borrow::Cow, path::PathBuf};
use trillium_smol::async_io::block_on;
mod client;
use client::{DocsRsClient, ResolvedMetadata};
#[derive(Debug)]
pub struct DocsRsSource {
client: DocsRsClient,
}
impl DocsRsSource {
pub fn new(cache_dir: PathBuf) -> Result<Self> {
let client = DocsRsClient::new(cache_dir)?;
Ok(Self { client })
}
pub fn from_default_cache() -> Option<Self> {
let cache_dir = home::cargo_home().ok()?.join("rustdoc-json");
DocsRsClient::new(cache_dir)
.ok()
.map(|client| Self { client })
}
async fn load_async(&self, crate_name: &str, version: &Version) -> Result<Option<RustdocData>> {
self.client.get_crate(crate_name, version).await
}
pub fn list_available_crates(&self) -> Option<std::iter::Empty<String>> {
None
}
}
impl Source for DocsRsSource {
fn lookup<'a>(&'a self, name: &str, version_req: &VersionReq) -> Option<Cow<'a, CrateInfo>> {
let ResolvedMetadata {
name,
version,
description,
} = block_on(self.client.resolve(name, version_req))
.ok()
.flatten()?;
Some(Cow::Owned(CrateInfo {
provenance: CrateProvenance::DocsRs,
version: Some(version),
description: Some(description),
name,
default_crate: false,
used_by: vec![],
json_path: None,
}))
}
fn load(&self, crate_name: &str, version: Option<&Version>) -> Option<RustdocData> {
block_on(self.load_async(crate_name, version?))
.ok()
.flatten()
}
}