use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct StreamPolicy {
#[serde(default)]
pub collect: bool,
#[serde(default)]
pub parallel: bool,
#[serde(default)]
pub parallel_max: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RefConfig {
pub source: String,
pub var: String,
#[serde(default)]
pub transforms: Vec<RefTransform>,
#[serde(default)]
pub is_output: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub stream_policy: Option<StreamPolicy>,
}
#[derive(Debug, Clone)]
pub struct RefTransform {
pub name: String,
pub args: Vec<RefArg>,
}
impl Serialize for RefTransform {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeTuple;
let mut tup = serializer.serialize_tuple(2)?;
tup.serialize_element(&self.name)?;
tup.serialize_element(&self.args)?;
tup.end()
}
}
impl<'de> Deserialize<'de> for RefTransform {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let (name, args) = <(String, Vec<RefArg>)>::deserialize(deserializer)?;
Ok(RefTransform { name, args })
}
}
#[derive(Debug, Clone)]
pub enum RefArg {
Literal(Value),
NestedRef(Box<RefConfig>),
}
impl Serialize for RefArg {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
RefArg::Literal(v) => v.serialize(serializer),
RefArg::NestedRef(r) => {
use serde::ser::SerializeMap;
let mut map = serializer.serialize_map(Some(1))?;
map.serialize_entry("__ref__", r)?;
map.end()
}
}
}
}
impl<'de> Deserialize<'de> for RefArg {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let value = Value::deserialize(deserializer)?;
if let Value::Object(map) = &value {
if let Some(inner) = map.get("__ref__") {
let nested: RefConfig =
serde_json::from_value(inner.clone()).map_err(serde::de::Error::custom)?;
return Ok(RefArg::NestedRef(Box::new(nested)));
}
}
Ok(RefArg::Literal(value))
}
}