use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum ConfigRef {
Qualified {
ref_type: String,
name: String,
recreate: bool,
},
Unqualified {
name: String,
recreate: bool,
},
SystemId {
id: String,
},
Literal(String),
}
impl ConfigRef {
pub fn effective_name(&self) -> &str {
match self {
Self::Qualified { name, .. } => name,
Self::Unqualified { name, .. } => name,
Self::SystemId { id } => id,
Self::Literal(s) => s,
}
}
pub fn should_recreate(&self) -> bool {
match self {
Self::Qualified { recreate, .. } => *recreate,
Self::Unqualified { recreate, .. } => *recreate,
Self::SystemId { .. } => false,
Self::Literal(_) => true,
}
}
pub fn is_reference(&self) -> bool {
!matches!(self, Self::Literal(_))
}
}
pub fn parse_config_ref(s: &str) -> ConfigRef {
let trimmed = s.trim();
if !trimmed.starts_with("{{") || !trimmed.ends_with("}}") {
return ConfigRef::Literal(s.to_string());
}
let inner = &trimmed[2..trimmed.len() - 2];
if inner.is_empty() {
return ConfigRef::Literal(s.to_string());
}
if inner.starts_with('#') && inner.ends_with('#') && inner.len() > 2 {
let id = &inner[1..inner.len() - 1];
return ConfigRef::SystemId { id: id.to_string() };
}
if inner.starts_with('%') && inner.ends_with('%') && inner.len() > 2 {
let body = &inner[1..inner.len() - 1];
return parse_qualified_or_unqualified(body, false);
}
parse_qualified_or_unqualified(inner, true)
}
fn parse_qualified_or_unqualified(body: &str, recreate: bool) -> ConfigRef {
if let Some(dot_pos) = body.find('.') {
let ref_type = &body[..dot_pos];
let name = &body[dot_pos + 1..];
if !ref_type.is_empty() && !name.is_empty() {
return ConfigRef::Qualified {
ref_type: ref_type.to_string(),
name: name.to_string(),
recreate,
};
}
}
ConfigRef::Unqualified {
name: body.to_string(),
recreate,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_qualified_recreate() {
assert_eq!(
parse_config_ref("{{agent_profile.coder}}"),
ConfigRef::Qualified {
ref_type: "agent_profile".into(),
name: "coder".into(),
recreate: true,
}
);
}
#[test]
fn test_qualified_no_recreate() {
assert_eq!(
parse_config_ref("{{%provider.openai%}}"),
ConfigRef::Qualified {
ref_type: "provider".into(),
name: "openai".into(),
recreate: false,
}
);
}
#[test]
fn test_unqualified_recreate() {
assert_eq!(
parse_config_ref("{{coder}}"),
ConfigRef::Unqualified {
name: "coder".into(),
recreate: true,
}
);
}
#[test]
fn test_unqualified_no_recreate() {
assert_eq!(
parse_config_ref("{{%coder%}}"),
ConfigRef::Unqualified {
name: "coder".into(),
recreate: false,
}
);
}
#[test]
fn test_system_id() {
assert_eq!(
parse_config_ref("{{#fctsidd-abc-123#}}"),
ConfigRef::SystemId {
id: "fctsidd-abc-123".into(),
}
);
}
#[test]
fn test_literal() {
assert_eq!(
parse_config_ref("just-a-string"),
ConfigRef::Literal("just-a-string".into())
);
}
#[test]
fn test_empty_braces() {
assert_eq!(parse_config_ref("{{}}"), ConfigRef::Literal("{{}}".into()));
}
#[test]
fn test_effective_name() {
let r = parse_config_ref("{{agent_profile.coder}}");
assert_eq!(r.effective_name(), "coder");
let r = parse_config_ref("{{%coder%}}");
assert_eq!(r.effective_name(), "coder");
let r = parse_config_ref("{{#sys-id#}}");
assert_eq!(r.effective_name(), "sys-id");
}
#[test]
fn test_should_recreate() {
assert!(parse_config_ref("{{coder}}").should_recreate());
assert!(parse_config_ref("{{agent_profile.coder}}").should_recreate());
assert!(!parse_config_ref("{{%coder%}}").should_recreate());
assert!(!parse_config_ref("{{#sys-id#}}").should_recreate());
}
}