1#![deny(unsafe_code)]
8#![warn(clippy::all, clippy::pedantic)]
9#![allow(clippy::module_name_repetitions)]
10#![doc = include_str!("../README.md")]
11
12pub mod core;
13mod error;
14pub mod kit;
15
16pub mod i18n;
17
18pub mod prelude;
19
20pub use error::TraitKitError;
21pub use error::TraitKitResult;
22
23#[cfg(feature = "async")]
24pub use core::AsyncAutoBuilder;
25#[cfg(feature = "async")]
26pub use kit::{AsyncKit, AsyncReady, AsyncUnbuilt};
27
28#[cfg(all(feature = "lifecycle", feature = "async"))]
29pub use core::AsyncLifecycle;
30#[cfg(feature = "lifecycle")]
31pub use core::Lifecycle;
32
33#[cfg(all(feature = "health", feature = "async"))]
34pub use core::AsyncHealthCheck;
35#[cfg(feature = "health")]
36pub use core::{HealthCheck, HealthStatus};
37
38#[cfg(feature = "observer")]
39pub use core::BuildObserver;
40
41#[cfg(all(feature = "scope", feature = "async"))]
42pub use kit::AsyncScope;
43#[cfg(feature = "scope")]
44pub use kit::Scope;
45
46#[cfg(all(feature = "shutdown", feature = "async"))]
47pub use kit::AsyncShutdownCoordinator;
48#[cfg(feature = "shutdown")]
49pub use kit::{ShutdownCoordinator, ShutdownPhase, ShutdownPhaseResult, ShutdownResult};
50
51#[cfg(all(test, feature = "async"))]
57pub(crate) mod test_helpers {
58 use std::future::Future;
59 use std::task::{self, Poll};
60
61 pub(crate) fn block_on<F: Future>(future: F) -> F::Output {
71 const MAX_POLLS: u32 = 1_000_000;
74
75 let waker = task::Waker::noop();
76 #[allow(clippy::needless_borrow)]
79 let mut cx = task::Context::from_waker(&waker);
80 let mut future = std::pin::pin!(future);
81 let mut polls = 0u32;
82 loop {
83 match future.as_mut().poll(&mut cx) {
84 Poll::Ready(v) => return v,
85 Poll::Pending => {
86 polls += 1;
87 assert!(
88 polls < MAX_POLLS,
89 "block_on: future did not complete within \
90 {MAX_POLLS} poll iterations (possible infinite loop)"
91 );
92 std::hint::spin_loop();
93 }
94 }
95 }
96 }
97
98 #[derive(Debug, thiserror::Error)]
100 #[allow(dead_code, reason = "mock error type verifies trait signature only")]
101 pub(crate) enum MockError {
102 #[error("mock build failed: {0}")]
103 Failed(String),
104 }
105
106 #[cfg(test)]
107 mod block_on_tests {
108 use super::*;
109 use std::sync::atomic::{AtomicU32, Ordering};
110 use std::task::Poll;
111
112 #[test]
113 fn block_on_handles_pending() {
114 static POLL_COUNT: AtomicU32 = AtomicU32::new(0);
115 POLL_COUNT.store(0, Ordering::SeqCst);
116
117 let result = block_on(std::future::poll_fn(|_cx| {
118 let n = POLL_COUNT.fetch_add(1, Ordering::SeqCst);
119 if n < 1 {
120 Poll::Pending
121 } else {
122 Poll::Ready(42)
123 }
124 }));
125 assert_eq!(result, 42);
126 assert!(POLL_COUNT.load(Ordering::SeqCst) >= 2);
127 }
128 }
129}