moonpool_core/providers.rs
1//! Provider bundle trait for simplified type parameters.
2//!
3//! This module provides a unified [`Providers`] trait that bundles all five
4//! provider types into a single type parameter, eliminating type parameter
5//! explosion in downstream code.
6//!
7//! ## Motivation
8//!
9//! Without bundling, code must carry five separate type parameters:
10//!
11//! ```text
12//! struct MyStruct<N, T, TP, R, S>
13//! where
14//! N: NetworkProvider,
15//! T: TimeProvider,
16//! TP: TaskProvider,
17//! R: RandomProvider,
18//! S: StorageProvider,
19//! ```
20//!
21//! With bundling, this simplifies to:
22//!
23//! ```text
24//! struct MyStruct<P: Providers>
25//! ```
26//!
27//! ## Usage
28//!
29//! ```rust,ignore
30//! use moonpool_core::{Providers, TokioProviders};
31//!
32//! let providers = TokioProviders::new();
33//! let time_now = providers.time().now();
34//! ```
35
36use crate::{NetworkProvider, RandomProvider, StorageProvider, TaskProvider, TimeProvider};
37#[cfg(feature = "tokio-providers")]
38use crate::{
39 TokioNetworkProvider, TokioRandomProvider, TokioStorageProvider, TokioTaskProvider,
40 TokioTimeProvider,
41};
42
43/// Implement [`Providers`] for a struct whose fields are named
44/// `network`, `time`, `task`, `random`, `storage` — the five canonical
45/// provider slots.
46///
47/// Expands to the trait impl plus the five trivial getter forwards. The
48/// type of each slot is specified once in the macro invocation, so the
49/// implementing struct does not have to repeat the field-to-type mapping
50/// in the trait body.
51#[doc(hidden)]
52#[macro_export]
53macro_rules! impl_providers_bundle {
54 (
55 $struct:ty {
56 network: $network_ty:ty,
57 time: $time_ty:ty,
58 task: $task_ty:ty,
59 random: $random_ty:ty,
60 storage: $storage_ty:ty $(,)?
61 }
62 ) => {
63 impl $crate::Providers for $struct {
64 type Network = $network_ty;
65 type Time = $time_ty;
66 type Task = $task_ty;
67 type Random = $random_ty;
68 type Storage = $storage_ty;
69
70 fn network(&self) -> &Self::Network {
71 &self.network
72 }
73
74 fn time(&self) -> &Self::Time {
75 &self.time
76 }
77
78 fn task(&self) -> &Self::Task {
79 &self.task
80 }
81
82 fn random(&self) -> &Self::Random {
83 &self.random
84 }
85
86 fn storage(&self) -> &Self::Storage {
87 &self.storage
88 }
89 }
90 };
91}
92
93/// Bundle of all provider types for a runtime environment.
94///
95/// This trait consolidates the five provider types ([`NetworkProvider`],
96/// [`TimeProvider`], [`TaskProvider`], [`RandomProvider`], [`StorageProvider`])
97/// into a single bundle, reducing type parameter explosion and repetitive
98/// where clauses.
99///
100/// ## Implementations
101///
102/// - [`TokioProviders`]: Production providers using real Tokio runtime
103/// - `SimProviders` (in moonpool-sim): Simulation providers for deterministic testing
104///
105/// ## Design
106///
107/// The trait uses associated types to preserve type information at compile time
108/// without runtime dispatch. Accessor methods provide convenient access to
109/// individual providers while maintaining the bundle.
110pub trait Providers: Clone + Send + Sync + 'static {
111 /// Network provider type for TCP connections and listeners.
112 type Network: NetworkProvider;
113
114 /// Time provider type for sleep, timeout, and time queries.
115 type Time: TimeProvider;
116
117 /// Task provider type for spawning local tasks.
118 type Task: TaskProvider;
119
120 /// Random provider type for deterministic or real randomness.
121 type Random: RandomProvider;
122
123 /// Storage provider type for file I/O operations.
124 type Storage: StorageProvider;
125
126 /// Get the network provider instance.
127 fn network(&self) -> &Self::Network;
128
129 /// Get the time provider instance.
130 fn time(&self) -> &Self::Time;
131
132 /// Get the task provider instance.
133 fn task(&self) -> &Self::Task;
134
135 /// Get the random provider instance.
136 fn random(&self) -> &Self::Random;
137
138 /// Get the storage provider instance.
139 fn storage(&self) -> &Self::Storage;
140}
141
142/// Production providers using Tokio runtime.
143///
144/// This struct bundles all five Tokio-based providers into a single
145/// instance that implements [`Providers`].
146///
147/// ## Example
148///
149/// ```rust,ignore
150/// use moonpool_core::{Providers, TokioProviders};
151///
152/// let providers = TokioProviders::new();
153///
154/// // Access individual providers
155/// let network = providers.network();
156/// let time = providers.time();
157/// let task = providers.task();
158/// let random = providers.random();
159/// ```
160#[cfg(feature = "tokio-providers")]
161#[derive(Clone)]
162pub struct TokioProviders {
163 network: TokioNetworkProvider,
164 time: TokioTimeProvider,
165 task: TokioTaskProvider,
166 random: TokioRandomProvider,
167 storage: TokioStorageProvider,
168}
169
170#[cfg(feature = "tokio-providers")]
171impl TokioProviders {
172 /// Create a new production providers bundle.
173 ///
174 /// Initializes all five Tokio-based providers with their default
175 /// configurations.
176 #[must_use]
177 pub fn new() -> Self {
178 Self {
179 network: TokioNetworkProvider::new(),
180 time: TokioTimeProvider::new(),
181 task: TokioTaskProvider,
182 random: TokioRandomProvider::new(),
183 storage: TokioStorageProvider::new(),
184 }
185 }
186}
187
188#[cfg(feature = "tokio-providers")]
189impl Default for TokioProviders {
190 fn default() -> Self {
191 Self::new()
192 }
193}
194
195#[cfg(feature = "tokio-providers")]
196impl_providers_bundle!(TokioProviders {
197 network: TokioNetworkProvider,
198 time: TokioTimeProvider,
199 task: TokioTaskProvider,
200 random: TokioRandomProvider,
201 storage: TokioStorageProvider,
202});