use anyhow::Context;
use anyhow::Result;
use serde::Deserialize;
use serde::de::DeserializeOwned;
use std::collections::HashMap;
#[derive(Default, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
pub struct RuntimeTestConfig<T = HashMap<String, toml::Value>> {
#[serde(default)]
pub args: StringList,
#[serde(default)]
pub wasmtime_flags: StringList,
pub lang: Option<T>,
}
#[derive(Deserialize, Clone, Debug)]
#[serde(untagged)]
pub enum StringList {
String(String),
List(Vec<String>),
}
impl From<StringList> for Vec<String> {
fn from(list: StringList) -> Vec<String> {
match list {
StringList::String(s) => s.split_whitespace().map(|s| s.to_string()).collect(),
StringList::List(s) => s,
}
}
}
impl Default for StringList {
fn default() -> StringList {
StringList::List(Vec::new())
}
}
#[derive(Clone, Default, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
pub struct WitConfig {
#[serde(default, rename = "async")]
pub async_: bool,
#[serde(default)]
pub error_context: bool,
pub default_bindgen_args: Option<bool>,
pub runner: Option<String>,
pub dependencies: Option<StringList>,
pub wac: Option<String>,
}
impl WitConfig {
pub fn runner_world(&self) -> &str {
self.runner.as_deref().unwrap_or("runner")
}
pub fn dependency_worlds(&self) -> Vec<String> {
match self.dependencies.clone() {
Some(list) => list.into(),
None => vec!["test".to_string()],
}
}
}
pub fn parse_test_config<T>(contents: &str, comment: &str) -> Result<T>
where
T: DeserializeOwned,
{
let config_lines: Vec<_> = contents
.lines()
.take_while(|l| l.starts_with(comment))
.map(|l| &l[comment.len()..])
.collect();
let config_text = config_lines.join("\n");
toml::from_str(&config_text).context("failed to parse the test configuration")
}