use stillwater::effect::resource::{
assert_resource_neutral, bracket, resource_bracket, Bracket, DbRes, Empty, FileRes, Has,
ResourceEffect, ResourceEffectExt, ResourceKind, TrackedExt, TxRes,
};
use stillwater::{pure, Effect};
fn open_file(
path: &str,
) -> impl ResourceEffect<
Output = String,
Error = String,
Env = (),
Acquires = Has<FileRes>,
Releases = Empty,
> {
println!(" Opening file: {}", path);
pure::<_, String, ()>(format!("FileHandle({})", path)).acquires::<FileRes>()
}
fn close_file(
handle: String,
) -> impl ResourceEffect<Output = (), Error = String, Env = (), Acquires = Empty, Releases = Has<FileRes>>
{
println!(" Closing file: {}", handle);
pure::<_, String, ()>(()).releases::<FileRes>()
}
fn read_contents(
handle: &str,
) -> impl ResourceEffect<Output = String, Error = String, Env = (), Acquires = Empty, Releases = Empty>
{
println!(" Reading contents from: {}", handle);
pure::<_, String, ()>(format!("Contents of {}", handle)).neutral()
}
async fn example_basic_annotation() {
println!("\n=== Example 1: Basic Resource Annotation ===");
let acquire = open_file("data.txt");
let handle = acquire.run(&()).await.unwrap();
println!(" Got handle: {}", handle);
let contents = read_contents(&handle).run(&()).await.unwrap();
println!(" Contents: {}", contents);
close_file(handle).run(&()).await.unwrap();
println!(" File closed successfully");
}
async fn example_resource_bracket() {
println!("\n=== Example 2: Resource Bracket Pattern ===");
println!("\n Using turbofish syntax:");
let result = resource_bracket::<FileRes, _, _, _, _, _, _, _, _, _>(
pure::<_, String, ()>("file_handle".to_string()),
|handle: String| {
println!(" Releasing: {}", handle);
async { Ok(()) }
},
|handle: &String| {
println!(" Using handle: {}", handle);
pure::<_, String, ()>(format!("Processed: {}", handle))
},
)
.run(&())
.await;
println!(" Result: {:?}", result);
println!("\n Using builder pattern:");
let result = Bracket::<FileRes>::new()
.acquire(pure::<_, String, ()>("file_handle".to_string()))
.release(|handle: String| {
println!(" Releasing: {}", handle);
async { Ok(()) }
})
.use_fn(|handle: &String| {
println!(" Using handle: {}", handle);
pure::<_, String, ()>(format!("Processed: {}", handle))
})
.run(&())
.await;
println!(" Result: {:?}", result);
println!("\n Using bracket() function:");
let result = bracket::<FileRes>()
.acquire(pure::<_, String, ()>("file_handle".to_string()))
.release(|handle: String| {
println!(" Releasing: {}", handle);
async { Ok(()) }
})
.use_fn(|handle: &String| {
println!(" Using handle: {}", handle);
pure::<_, String, ()>(format!("Processed: {}", handle))
})
.run(&())
.await;
println!(" Result: {:?}", result);
}
fn begin_transaction() -> impl ResourceEffect<
Output = String,
Error = String,
Env = (),
Acquires = Has<TxRes>,
Releases = Empty,
> {
println!(" BEGIN TRANSACTION");
pure::<_, String, ()>("tx_12345".to_string()).acquires::<TxRes>()
}
fn commit_transaction(
_tx: String,
) -> impl ResourceEffect<Output = (), Error = String, Env = (), Acquires = Empty, Releases = Has<TxRes>>
{
println!(" COMMIT");
pure::<_, String, ()>(()).releases::<TxRes>()
}
#[allow(dead_code)]
fn rollback_transaction(
_tx: String,
) -> impl ResourceEffect<Output = (), Error = String, Env = (), Acquires = Empty, Releases = Has<TxRes>>
{
println!(" ROLLBACK");
pure::<_, String, ()>(()).releases::<TxRes>()
}
fn execute_query(
tx: &str,
query: &str,
) -> impl ResourceEffect<
Output = Vec<String>,
Error = String,
Env = (),
Acquires = Empty,
Releases = Empty,
> {
println!(" QUERY [{}]: {}", tx, query);
pure::<_, String, ()>(vec!["row1".to_string(), "row2".to_string()]).neutral()
}
async fn example_transaction_protocol() {
println!("\n=== Example 3: Transaction Protocol ===");
let result = resource_bracket::<TxRes, _, _, _, _, _, _, _, _, _>(
begin_transaction(),
|tx: String| async move {
commit_transaction(tx).run(&()).await
},
|tx: &String| {
println!(" Executing queries...");
let _rows1 = execute_query(tx, "SELECT * FROM users");
let _rows2 = execute_query(tx, "UPDATE users SET active = true");
pure::<_, String, ()>("Transaction completed".to_string())
},
)
.run(&())
.await;
println!(" Result: {:?}", result);
}
async fn example_multiple_resources() {
println!("\n=== Example 4: Multiple Resource Types ===");
let effect = pure::<_, String, ()>(42)
.acquires::<FileRes>()
.also_acquires::<DbRes>();
let result = effect.run(&()).await;
println!(" Result: {:?}", result);
let release_both = pure::<_, String, ()>(())
.releases::<FileRes>()
.also_releases::<DbRes>();
release_both.run(&()).await.unwrap();
println!(" Released both resources");
}
fn safe_file_operation(
path: &str,
) -> impl ResourceEffect<Output = String, Error = String, Env = (), Acquires = Empty, Releases = Empty>
{
let path = path.to_string();
let effect = resource_bracket::<FileRes, _, _, _, _, _, _, _, _, _>(
pure::<_, String, ()>(format!("handle_{}", path)),
|_handle: String| async { Ok(()) },
|handle: &String| pure::<_, String, ()>(format!("Read from {}", handle)),
);
assert_resource_neutral(effect)
}
async fn example_neutrality_assertion() {
println!("\n=== Example 5: Compile-Time Neutrality Assertion ===");
let result = safe_file_operation("config.json").run(&()).await;
println!(" Result: {:?}", result);
println!(" The type system guarantees no resource leaks!");
}
struct PoolRes;
impl ResourceKind for PoolRes {
const NAME: &'static str = "ConnectionPool";
}
fn acquire_pool_connection() -> impl ResourceEffect<
Output = String,
Error = String,
Env = (),
Acquires = Has<PoolRes>,
Releases = Empty,
> {
println!(" Acquiring connection from pool...");
pure::<_, String, ()>("conn_42".to_string()).acquires::<PoolRes>()
}
fn release_pool_connection(
_conn: String,
) -> impl ResourceEffect<Output = (), Error = String, Env = (), Acquires = Empty, Releases = Has<PoolRes>>
{
println!(" Returning connection to pool");
pure::<_, String, ()>(()).releases::<PoolRes>()
}
async fn example_custom_resource() {
println!("\n=== Example 6: Custom Resource Kinds ===");
let result = resource_bracket::<PoolRes, _, _, _, _, _, _, _, _, _>(
acquire_pool_connection(),
|conn: String| async move { release_pool_connection(conn).run(&()).await },
|conn: &String| {
println!(" Using connection: {}", conn);
pure::<_, String, ()>(format!("Query result from {}", conn))
},
)
.run(&())
.await;
println!(" Result: {:?}", result);
}
#[tokio::main]
async fn main() {
println!("Compile-Time Resource Tracking Examples");
println!("========================================");
println!();
println!("This demonstrates type-level resource tracking with ZERO runtime overhead.");
println!("All resource safety is verified at compile time.");
example_basic_annotation().await;
example_resource_bracket().await;
example_transaction_protocol().await;
example_multiple_resources().await;
example_neutrality_assertion().await;
example_custom_resource().await;
println!("\n=== All examples completed! ===");
println!();
println!("Key takeaways:");
println!(" - Use .acquires::<R>() to mark resource acquisition");
println!(" - Use .releases::<R>() to mark resource release");
println!(" - Use resource_bracket for guaranteed cleanup");
println!(" - Use assert_resource_neutral for compile-time safety checks");
println!(" - Define custom ResourceKind types for domain-specific resources");
println!(" - ALL tracking is compile-time only - zero runtime overhead!");
}