1use serde::{Deserialize, Serialize};
2use std::ops::Add;
3
4#[derive(Copy, Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
5pub enum ServiceState {
6 Stateful,
8 Stateless,
10}
11
12impl ServiceState {
13 pub fn stateful(&self) -> bool {
14 match self {
15 ServiceState::Stateless => false,
16 ServiceState::Stateful => true,
17 }
18 }
19
20 pub fn stateless(&self) -> bool {
21 !self.stateful()
22 }
23}
24
25#[derive(Clone, Debug, Serialize, Deserialize)]
26pub struct ServiceKey {
27 pub id: Option<u32>,
29 pub name: String,
31 pub ns: Option<String>,
33}
34
35impl ServiceKey {
36 pub fn new(name: String, ns: Option<String>) -> Self {
37 assert_ne!(name, "");
38 ServiceKey { id: None, name, ns }
39 }
40
41 pub fn id(&self) -> Option<u32> {
42 self.id
43 }
44
45 pub fn has_id(&self) -> bool {
46 self.id.is_some()
47 }
48
49 pub fn path(&self) -> Option<String> {
51 let id = self.id?;
52 Some(self.path_with_id(id))
53 }
54
55 pub fn path_with_id(&self, id: u32) -> String {
57 self.path_fn(id, |sk| {
58 format!("/{}/{}/{}", sk.ns(), sk.name, sk.id.unwrap())
59 })
60 }
61
62 pub fn path_fn(&self, id: u32, f: fn(ServiceKey) -> String) -> String {
63 let mut sk = self.clone();
64 sk.id = Some(id);
65 f(sk)
66 }
67
68 pub fn parent_path(&self) -> String {
70 self.parent_path_fn(|sk| format!("/{}/{}/", sk.ns(), sk.name))
71 }
72
73 pub fn parent_path_fn(&self, f: fn(ServiceKey) -> String) -> String {
74 f(self.clone())
75 }
76
77 pub fn root_path(&self) -> String {
79 self.root_fn(|sk| format!("/{}/", sk.ns()))
80 }
81
82 pub fn root_fn(&self, f: fn(ServiceKey) -> String) -> String {
83 f(self.clone())
84 }
85
86 pub fn parse(value: &str) -> Result<ServiceKey, ()> {
88 let v: Vec<&str> = value.trim().trim_start_matches('/').split('/').collect();
89 if v.len() != 3 {
90 return Err(());
91 }
92
93 let id = v[2].parse::<u32>().map_err(|_| ())?;
94 let v2: Vec<&str> = v[0].split('-').collect();
95
96 Ok(ServiceKey {
97 id: Some(id),
98 name: v[1].to_string(),
99 ns: if v2.len() == 1 {
100 None
101 } else {
102 Some(v2[0].to_string())
103 },
104 })
105 }
106
107 fn ns(&self) -> String {
108 self.ns
109 .clone()
110 .and_then(|s| Some(s.add("-service")))
111 .unwrap_or("service".to_string())
112 }
113}
114
115impl TryFrom<String> for ServiceKey {
116 type Error = String;
117 fn try_from(value: String) -> Result<Self, Self::Error> {
118 ServiceKey::parse(&value).map_err(|_| value)
119 }
120}
121
122impl<'a> TryFrom<&'a str> for ServiceKey {
123 type Error = &'a str;
124 fn try_from(value: &'a str) -> Result<Self, Self::Error> {
125 ServiceKey::parse(value).map_err(|_| value)
126 }
127}
128
129impl<'a> TryFrom<&'a [u8]> for ServiceKey {
130 type Error = &'a [u8];
131 fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
132 let v = std::str::from_utf8(value).map_err(|_| value)?;
133 ServiceKey::parse(v).map_err(|_| value)
134 }
135}
136
137#[derive(Clone, Debug, Serialize, Deserialize)]
138pub struct Service {
139 pub key: ServiceKey,
141 pub ttl: Option<i64>,
143 pub ip: Option<String>,
145 pub port: Option<u16>,
147 pub state: Option<ServiceState>,
149 pub category: Option<u32>,
151 pub extend: Option<String>,
153 #[serde(skip)]
155 pub revision: Option<i64>,
156}
157
158impl Service {
159 pub fn from_key(key: ServiceKey) -> Self {
160 Self {
161 key,
162 ttl: None,
163 ip: None,
164 port: None,
165 state: None,
166 category: None,
167 extend: None,
168 revision: None,
169 }
170 }
171
172 pub fn address(&self) -> String {
173 if self.ip.is_none() {
174 return String::new();
175 } else if self.port.is_none() {
176 return self.ip.as_ref().unwrap().clone();
177 } else {
178 format!(
179 "{}:{}",
180 self.ip.as_ref().unwrap(),
181 self.port.as_ref().unwrap()
182 )
183 }
184 }
185
186 pub fn ttl(mut self, ttl: Option<i64>) -> Self {
187 self.ttl = ttl;
188 self
189 }
190
191 pub fn ip(mut self, ip: Option<String>) -> Self {
192 self.ip = ip;
193 self
194 }
195
196 pub fn port(mut self, port: Option<u16>) -> Self {
197 self.port = port;
198 self
199 }
200
201 pub fn state(mut self, state: Option<ServiceState>) -> Self {
202 self.state = state;
203 self
204 }
205
206 pub fn category(mut self, category: Option<u32>) -> Self {
207 self.category = category;
208 self
209 }
210
211 pub fn extend(mut self, extend: Option<String>) -> Self {
212 self.extend = extend;
213 self
214 }
215}
216
217#[derive(Clone, Debug)]
218pub struct Services {
219 pub services: Vec<Service>,
221}
222
223impl Services {
224 pub fn new() -> Services {
225 Services { services: vec![] }
226 }
227}
228
229#[derive(Copy, Clone, Debug, Eq, PartialEq)]
231pub enum ServiceStatus {
232 Registered = 0,
234 Unregistered = 1,
236}
237
238impl ServiceStatus {
239 pub fn registered(&self) -> bool {
240 match self {
241 ServiceStatus::Registered => true,
242 ServiceStatus::Unregistered => false,
243 }
244 }
245
246 pub fn unregistered(&self) -> bool {
247 !self.registered()
248 }
249}
250
251impl From<u32> for ServiceStatus {
252 fn from(value: u32) -> Self {
253 match value {
254 0 => ServiceStatus::Registered,
255 1 => ServiceStatus::Unregistered,
256 _ => panic!("invalid value:{} for ServiceStatus", value),
257 }
258 }
259}