wit.rs

  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}