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