foundation_utils/lib.rs
1//! # Foundation Utils
2//!
3//! Core foundational utilities for the PromptFleet Agents project.
4//! Provides zero-dependency, WASM-compatible patterns for:
5//!
6//! - **RAII Guards**: Automatic resource cleanup with Drop trait
7//! - **Scoped Operations**: Guaranteed setup/teardown patterns
8//! - **Context Management**: Thread-safe context propagation
9//! - **Resource Management**: Safe resource acquisition/release
10//!
11//! ## Design Principles
12//!
13//! - **Zero Dependencies**: Pure Rust stdlib only
14//! - **WASM Compatible**: Designed for WebAssembly environments
15//! - **Zero Cost**: Compile-time abstractions with no runtime overhead
16//! - **Exception Safe**: Automatic cleanup even during panics
17//! - **Type Safe**: Compiler-enforced correctness
18//!
19//! ## Usage
20//!
21//! ```rust
22//! use foundation_utils::raii::Guard;
23//! use foundation_utils::scoped::with_context;
24//!
25//! // RAII guard for automatic cleanup
26//! let _guard = Guard::new("my_resource", |r| {
27//! println!("Cleaning up: {}", r);
28//! });
29//!
30//! // Scoped access to a value (value drops when scope ends)
31//! let result = with_context(42, |ctx| {
32//! ctx + 1
33//! });
34//! assert_eq!(result, 43);
35//! ```
36
37pub mod context;
38pub mod raii;
39pub mod resource;
40pub mod scoped;
41
42// Re-export commonly used types
43pub use context::{ContextManager, ThreadLocalContext};
44pub use raii::{Guard, ScopedGuard};
45pub use resource::{ResourceGuard, ResourcePool};
46pub use scoped::{ScopedBuilder, ScopedCallback, with_context};
47
48/// Version of the foundation utils
49pub const VERSION: &str = env!("CARGO_PKG_VERSION");
50
51/// Create a simple RAII guard with cleanup function
52///
53/// This is the most basic guard pattern - useful for any resource that needs cleanup
54///
55/// # Example
56/// ```rust
57/// use foundation_utils::guard;
58///
59/// let _guard = guard("my_resource", |r| {
60/// println!("Cleaning up: {}", r);
61/// });
62/// // Cleanup happens automatically when guard drops
63/// ```
64pub fn guard<T, F>(resource: T, cleanup: F) -> Guard<T, F>
65where
66 F: FnOnce(T),
67{
68 Guard::new(resource, cleanup)
69}
70
71/// Execute a function with scoped setup and cleanup
72///
73/// This pattern guarantees that cleanup happens even if the function panics
74///
75/// # Example
76/// ```rust
77/// use foundation_utils::with_scoped;
78///
79/// let result = with_scoped(
80/// || 42,
81/// |resource| *resource + 10,
82/// |resource| println!("cleanup: {}", resource),
83/// );
84/// assert_eq!(result, 52);
85/// ```
86pub fn with_scoped<S, W, C, T, R>(setup: S, work: W, cleanup: C) -> R
87where
88 S: FnOnce() -> T,
89 W: FnOnce(&T) -> R,
90 C: FnOnce(T),
91{
92 let resource = setup();
93 let _guard = guard(resource, cleanup);
94 work(_guard.resource())
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100 use std::sync::{Arc, Mutex};
101
102 #[test]
103 fn test_basic_guard() {
104 let cleanup_called = Arc::new(Mutex::new(false));
105 let cleanup_called_clone = cleanup_called.clone();
106
107 {
108 let _guard = guard("test_resource", move |_| {
109 *cleanup_called_clone.lock().unwrap() = true;
110 });
111
112 // Guard is active
113 assert!(!*cleanup_called.lock().unwrap());
114 } // Guard drops here
115
116 // Cleanup should have been called
117 assert!(*cleanup_called.lock().unwrap());
118 }
119
120 #[test]
121 fn test_with_scoped() {
122 let cleanup_called = Arc::new(Mutex::new(false));
123 let cleanup_called_clone = cleanup_called.clone();
124
125 let result = with_scoped(
126 || "test_resource",
127 |resource| format!("processed: {}", resource),
128 move |_| {
129 *cleanup_called_clone.lock().unwrap() = true;
130 },
131 );
132
133 assert_eq!(result, "processed: test_resource");
134 assert!(*cleanup_called.lock().unwrap());
135 }
136}