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 {}