1mod v0_0_1;
2mod v0_0_4;
3
4use super::{wasm_engine, WasmState};
5use anyhow::{Context, Result};
6use language::LspAdapterDelegate;
7use semantic_version::SemanticVersion;
8use std::sync::Arc;
9use wasmtime::{
10 component::{Component, Instance, Linker, Resource},
11 Store,
12};
13
14use v0_0_4 as latest;
15
16pub use latest::{Command, LanguageServerConfig};
17
18pub fn new_linker(
19 f: impl Fn(&mut Linker<WasmState>, fn(&mut WasmState) -> &mut WasmState) -> Result<()>,
20) -> Linker<WasmState> {
21 let mut linker = Linker::new(&wasm_engine());
22 wasmtime_wasi::command::add_to_linker(&mut linker).unwrap();
23 f(&mut linker, wasi_view).unwrap();
24 linker
25}
26
27fn wasi_view(state: &mut WasmState) -> &mut WasmState {
28 state
29}
30
31/// Returns whether the given Wasm API version is supported by the Wasm host.
32pub fn is_supported_wasm_api_version(version: SemanticVersion) -> bool {
33 v0_0_1::VERSION <= version && version <= v0_0_4::VERSION
34}
35
36pub enum Extension {
37 V004(v0_0_4::Extension),
38 V001(v0_0_1::Extension),
39}
40
41impl Extension {
42 pub async fn instantiate_async(
43 store: &mut Store<WasmState>,
44 version: SemanticVersion,
45 component: &Component,
46 ) -> Result<(Self, Instance)> {
47 if version < latest::VERSION {
48 let (extension, instance) =
49 v0_0_1::Extension::instantiate_async(store, &component, v0_0_1::linker())
50 .await
51 .context("failed to instantiate wasm extension")?;
52 Ok((Self::V001(extension), instance))
53 } else {
54 let (extension, instance) =
55 v0_0_4::Extension::instantiate_async(store, &component, v0_0_4::linker())
56 .await
57 .context("failed to instantiate wasm extension")?;
58 Ok((Self::V004(extension), instance))
59 }
60 }
61
62 pub async fn call_init_extension(&self, store: &mut Store<WasmState>) -> Result<()> {
63 match self {
64 Extension::V004(ext) => ext.call_init_extension(store).await,
65 Extension::V001(ext) => ext.call_init_extension(store).await,
66 }
67 }
68
69 pub async fn call_language_server_command(
70 &self,
71 store: &mut Store<WasmState>,
72 config: &LanguageServerConfig,
73 resource: Resource<Arc<dyn LspAdapterDelegate>>,
74 ) -> Result<Result<Command, String>> {
75 match self {
76 Extension::V004(ext) => {
77 ext.call_language_server_command(store, config, resource)
78 .await
79 }
80 Extension::V001(ext) => Ok(ext
81 .call_language_server_command(store, &config.clone().into(), resource)
82 .await?
83 .map(|command| command.into())),
84 }
85 }
86
87 pub async fn call_language_server_initialization_options(
88 &self,
89 store: &mut Store<WasmState>,
90 config: &LanguageServerConfig,
91 resource: Resource<Arc<dyn LspAdapterDelegate>>,
92 ) -> Result<Result<Option<String>, String>> {
93 match self {
94 Extension::V004(ext) => {
95 ext.call_language_server_initialization_options(store, config, resource)
96 .await
97 }
98 Extension::V001(ext) => {
99 ext.call_language_server_initialization_options(
100 store,
101 &config.clone().into(),
102 resource,
103 )
104 .await
105 }
106 }
107 }
108}