wit.rs

  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}