iocaine 2.4.0

The deadliest poison known to AI
Documentation
// SPDX-FileCopyrightText: 2025 Gergely Nagy
// SPDX-FileContributor: Gergely Nagy
//
// SPDX-License-Identifier: MIT

use regex::Regex;
use serde::Deserialize;

#[derive(Clone, Debug, Deserialize)]
pub struct MetricsConfig {
    #[serde(default)]
    pub enable: bool,
    #[serde(default, rename = "persist-path")]
    pub persist_path: Option<String>,
    #[serde(default)]
    pub labels: Vec<MetricsLabel>,
    #[serde(default = "MetricsConfig::default_bind")]
    pub bind: tokio_listener::ListenerAddress,
    #[serde(default)]
    pub agent_group: Vec<AgentGroupConfig>,
}

impl MetricsConfig {
    fn default_bind() -> tokio_listener::ListenerAddress {
        "127.0.0.1:42042".parse().unwrap()
    }
}

impl Default for MetricsConfig {
    fn default() -> Self {
        Self {
            enable: Default::default(),
            persist_path: None,
            labels: Vec::default(),
            bind: Self::default_bind(),
            agent_group: Vec::default(),
        }
    }
}

#[derive(Clone, Debug, Deserialize, PartialEq)]
pub enum MetricsLabel {
    #[serde(alias = "host")]
    Host,
    #[serde(alias = "user-agent")]
    UserAgent,
    #[serde(alias = "user-agent-group")]
    UserAgentGroup,
    #[serde(alias = "verdict")]
    Verdict,
}

#[derive(Clone, Debug, Deserialize)]
pub struct AgentGroupConfig {
    #[serde(with = "serde_regex")]
    pub agent: Regex,
    pub group: String,
}

impl PartialEq for AgentGroupConfig {
    fn eq(&self, other: &Self) -> bool {
        self.group == other.group && self.agent.as_str() == other.agent.as_str()
    }
}