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