use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Endpoint {
Simple(String),
Weighted {
address: String,
#[serde(default = "default_weight")]
weight: u32,
},
}
fn default_weight() -> u32 {
1
}
impl Endpoint {
pub fn address(&self) -> &str {
match self {
Self::Simple(s) => s,
Self::Weighted { address, .. } => address,
}
}
pub fn weight(&self) -> u32 {
match self {
Self::Simple(_) => 1,
Self::Weighted { weight, .. } => *weight,
}
}
}
impl From<String> for Endpoint {
fn from(s: String) -> Self {
Self::Simple(s)
}
}
impl From<&str> for Endpoint {
fn from(s: &str) -> Self {
Self::Simple(s.to_owned())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn simple_endpoint_has_weight_one() {
let ep: Endpoint = "10.0.0.1:8080".into();
assert_eq!(ep.address(), "10.0.0.1:8080", "simple endpoint address mismatch");
assert_eq!(ep.weight(), 1, "simple endpoint should default to weight 1");
}
#[test]
fn weighted_endpoint_preserves_weight() {
let yaml = r#"
address: "10.0.0.2:8080"
weight: 3
"#;
let ep: Endpoint = serde_yaml::from_str(yaml).unwrap();
assert_eq!(ep.address(), "10.0.0.2:8080", "weighted endpoint address mismatch");
assert_eq!(ep.weight(), 3, "weighted endpoint should preserve configured weight");
}
#[test]
fn weighted_endpoint_defaults_weight_to_one() {
let yaml = "address: \"10.0.0.1:80\"";
let ep: Endpoint = serde_yaml::from_str(yaml).unwrap();
assert_eq!(ep.weight(), 1, "omitted weight should default to 1");
}
#[test]
fn from_string() {
let ep = Endpoint::from("10.0.0.1:80".to_owned());
assert_eq!(ep.address(), "10.0.0.1:80", "From<String> should preserve address");
}
#[test]
fn parse_mixed_list() {
let yaml = r#"
- "10.0.0.1:8080"
- address: "10.0.0.2:8080"
weight: 3
"#;
let eps: Vec<Endpoint> = serde_yaml::from_str(yaml).unwrap();
assert_eq!(eps.len(), 2, "mixed list should parse two endpoints");
assert_eq!(eps[0].weight(), 1, "simple entry should have weight 1");
assert_eq!(eps[1].weight(), 3, "weighted entry should have weight 3");
}
}