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 = "observability")]
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(test, feature = "async"))]
52pub(crate) mod test_helpers {
53 use std::future::Future;
54 use std::task::{self, Poll};
55
56 pub(crate) fn block_on<F: Future>(future: F) -> F::Output {
66 const MAX_POLLS: u32 = 1_000_000;
69
70 let waker = task::Waker::noop();
71 #[allow(clippy::needless_borrow)]
74 let mut cx = task::Context::from_waker(&waker);
75 let mut future = std::pin::pin!(future);
76 let mut polls = 0u32;
77 loop {
78 match future.as_mut().poll(&mut cx) {
79 Poll::Ready(v) => return v,
80 Poll::Pending => {
81 polls += 1;
82 if polls >= MAX_POLLS {
83 panic!(
84 "block_on: future did not complete within \
85 {MAX_POLLS} poll iterations (possible infinite loop)"
86 );
87 }
88 std::hint::spin_loop();
89 }
90 }
91 }
92 }
93
94 #[derive(Debug, thiserror::Error)]
96 #[allow(dead_code, reason = "mock error type verifies trait signature only")]
97 pub(crate) enum MockError {
98 #[error("mock build failed: {0}")]
99 Failed(String),
100 }
101
102 #[cfg(test)]
103 mod block_on_tests {
104 use super::*;
105 use std::sync::atomic::{AtomicU32, Ordering};
106 use std::task::Poll;
107
108 #[test]
109 fn block_on_handles_pending() {
110 static POLL_COUNT: AtomicU32 = AtomicU32::new(0);
111 POLL_COUNT.store(0, Ordering::SeqCst);
112
113 let result = block_on(std::future::poll_fn(|_cx| {
114 let n = POLL_COUNT.fetch_add(1, Ordering::SeqCst);
115 if n < 1 {
116 Poll::Pending
117 } else {
118 Poll::Ready(42)
119 }
120 }));
121 assert_eq!(result, 42);
122 assert!(POLL_COUNT.load(Ordering::SeqCst) >= 2);
123 }
124 }
125}