scuffle_bootstrap/
lib.rs

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