moonpool_core/lib.rs
1//! # moonpool-core
2//!
3//! Core abstractions for the moonpool simulation framework.
4//!
5//! This crate provides the foundational traits and types that enable
6//! moonpool's simulation capabilities. Application code depends on
7//! these abstractions rather than concrete implementations, allowing
8//! seamless switching between simulation and production environments.
9//!
10//! ## The Provider Pattern
11//!
12//! The key insight is that distributed systems interact with the outside
13//! world through a small set of operations: time, networking, task spawning,
14//! and randomness. By abstracting these behind traits, we can substitute
15//! deterministic simulation implementations during testing.
16//!
17//! ```text
18//! ┌──────────────────────────────────────────────────────┐
19//! │ Application Code │
20//! │ Uses: TimeProvider, NetworkProvider, etc. │
21//! └───────────────────────┬──────────────────────────────┘
22//! │ depends on traits
23//! ┌──────────────┴──────────────┐
24//! ▼ ▼
25//! ┌─────────────────┐ ┌─────────────────┐
26//! │ Simulation │ │ Production │
27//! │ SimTimeProvider │ │ TokioTimeProvider│
28//! │ SimNetworkProv. │ │ TokioNetworkProv.│
29//! │ (deterministic) │ │ (real I/O) │
30//! └─────────────────┘ └─────────────────┘
31//! ```
32//!
33//! ## Provider Traits
34//!
35//! | Trait | Simulation | Production | Purpose |
36//! |-------|------------|------------|---------|
37//! | [`TimeProvider`] | Logical time | Wall clock | Sleep, timeout, `now()` |
38//! | [`TaskProvider`] | Event-driven | Tokio spawn | Task spawning |
39//! | [`RandomProvider`] | Seeded RNG | System RNG | Deterministic randomness |
40//! | [`NetworkProvider`] | Simulated TCP | Real TCP | Connect, listen, accept |
41//! | [`StorageProvider`] | Fault-injected I/O | Real filesystem | File open, read, write, sync |
42//!
43//! **Important**: Never call tokio directly in application code.
44//! - ❌ `tokio::time::sleep()`
45//! - ✅ `time_provider.sleep()`
46//!
47//! ## Core Types
48//!
49//! Types for endpoint addressing:
50//!
51//! - [`UID`]: 128-bit unique identifier (deterministically generated in simulation)
52//! - [`Endpoint`]: Network address + token for direct addressing
53//! - [`NetworkAddress`]: IP address + port
54//! - [`WellKnownToken`]: Reserved tokens for system services
55
56#![deny(missing_docs)]
57#![deny(clippy::unwrap_used)]
58
59mod codec;
60mod error;
61mod network;
62mod providers;
63mod random;
64#[cfg(feature = "deterministic-select")]
65mod select;
66#[cfg(feature = "deterministic-select")]
67pub mod select_support;
68mod storage;
69mod task;
70mod time;
71mod types;
72mod well_known;
73
74/// `select!` as tokio's macro, verbatim (production passthrough).
75///
76/// With the `deterministic-select` feature enabled (moonpool-sim does this),
77/// this re-export is replaced by the seeded-offset macro defined in
78/// [`select`](crate::select!); both are tokio's expansion, so the grammar
79/// and limits are identical either way.
80#[cfg(all(feature = "select", not(feature = "deterministic-select")))]
81pub use tokio::select;
82
83/// tokio re-export used by `select!` expansions so downstream crates never
84/// need a direct tokio dependency for the macro to resolve. Not public API.
85#[cfg(feature = "select")]
86#[doc(hidden)]
87pub use tokio as __tokio;
88
89// Codec exports
90pub use codec::{CodecError, JsonCodec, MessageCodec};
91
92// Error exports
93pub use error::{SimulationError, SimulationResult};
94
95// Provider trait exports
96pub use network::{NetworkProvider, TcpListenerTrait};
97#[cfg(feature = "tokio-net")]
98pub use network::{TokioNetworkProvider, TokioTcpListener};
99pub use providers::Providers;
100#[cfg(feature = "tokio-providers")]
101pub use providers::TokioProviders;
102pub use random::RandomProvider;
103#[cfg(feature = "tokio-random")]
104pub use random::TokioRandomProvider;
105pub use storage::{OpenOptions, StorageFile, StorageProvider};
106#[cfg(feature = "tokio-fs")]
107pub use storage::{TokioStorageFile, TokioStorageProvider};
108pub use task::{JoinError, TaskProvider};
109#[cfg(feature = "tokio-task")]
110pub use task::{TokioJoinHandle, TokioTaskProvider};
111#[cfg(feature = "tokio-time")]
112pub use time::TokioTimeProvider;
113pub use time::{TimeError, TimeProvider};
114
115// Core type exports
116pub use types::{Endpoint, NetworkAddress, NetworkAddressParseError, UID, flags};
117pub use well_known::{WELL_KNOWN_RESERVED_COUNT, WellKnownToken};
118
119/// Common imports for writing code against the provider traits.
120///
121/// Bringing the provider traits into scope is the usual ergonomic need — their
122/// `async fn`s (RPIT) are only callable with the trait in scope. Glob-import this
123/// in production code:
124///
125/// ```
126/// use moonpool_core::prelude::*;
127/// ```
128pub mod prelude {
129 pub use crate::{
130 NetworkProvider, Providers, RandomProvider, StorageProvider, TaskProvider,
131 TcpListenerTrait, TimeProvider,
132 };
133
134 #[cfg(feature = "tokio-providers")]
135 pub use crate::TokioProviders;
136}