use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct HostManifest {
#[serde(default)]
pub externals: Vec<ManifestExternal>,
#[serde(default)]
pub types: Vec<SemanticTypeDef>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ManifestExternal {
pub name: String,
#[serde(default)]
pub params: Vec<ManifestParam>,
#[serde(default)]
pub returns: TypeRef,
#[serde(default)]
pub kind: ExternalKind,
#[serde(default)]
pub doc: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ManifestParam {
pub name: String,
#[serde(default)]
pub ty: TypeRef,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SemanticTypeDef {
pub name: String,
pub base: BaseType,
#[serde(default)]
pub constraint: Option<Constraint>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "kind")]
pub enum Constraint {
Enum { values: Vec<String> },
Regex { pattern: String },
Range {
#[serde(default)]
min: Option<i64>,
#[serde(default)]
max: Option<i64>,
},
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(transparent)]
pub struct TypeRef(pub String);
impl TypeRef {
#[must_use]
pub fn is_unspecified(&self) -> bool {
self.0.trim().is_empty()
}
#[must_use]
pub fn as_base(&self) -> Option<BaseType> {
BaseType::from_keyword(self.0.trim())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum BaseType {
String,
Int,
Float,
Bool,
Void,
}
impl BaseType {
#[must_use]
pub fn from_keyword(s: &str) -> Option<Self> {
match s.to_ascii_lowercase().as_str() {
"string" => Some(Self::String),
"int" => Some(Self::Int),
"float" => Some(Self::Float),
"bool" => Some(Self::Bool),
"void" => Some(Self::Void),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ExternalKind {
Query,
Effect,
Presentation,
#[default]
Plain,
}
impl ExternalKind {
#[must_use]
pub fn from_tag(s: &str) -> Option<Self> {
match s.to_ascii_lowercase().as_str() {
"query" => Some(Self::Query),
"effect" => Some(Self::Effect),
"presentation" => Some(Self::Presentation),
"plain" => Some(Self::Plain),
_ => None,
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct DocBlock {
pub doc: Option<String>,
pub params: Vec<(String, TypeRef)>,
pub returns: Option<TypeRef>,
pub kind: Option<ExternalKind>,
}