use capsec::prelude::*;
#[capsec::context]
struct AppCtx {
fs_read: FsRead,
fs_write: FsWrite,
net: NetConnect,
env: EnvRead,
}
fn run_app(ctx: &AppCtx) {
let config_path = get_config_path(ctx); let config = load_file(&config_path, ctx);
let processed = config.to_uppercase();
save_output("/tmp/capsec-demo-output.txt", &processed, ctx);
println!("Would send {} bytes to metrics server", processed.len());
}
fn get_config_path(cap: &impl CapProvider<EnvRead>) -> String {
capsec::env::var("APP_CONFIG", cap).unwrap_or_else(|_| "/etc/app/config.toml".into())
}
fn load_file(path: &str, cap: &impl CapProvider<FsRead>) -> String {
capsec::fs::read_to_string(path, cap).unwrap_or_else(|_| "# default config".into())
}
fn save_output(path: &str, data: &str, cap: &impl CapProvider<FsWrite>) {
if let Err(e) = capsec::fs::write(path, data.as_bytes(), cap) {
eprintln!("Warning: could not write {path}: {e}");
}
}
#[capsec::main]
fn main(root: CapRoot) {
let ctx = AppCtx::new(&root);
run_app(&ctx);
println!("Done. The #[capsec::context] macro eliminated all boilerplate.");
}