1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
// RGB standard library // Written in 2020 by // Dr. Maxim Orlovsky <orlovsky@pandoracore.com> // // To the extent possible under law, the author(s) have dedicated all // copyright and related and neighboring rights to this software to // the public domain worldwide. This software is distributed without // any warranty. // // You should have received a copy of the MIT License // along with this software. // If not, see <https://opensource.org/licenses/MIT>. use std::error::Error; /// Trait for simpler service implementation with run loops #[async_trait] pub trait Service { /// Run loop for the service, which must never return. If you have a run /// loop that may fail, use [`TryService`] trait istead async fn run_loop(self); } /// Trait for simpler service implementation with run loops which may fail with /// `TryService::ErrorType` errors; otherwise they should never return #[async_trait] pub trait TryService: Sized { /// Type of the error which is produced in case of service failure and /// is returned from the internal [`try_run_loop()`] procedure type ErrorType: Error; /// NB: Do not reimplement this one: the function keeps in check that if the /// failure happens during run loop, the program will panic reporting the /// failure. To implement the actual run loop please provide implementation /// for [`try_run_loop()`] async fn run_or_panic(self, service_name: &str) { let should_not_return = self.try_run_loop().await; let msg = handle_failure(service_name, should_not_return); panic!(msg) } /// Main failable run loop implementation. Must produce an error of type /// [`TryService::ErrorType`] or never return. async fn try_run_loop(self) -> Result<(), Self::ErrorType>; } /// Marker trait that can be implemented for data structures used by `Clap` or /// by any other form of API handling. pub trait Exec { /// Runtime context data type, that is provided for execution context. type Runtime: Sized; /// Error type that may result from the execution type Error: ::std::error::Error; /// Main execution routine fn exec(&self, runtime: &mut Self::Runtime) -> Result<(), Self::Error>; } fn handle_failure<T>( service_name: &str, result: Result<T, impl ::std::error::Error>, ) -> String { match result { Err(err) => { format!("{} run loop has failed with error {}", service_name, err) } Ok(_) => { format!("{} has failed without reporting a error", service_name) } } }