1use std::path::PathBuf;
2use std::sync::Arc;
3
4use anyhow::{anyhow, Result};
5use async_trait::async_trait;
6use futures::FutureExt;
7use indexed_docs::{IndexedDocsDatabase, IndexedDocsProvider, PackageName, ProviderId};
8use wasmtime_wasi::WasiView;
9
10use crate::wasm_host::{WasmExtension, WasmHost};
11
12pub struct ExtensionIndexedDocsProvider {
13 pub(crate) extension: WasmExtension,
14 pub(crate) host: Arc<WasmHost>,
15 pub(crate) id: ProviderId,
16}
17
18#[async_trait]
19impl IndexedDocsProvider for ExtensionIndexedDocsProvider {
20 fn id(&self) -> ProviderId {
21 self.id.clone()
22 }
23
24 fn database_path(&self) -> PathBuf {
25 let mut database_path = self.host.work_dir.clone();
26 database_path.push(self.extension.manifest.id.as_ref());
27 database_path.push("docs");
28 database_path.push(format!("{}.0.mdb", self.id));
29
30 database_path
31 }
32
33 async fn suggest_packages(&self) -> Result<Vec<PackageName>> {
34 self.extension
35 .call({
36 let id = self.id.clone();
37 |extension, store| {
38 async move {
39 let packages = extension
40 .call_suggest_docs_packages(store, id.as_ref())
41 .await?
42 .map_err(|err| anyhow!("{err:?}"))?;
43
44 Ok(packages
45 .into_iter()
46 .map(|package| PackageName::from(package.as_str()))
47 .collect())
48 }
49 .boxed()
50 }
51 })
52 .await
53 }
54
55 async fn index(&self, package: PackageName, database: Arc<IndexedDocsDatabase>) -> Result<()> {
56 self.extension
57 .call({
58 let id = self.id.clone();
59 |extension, store| {
60 async move {
61 let database_resource = store.data_mut().table().push(database)?;
62 extension
63 .call_index_docs(
64 store,
65 id.as_ref(),
66 package.as_ref(),
67 database_resource,
68 )
69 .await?
70 .map_err(|err| anyhow!("{err:?}"))?;
71
72 anyhow::Ok(())
73 }
74 .boxed()
75 }
76 })
77 .await
78 }
79}