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}