use serde::{Deserialize, Serialize};
use crate::error::PluginError;
pub type PermissionClaim = String;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum IotClass {
LocalPush,
LocalPolling,
CloudPush,
CloudPolling,
AssumedState,
Calculated,
#[serde(other)]
Other,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum IntegrationType {
Integration,
Helper,
Entity,
#[serde(other)]
Other,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PluginManifest {
pub domain: String,
pub name: String,
pub version: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub documentation: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub iot_class: Option<IotClass>,
#[serde(default)]
pub config_flow: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub integration_type: Option<IntegrationType>,
#[serde(default)]
pub dependencies: Vec<String>,
#[serde(default)]
pub requirements: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wasm_module: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wasm_module_hash: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wasm_module_sig: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub publisher_key: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub min_homecore_version: Option<String>,
#[serde(default)]
pub host_imports_required: Vec<String>,
#[serde(default)]
pub homecore_permissions: Vec<PermissionClaim>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cog_id: Option<String>,
}
impl PluginManifest {
pub fn parse_json(s: &str) -> Result<Self, PluginError> {
let m: Self = serde_json::from_str(s)
.map_err(|e| PluginError::InvalidManifest(e.to_string()))?;
m.validate()?;
Ok(m)
}
fn validate(&self) -> Result<(), PluginError> {
if self.domain.trim().is_empty() {
return Err(PluginError::InvalidManifest(
"manifest `domain` must not be empty".into(),
));
}
if self.name.trim().is_empty() {
return Err(PluginError::InvalidManifest(
"manifest `name` must not be empty".into(),
));
}
if self.version.trim().is_empty() {
return Err(PluginError::InvalidManifest(
"manifest `version` must not be empty".into(),
));
}
Ok(())
}
}