1#![no_std]
31#![warn(missing_docs)]
32#![warn(clippy::all)]
33#![allow(clippy::module_name_repetitions)]
34#![allow(clippy::missing_errors_doc)]
35#![allow(clippy::missing_panics_doc)]
36#![allow(clippy::struct_field_names)]
37#![allow(clippy::must_use_candidate)]
38#![allow(clippy::return_self_not_must_use)]
39#![allow(clippy::needless_pass_by_value)]
40#![allow(clippy::option_if_let_else)]
41#![allow(clippy::implicit_clone)]
42#![allow(clippy::manual_string_new)]
43#![allow(clippy::uninlined_format_args)]
44
45extern crate no_std_compat as std;
46
47use std::prelude::v1::*;
48
49pub use async_trait::async_trait;
50
51use std::fmt::{Debug, Formatter};
52use std::sync::Arc;
53use parking_lot::Mutex;
54
55use serde::{Deserialize, Serialize};
56
57#[cfg(feature = "std_base")]
58mod features;
59mod services;
60
61#[cfg(feature = "std_base")]
62pub use features::Features;
63#[cfg(feature = "std_base")]
64use product_os_router::{Body, ProductOSRouter, Response};
65#[cfg(feature = "std_base")]
66use serde_json::Value;
67pub use services::Services;
68
69#[cfg(feature = "std_base")]
74pub fn now_millis() -> i64 {
75 std::time::SystemTime::now()
76 .duration_since(std::time::SystemTime::UNIX_EPOCH)
77 .map(|d| d.as_millis() as i64)
78 .unwrap_or(0)
79}
80
81#[cfg(not(feature = "std_base"))]
83pub fn now_millis() -> i64 {
84 0
85}
86
87#[cfg(feature = "std_base")]
92#[derive(Deserialize, Serialize)]
93#[serde(rename_all = "camelCase")]
94pub struct RegistryFeature {
95 pub identifier: String,
97 pub paths: Vec<String>,
99 #[serde(skip, default = "default_feature")]
101 pub feature: Option<Arc<dyn Feature>>,
102 #[serde(skip, default = "default_feature_mut")]
104 pub feature_mut: Option<Arc<Mutex<dyn Feature>>>
105}
106
107#[cfg(feature = "std_base")]
108impl Debug for RegistryFeature {
109 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
110 write!(f, "Identifier: {}\nPaths: {:?}\n", self.identifier, self.paths)
111 }
112}
113
114#[cfg(feature = "std_base")]
115fn default_feature() -> Option<Arc<dyn Feature>> {
116 Some(Arc::new(DefaultFeature {}))
117}
118
119#[cfg(feature = "std_base")]
120fn default_feature_mut() -> Option<Arc<Mutex<dyn Feature>>> {
121 Some(Arc::new(Mutex::new(DefaultFeature {})))
122}
123
124pub enum What {
126 Characteristic(String),
128 Id(u8)
130}
131
132#[derive(Deserialize, Serialize)]
137#[serde(rename_all = "camelCase")]
138pub struct RegistryService {
139 pub identifier: String,
141 pub key: String,
143 #[serde(rename = "type")]
145 pub kind: String,
146 pub active: bool,
148 pub enabled: bool,
150 pub created_at: i64,
152 pub updated_at: i64,
154 #[serde(skip, default = "default_service")]
156 pub service: Option<Arc<dyn Service>>,
157 #[serde(skip, default = "default_service_mut")]
159 pub service_mut: Option<Arc<Mutex<dyn Service>>>
160}
161
162impl Debug for RegistryService {
163 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
164 write!(f, "Identifier: {}\nKey: {}\nEnabled: {}\nActive:{:?}", self.identifier, self.key, self.enabled, self.active)
165 }
166}
167
168const LOCK_TIMEOUT: core::time::Duration = core::time::Duration::new(10, 0);
169
170macro_rules! delegate_lifecycle {
171 ($self:ident, $immutable_method:ident) => {{
172 if let Some(service) = &$self.service {
173 return service.$immutable_method().await;
174 }
175 if let Some(service_arc) = &$self.service_mut {
176 let service_clone = service_arc.clone();
177 let locked = service_clone.try_lock_for(LOCK_TIMEOUT);
178 if let Some(guard) = locked {
179 return guard.$immutable_method().await;
180 }
181 }
182 Err(())
183 }};
184 ($self:ident, $immutable_method:ident, $mutable_method:ident) => {{
185 if let Some(service) = &$self.service {
186 return service.$immutable_method().await;
187 }
188 if let Some(service_arc) = &$self.service_mut {
189 let service_clone = service_arc.clone();
190 let locked = service_clone.try_lock_for(LOCK_TIMEOUT);
191 if let Some(mut guard) = locked {
192 return guard.$mutable_method().await;
193 }
194 }
195 Err(())
196 }};
197}
198
199impl RegistryService {
200 pub fn identifier(&self) -> &str {
202 &self.identifier
203 }
204
205 pub fn key(&self) -> &str {
207 &self.key
208 }
209
210 #[deprecated(since = "0.0.28", note = "use identifier() which now returns &str; call .to_owned() if you need a String")]
212 pub fn identifier_owned(&self) -> String {
213 self.identifier.to_owned()
214 }
215
216 #[deprecated(since = "0.0.28", note = "use key() which now returns &str; call .to_owned() if you need a String")]
218 pub fn key_owned(&self) -> String {
219 self.key.to_owned()
220 }
221
222 pub fn is_enabled(&self) -> bool {
224 self.enabled
225 }
226
227 pub fn is_active(&self) -> bool {
229 self.active
230 }
231
232 #[allow(clippy::await_holding_lock)]
236 pub async fn status(&self) -> Result<(), ()> {
237 delegate_lifecycle!(self, status)
238 }
239
240 #[allow(clippy::await_holding_lock)]
244 pub async fn init(&mut self) -> Result<(), ()> {
245 delegate_lifecycle!(self, init_service, init_service_mut)
246 }
247
248 #[allow(clippy::await_holding_lock)]
252 pub async fn start(&mut self) -> Result<(), ()> {
253 delegate_lifecycle!(self, start, start_mut)
254 }
255
256 #[allow(clippy::await_holding_lock)]
260 pub async fn stop(&mut self) -> Result<(), ()> {
261 delegate_lifecycle!(self, stop, stop_mut)
262 }
263
264 #[allow(clippy::await_holding_lock)]
268 pub async fn restart(&mut self) -> Result<(), ()> {
269 delegate_lifecycle!(self, restart, restart_mut)
270 }
271
272 #[allow(clippy::await_holding_lock)]
276 pub async fn call(&mut self, action: &What, input: &Option<serde_json::Value>) -> Result<Option<serde_json::Value>, ServiceError> {
277 if let Some(service) = &self.service {
278 return service.call(action, input).await;
279 }
280 if let Some(service_arc) = &self.service_mut {
281 let service_clone = service_arc.clone();
282 let locked = service_clone.try_lock_for(LOCK_TIMEOUT);
283 if let Some(mut guard) = locked {
284 return guard.call_mut(action, input).await;
285 }
286 return Err(ServiceError::LockTimeout);
287 }
288 Err(ServiceError::GenericError("No service set".to_string()))
289 }
290}
291
292fn default_service() -> Option<Arc<dyn Service>> {
293 Some(Arc::new(DefaultService {}))
294}
295
296fn default_service_mut() -> Option<Arc<Mutex<dyn Service>>> {
297 Some(Arc::new(Mutex::new(DefaultService {})))
298}
299
300#[cfg(feature = "std_base")]
309#[async_trait]
310pub trait Feature: Send + Sync {
311 async fn register(&self, feature: Arc<dyn Feature>, base_path: String, router: &mut product_os_router::ProductOSRouter) -> RegistryFeature;
313 async fn register_mut(&self, feature: Arc<Mutex<dyn Feature>>, base_path: String, router: &mut product_os_router::ProductOSRouter) -> RegistryFeature;
315 fn identifier(&self) -> String;
317 async fn request(&self, action: &What, input: &Option<serde_json::Value>, semver: &str) -> Response<Body>;
319 async fn request_mut(&mut self, action: &What, input: &Option<serde_json::Value>, semver: &str) -> Response<Body>;
321 async fn init_feature(&self) -> Result<(), ()> { Ok(()) }
323 async fn init_feature_mut(&mut self) -> Result<(), ()> { Ok(()) }
325}
326
327#[cfg(feature = "std_base")]
331pub struct DefaultFeature {}
332
333#[cfg(feature = "std_base")]
334#[async_trait]
335impl Feature for DefaultFeature {
336 async fn register(&self, feature: Arc<dyn Feature>, _: String, _: &mut ProductOSRouter) -> RegistryFeature {
337 RegistryFeature {
338 identifier: "".to_string(),
339 paths: vec![],
340 feature: Some(feature),
341 feature_mut: None
342 }
343 }
344
345 async fn register_mut(&self, feature: Arc<Mutex<dyn Feature>>, _: String, _: &mut ProductOSRouter) -> RegistryFeature {
346 RegistryFeature {
347 identifier: "".to_string(),
348 paths: vec![],
349 feature: None,
350 feature_mut: Some(feature)
351 }
352 }
353
354 fn identifier(&self) -> String {
355 "default".to_string()
356 }
357
358 async fn request(&self, _action: &What, _input: &Option<Value>, _semver: &str) -> Response<Body> {
359 Response::default()
360 }
361
362 async fn request_mut(&mut self, _action: &What, _input: &Option<Value>, _semver: &str) -> Response<Body> {
363 Response::default()
364 }
365}
366
367#[derive(Debug, Clone)]
369pub enum ServiceError {
370 GenericError(String),
372 LockTimeout,
374 NotFound,
376 InvalidState(String),
378}
379
380impl std::fmt::Display for ServiceError {
381 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
382 match self {
383 ServiceError::GenericError(s) => write!(f, "{}", s),
384 ServiceError::LockTimeout => write!(f, "Failed to acquire service lock within timeout"),
385 ServiceError::NotFound => write!(f, "Service not found"),
386 ServiceError::InvalidState(s) => write!(f, "Invalid service state: {}", s),
387 }
388 }
389}
390
391impl std::error::Error for ServiceError {}
392
393#[derive(Debug, Clone)]
395pub enum FeatureError {
396 GenericError(String),
398 LockTimeout,
400 NotFound,
402 RouterInsertError {
404 identifier: String,
406 path: String,
408 details: String
410 },
411 MultipleFallbacks {
413 identifier: String
415 },
416}
417
418impl std::fmt::Display for FeatureError {
419 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
420 match self {
421 FeatureError::GenericError(s) => write!(f, "{}", s),
422 FeatureError::LockTimeout => write!(f, "Failed to acquire feature lock within timeout"),
423 FeatureError::NotFound => write!(f, "Feature not found"),
424 FeatureError::RouterInsertError { identifier, path, details } => {
425 write!(f, "Failed to insert path '{}' for feature '{}': {}", path, identifier, details)
426 }
427 FeatureError::MultipleFallbacks { identifier } => {
428 write!(f, "Cannot set fallback route for '{}': fallback already defined", identifier)
429 }
430 }
431 }
432}
433
434impl std::error::Error for FeatureError {}
435
436#[async_trait]
442pub trait Service: Send + Sync {
443 async fn register(&self, service: Arc<dyn Service>) -> RegistryService;
445 async fn register_mut(&self, service: Arc<Mutex<dyn Service>>) -> RegistryService;
447 fn identifier(&self) -> String;
449 fn key(&self) -> String;
451 fn is_enabled(&self) -> bool;
453 fn is_active(&self) -> bool;
455 async fn status(&self) -> Result<(), ()>;
457 async fn init_service(&self) -> Result<(), ()> { Ok(()) }
459 async fn start(&self) -> Result<(), ()>;
461 async fn stop(&self) -> Result<(), ()>;
463 async fn call(&self, _action: &What, _input: &Option<serde_json::Value>) -> Result<Option<serde_json::Value>, ServiceError> {
465 Ok(None)
466 }
467 async fn restart(&self) -> Result<(), ()>;
469 async fn init_service_mut(&mut self) -> Result<(), ()> { Ok(()) }
471 async fn start_mut(&mut self) -> Result<(), ()>;
473 async fn stop_mut(&mut self) -> Result<(), ()>;
475 async fn restart_mut(&mut self) -> Result<(), ()>;
477 async fn call_mut(&mut self, _action: &What, _input: &Option<serde_json::Value>) -> Result<Option<serde_json::Value>, ServiceError> {
479 Ok(None)
480 }
481}
482
483pub struct DefaultService {}
487
488#[async_trait]
489impl Service for DefaultService {
490 async fn register(&self, service: Arc<dyn Service>) -> RegistryService {
491 RegistryService {
492 identifier: "".to_string(),
493 key: "".to_string(),
494 kind: "".to_string(),
495 active: false,
496 enabled: false,
497 created_at: now_millis(),
498 updated_at: now_millis(),
499 service: Some(service),
500 service_mut: None
501 }
502 }
503
504 async fn register_mut(&self, service: Arc<Mutex<dyn Service>>) -> RegistryService {
505 RegistryService {
506 identifier: "".to_string(),
507 key: "".to_string(),
508 kind: "".to_string(),
509 active: false,
510 enabled: false,
511 created_at: now_millis(),
512 updated_at: now_millis(),
513 service: None,
514 service_mut: Some(service)
515 }
516 }
517
518 fn identifier(&self) -> String {
519 "default".to_string()
520 }
521
522 fn key(&self) -> String {
523 "key".to_string()
524 }
525
526 fn is_enabled(&self) -> bool {
527 false
528 }
529
530 fn is_active(&self) -> bool {
531 false
532 }
533
534 async fn status(&self) -> Result<(), ()> { Ok(()) }
535
536 async fn init_service(&self) -> Result<(), ()> { Ok(()) }
537
538 async fn start(&self) -> Result<(), ()> { Ok(()) }
539
540 async fn stop(&self) -> Result<(), ()> { Ok(()) }
541
542 async fn restart(&self) -> Result<(), ()> { Ok(()) }
543
544 async fn call(&self, _action: &What, _input: &Option<serde_json::Value>) -> Result<Option<serde_json::Value>, ServiceError> {
545 Ok(None)
546 }
547
548 async fn init_service_mut(&mut self) -> Result<(), ()> { Ok(()) }
549
550 async fn start_mut(&mut self) -> Result<(), ()> { Ok(()) }
551
552 async fn stop_mut(&mut self) -> Result<(), ()> { Ok(()) }
553
554 async fn restart_mut(&mut self) -> Result<(), ()> { Ok(()) }
555
556 async fn call_mut(&mut self, _action: &What, _input: &Option<serde_json::Value>) -> Result<Option<serde_json::Value>, ServiceError> {
557 Ok(None)
558 }
559}
560
561#[cfg(all(feature = "std_base", feature = "feature_service"))]
565pub trait FeatureService: Feature + Service {}