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
64pub mod config;
65pub mod global;
66pub mod service;
67
68pub use config::ConfigParser;
69#[doc(hidden)]
70pub use config::EmptyConfig;
71pub use global::{Global, GlobalWithoutConfig};
72pub use service::Service;
73
74#[doc(hidden)]
75pub mod prelude {
76 pub use {anyhow, futures, scuffle_bootstrap_derive, scuffle_context, tokio};
77}
78
79/// This macro is used to generate the main function for a given global type
80/// and service types. It will run all the services in parallel and wait for
81/// them to finish before exiting.
82///
83/// # Example
84///
85/// ```rust
86/// # #[cfg(not(windows))]
87/// # {
88/// # use std::sync::Arc;
89/// # struct MyGlobal;
90/// # struct MyService;
91/// # impl scuffle_bootstrap::global::GlobalWithoutConfig for MyGlobal {
92/// # async fn init() -> anyhow::Result<Arc<Self>> {
93/// # Ok(Arc::new(Self))
94/// # }
95/// # }
96/// # impl scuffle_bootstrap::service::Service<MyGlobal> for MyService {
97/// # async fn run(self, global: Arc<MyGlobal>, ctx: scuffle_context::Context) -> anyhow::Result<()> {
98/// # println!("running");
99/// # ctx.done().await;
100/// # Ok(())
101/// # }
102/// # }
103/// # impl scuffle_signal::SignalConfig for MyGlobal {
104/// # }
105/// scuffle_bootstrap::main! {
106/// MyGlobal {
107/// scuffle_signal::SignalSvc,
108/// MyService,
109/// }
110/// }
111/// # }
112/// ```
113///
114/// # See Also
115///
116/// - [`Service`]
117/// - [`Global`]
118// We wrap the macro here so that the doc tests can be run & that the docs resolve for `Service` & `Global`
119#[macro_export]
120macro_rules! main {
121 ($($body:tt)*) => {
122 $crate::prelude::scuffle_bootstrap_derive::main! { $($body)* }
123 };
124}
125
126/// Changelogs generated by [scuffle_changelog]
127#[cfg(feature = "docs")]
128#[scuffle_changelog::changelog]
129pub mod changelog {}