use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct BehaviorConfig {
#[serde(rename = "$schema", skip_serializing_if = "Option::is_none")]
pub schema: Option<String>,
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub root: CompositionConfig,
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub configs: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum CompositionConfig {
Sequence {
children: Vec<CompositionConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
name: Option<String>,
},
Selector {
children: Vec<CompositionConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
name: Option<String>,
},
Parallel {
children: Vec<CompositionConfig>,
#[serde(default = "default_parallel_policy")]
policy: ParallelPolicyConfig,
#[serde(skip_serializing_if = "Option::is_none")]
name: Option<String>,
},
Node {
node: String,
#[serde(skip_serializing_if = "Option::is_none")]
config_ref: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
config: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
name: Option<String>,
},
}
fn default_parallel_policy() -> ParallelPolicyConfig {
ParallelPolicyConfig::RequireAll
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ParallelPolicyConfig {
RequireAll,
RequireOne,
RequireN(usize),
}
impl From<ParallelPolicyConfig> for crate::composition::ParallelPolicy {
fn from(config: ParallelPolicyConfig) -> Self {
match config {
ParallelPolicyConfig::RequireAll => crate::composition::ParallelPolicy::RequireAll,
ParallelPolicyConfig::RequireOne => crate::composition::ParallelPolicy::RequireOne,
ParallelPolicyConfig::RequireN(n) => crate::composition::ParallelPolicy::RequireN(n),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct NodeConfig {
pub node: String,
#[serde(default)]
pub config: serde_json::Value,
}
#[derive(Debug, Clone)]
pub struct NodeReference {
pub node_type: String,
pub config: serde_json::Value,
pub name: Option<String>,
}
impl BehaviorConfig {
pub fn from_json(json: &str) -> anyhow::Result<Self> {
Ok(serde_json::from_str(json)?)
}
pub fn from_file(path: impl AsRef<std::path::Path>) -> anyhow::Result<Self> {
let content = std::fs::read_to_string(path)?;
Self::from_json(&content)
}
pub fn to_json(&self) -> anyhow::Result<String> {
Ok(serde_json::to_string_pretty(self)?)
}
pub fn generate_schema() -> anyhow::Result<String> {
let schema = schemars::schema_for!(BehaviorConfig);
Ok(serde_json::to_string_pretty(&schema)?)
}
pub fn get_config(&self, key: &str) -> Option<&serde_json::Value> {
self.configs.get(key)
}
}