moonpool_core/providers.rs
1//! Provider bundle trait for simplified type parameters.
2//!
3//! This module provides a unified [`Providers`] trait that bundles all four
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 four separate type parameters:
10//!
11//! ```text
12//! struct MyStruct<N, T, TP, R>
13//! where
14//! N: NetworkProvider + Clone + 'static,
15//! T: TimeProvider + Clone + 'static,
16//! TP: TaskProvider + Clone + 'static,
17//! R: RandomProvider + Clone + 'static,
18//! ```
19//!
20//! With bundling, this simplifies to:
21//!
22//! ```text
23//! struct MyStruct<P: Providers>
24//! ```
25//!
26//! ## Usage
27//!
28//! ```rust,ignore
29//! use moonpool_core::{Providers, TokioProviders};
30//!
31//! let providers = TokioProviders::new();
32//! let time_now = providers.time().now();
33//! ```
34
35use crate::{
36 NetworkProvider, RandomProvider, TaskProvider, TimeProvider, TokioNetworkProvider,
37 TokioRandomProvider, TokioTaskProvider, TokioTimeProvider,
38};
39
40/// Bundle of all provider types for a runtime environment.
41///
42/// This trait consolidates the four provider types ([`NetworkProvider`],
43/// [`TimeProvider`], [`TaskProvider`], [`RandomProvider`]) into a single
44/// bundle, reducing type parameter explosion and repetitive where clauses.
45///
46/// ## Implementations
47///
48/// - [`TokioProviders`]: Production providers using real Tokio runtime
49/// - `SimProviders` (in moonpool-sim): Simulation providers for deterministic testing
50///
51/// ## Design
52///
53/// The trait uses associated types to preserve type information at compile time
54/// without runtime dispatch. Accessor methods provide convenient access to
55/// individual providers while maintaining the bundle.
56pub trait Providers: Clone + 'static {
57 /// Network provider type for TCP connections and listeners.
58 type Network: NetworkProvider + Clone + 'static;
59
60 /// Time provider type for sleep, timeout, and time queries.
61 type Time: TimeProvider + Clone + 'static;
62
63 /// Task provider type for spawning local tasks.
64 type Task: TaskProvider + Clone + 'static;
65
66 /// Random provider type for deterministic or real randomness.
67 type Random: RandomProvider + Clone + 'static;
68
69 /// Get the network provider instance.
70 fn network(&self) -> &Self::Network;
71
72 /// Get the time provider instance.
73 fn time(&self) -> &Self::Time;
74
75 /// Get the task provider instance.
76 fn task(&self) -> &Self::Task;
77
78 /// Get the random provider instance.
79 fn random(&self) -> &Self::Random;
80}
81
82/// Production providers using Tokio runtime.
83///
84/// This struct bundles all four Tokio-based providers into a single
85/// instance that implements [`Providers`].
86///
87/// ## Example
88///
89/// ```rust,ignore
90/// use moonpool_core::{Providers, TokioProviders};
91///
92/// let providers = TokioProviders::new();
93///
94/// // Access individual providers
95/// let network = providers.network();
96/// let time = providers.time();
97/// let task = providers.task();
98/// let random = providers.random();
99/// ```
100#[derive(Clone)]
101pub struct TokioProviders {
102 network: TokioNetworkProvider,
103 time: TokioTimeProvider,
104 task: TokioTaskProvider,
105 random: TokioRandomProvider,
106}
107
108impl TokioProviders {
109 /// Create a new production providers bundle.
110 ///
111 /// Initializes all four Tokio-based providers with their default
112 /// configurations.
113 pub fn new() -> Self {
114 Self {
115 network: TokioNetworkProvider::new(),
116 time: TokioTimeProvider::new(),
117 task: TokioTaskProvider,
118 random: TokioRandomProvider::new(),
119 }
120 }
121}
122
123impl Default for TokioProviders {
124 fn default() -> Self {
125 Self::new()
126 }
127}
128
129impl Providers for TokioProviders {
130 type Network = TokioNetworkProvider;
131 type Time = TokioTimeProvider;
132 type Task = TokioTaskProvider;
133 type Random = TokioRandomProvider;
134
135 fn network(&self) -> &Self::Network {
136 &self.network
137 }
138
139 fn time(&self) -> &Self::Time {
140 &self.time
141 }
142
143 fn task(&self) -> &Self::Task {
144 &self.task
145 }
146
147 fn random(&self) -> &Self::Random {
148 &self.random
149 }
150}