scuffle_bootstrap/lib.rs
1//! A utility crate for creating binaries.
2//!
3//! Refer to [`Global`], [`Service`], and [`main`] for more information.
4//!
5//! ## Usage
6//!
7//! ```rust,no_run
8//! use std::sync::Arc;
9//!
10//! /// Our global state
11//! struct Global;
12//!
13//! // Required by the signal service
14//! impl scuffle_signal::SignalConfig for Global {}
15//!
16//! impl scuffle_bootstrap::global::GlobalWithoutConfig for Global {
17//! async fn init() -> anyhow::Result<Arc<Self>> {
18//! Ok(Arc::new(Self))
19//! }
20//! }
21//!
22//! /// Our own custom service
23//! struct MySvc;
24//!
25//! impl scuffle_bootstrap::service::Service<Global> for MySvc {
26//! async fn run(self, global: Arc<Global>, ctx: scuffle_context::Context) -> anyhow::Result<()> {
27//! # let _ = global;
28//! println!("running");
29//!
30//! // Do some work here
31//!
32//! // Wait for the context to be cacelled by the signal service
33//! ctx.done().await;
34//! Ok(())
35//! }
36//! }
37//!
38//! // This generates the main function which runs all the services
39//! scuffle_bootstrap::main! {
40//! Global {
41//! scuffle_signal::SignalSvc,
42//! MySvc,
43//! }
44//! }
45//! ```
46//!
47//! ## License
48//!
49//! This project is licensed under the [MIT](./LICENSE.MIT) or
50//! [Apache-2.0](./LICENSE.Apache-2.0) license. You can choose between one of
51//! them if you use this work.
52//!
53//! `SPDX-License-Identifier: MIT OR Apache-2.0`
54#![cfg_attr(all(coverage_nightly, test), feature(coverage_attribute))]
55
56pub mod config;
57pub mod global;
58pub mod service;
59
60pub use config::ConfigParser;
61#[doc(hidden)]
62pub use config::EmptyConfig;
63pub use global::{Global, GlobalWithoutConfig};
64pub use service::Service;
65
66#[doc(hidden)]
67pub mod prelude {
68 pub use {anyhow, futures, scuffle_bootstrap_derive, scuffle_context, tokio};
69}
70
71/// This macro is used to generate the main function for a given global type
72/// and service types. It will run all the services in parallel and wait for
73/// them to finish before exiting.
74///
75/// # Example
76///
77/// ```rust
78/// # use std::sync::Arc;
79/// # struct MyGlobal;
80/// # struct MyService;
81/// # impl scuffle_bootstrap::global::GlobalWithoutConfig for MyGlobal {
82/// # async fn init() -> anyhow::Result<Arc<Self>> {
83/// # Ok(Arc::new(Self))
84/// # }
85/// # }
86/// # impl scuffle_bootstrap::service::Service<MyGlobal> for MyService {
87/// # async fn run(self, global: Arc<MyGlobal>, ctx: scuffle_context::Context) -> anyhow::Result<()> {
88/// # println!("running");
89/// # ctx.done().await;
90/// # Ok(())
91/// # }
92/// # }
93/// # impl scuffle_signal::SignalConfig for MyGlobal {
94/// # }
95/// scuffle_bootstrap::main! {
96/// MyGlobal {
97/// scuffle_signal::SignalSvc,
98/// MyService,
99/// }
100/// }
101/// ```
102///
103/// # See Also
104///
105/// - [`Service`](crate::Service)
106/// - [`Global`](crate::Global)
107// We wrap the macro here so that the doc tests can be run & that the docs resolve for `Service` & `Global`
108#[macro_export]
109macro_rules! main {
110 ($($body:tt)*) => {
111 $crate::prelude::scuffle_bootstrap_derive::main! { $($body)* }
112 };
113}