detector 0.5.4

A set of types for service registration and discovery.
Documentation
use crate::Meta;
use serde::{Deserialize, Serialize};
use std::ops::Add;

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ServiceKey {
    /// 服务实例唯一id
    pub id: Option<u32>,
    /// 服务名字
    pub name: String,
    /// 命名空间
    pub ns: String,
}

impl ServiceKey {
    pub fn new<S1: Into<String>, S2: Into<String>>(name: S1, ns: S2) -> Self {
        let name = name.into();
        assert_ne!(name.len(), 0);
        let ns = ns.into();
        ServiceKey { id: None, name, ns }
    }

    pub fn id(&self) -> Option<u32> {
        self.id
    }

    pub fn has_id(&self) -> bool {
        self.id.is_some()
    }

    /// 路径
    pub fn path(&self) -> Option<String> {
        let id = self.id?;
        Some(self.path_with_id(id))
    }

    /// 组成一个路径
    pub fn path_with_id(&self, id: u32) -> String {
        self.path_fn(id, |sk| {
            format!("/{}/{}/{}", sk.ns(), sk.name, sk.id.unwrap())
        })
    }

    pub fn path_fn(&self, id: u32, f: fn(ServiceKey) -> String) -> String {
        let mut sk = self.clone();
        sk.id = Some(id);
        f(sk)
    }

    /// 父路径
    pub fn parent_path(&self) -> String {
        self.parent_path_fn(|sk| format!("/{}/{}/", sk.ns(), sk.name))
    }

    pub fn parent_path_fn(&self, f: fn(ServiceKey) -> String) -> String {
        f(self.clone())
    }

    /// 根路径
    pub fn root_path(&self) -> String {
        self.root_fn(|sk| format!("/{}/", sk.ns()))
    }

    pub fn root_fn(&self, f: fn(ServiceKey) -> String) -> String {
        f(self.clone())
    }

    /// 格式:/[{ns}-]service/{name}/{id}
    pub fn parse(value: &str) -> Result<ServiceKey, ()> {
        let v: Vec<&str> = value.trim().trim_start_matches('/').split('/').collect();
        if v.len() != 3 {
            return Err(());
        }

        let id = v[2].parse::<u32>().map_err(|_| ())?;
        let v2: Vec<&str> = v[0].split('-').collect();

        Ok(ServiceKey {
            id: Some(id),
            name: v[1].to_string(),
            ns: if v2.len() == 1 {
                String::new()
            } else {
                v2[0].to_string()
            },
        })
    }

    fn ns(&self) -> String {
        if self.ns.is_empty() {
            "service".to_string()
        } else {
            self.ns.clone().add("-service")
        }
    }
}

impl TryFrom<String> for ServiceKey {
    type Error = String;
    fn try_from(value: String) -> Result<Self, Self::Error> {
        ServiceKey::parse(&value).map_err(|_| value)
    }
}

impl<'a> TryFrom<&'a str> for ServiceKey {
    type Error = &'a str;
    fn try_from(value: &'a str) -> Result<Self, Self::Error> {
        ServiceKey::parse(value).map_err(|_| value)
    }
}

impl<'a> TryFrom<&'a [u8]> for ServiceKey {
    type Error = &'a [u8];
    fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
        let v = std::str::from_utf8(value).map_err(|_| value)?;
        ServiceKey::parse(v).map_err(|_| value)
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Service {
    /// key
    pub key: ServiceKey,
    /// 元数据
    pub meta: Option<Meta>,
    /// ttl时间, 秒数
    pub ttl: Option<i64>,
    /// 服务地址
    pub ip: Option<String>,
    /// 服务端口
    pub port: Option<u16>,
    /// 扩展
    pub extend: Option<String>,
    /// 版本, 只读的
    #[serde(skip)]
    pub revision: Option<i64>,
}

impl Service {
    pub fn from_key(key: ServiceKey) -> Self {
        Self {
            key,
            meta: None,
            ttl: None,
            ip: None,
            port: None,
            extend: None,
            revision: None,
        }
    }

    pub fn address(&self) -> String {
        if self.ip.is_none() {
            return String::new();
        } else if self.port.is_none() {
            return self.ip.as_ref().unwrap().clone();
        } else {
            format!(
                "{}:{}",
                self.ip.as_ref().unwrap(),
                self.port.as_ref().unwrap()
            )
        }
    }

    pub fn ttl(mut self, ttl: Option<i64>) -> Self {
        self.ttl = ttl;
        self
    }

    pub fn ip<S: Into<String>>(mut self, ip: Option<S>) -> Self {
        self.ip = ip.map(|ip| ip.into());
        self
    }

    pub fn port(mut self, port: Option<u16>) -> Self {
        self.port = port;
        self
    }

    pub fn extend<T: Into<String>>(mut self, extend: Option<T>) -> Self {
        self.extend = extend.map(|s| s.into());
        self
    }
}

#[derive(Clone, Debug)]
pub struct Services {
    /// 服务实例列表
    pub services: Vec<Service>,
}

impl Services {
    pub fn new() -> Services {
        Services { services: vec![] }
    }
}

/// 服务状态
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ServiceStatus {
    /// 已注册
    Registered = 0,
    /// 未注册
    Unregistered = 1,
}

impl ServiceStatus {
    pub fn registered(&self) -> bool {
        match self {
            ServiceStatus::Registered => true,
            ServiceStatus::Unregistered => false,
        }
    }

    pub fn unregistered(&self) -> bool {
        !self.registered()
    }
}

impl From<u32> for ServiceStatus {
    fn from(value: u32) -> Self {
        match value {
            0 => ServiceStatus::Registered,
            1 => ServiceStatus::Unregistered,
            _ => panic!("invalid value:{} for ServiceStatus", value),
        }
    }
}