defer_lite/lib.rs
1//! A Rust implementation of
2//! [Go's `defer` statement](https://tour.golang.org/flowcontrol/12) as the
3//! `defer!` macro, which executes a block of code when the surrounding scope
4//! ends.
5//!
6//! This crate focuses on providing a lightweight, high-performance, `no_std`
7//! implementation of the `defer!` macro.
8//!
9//! # Usage
10//!
11//! Add the dependency in your `Cargo.toml`:
12//!
13//! ```toml
14//! [dependencies]
15//! defer-lite = "1.0.0"
16//! ```
17
18#![no_std]
19
20#[doc(hidden)]
21pub struct Defer<F: FnOnce()> { // internal struct used by defer! macro
22 func: Option<F>,
23}
24
25impl<F: FnOnce()> Defer<F> {
26 pub fn new(func: F) -> Self {
27 Self { func: Some(func) }
28 }
29}
30
31impl<F: FnOnce()> Drop for Defer<F> {
32 fn drop(&mut self) {
33 self.func.take().map(|f| f());
34 }
35}
36
37/// Executes a block of code when the surrounding scope ends.
38///
39/// # Examples
40///
41/// Simplest example:
42///
43/// ```rust
44/// use defer_lite::defer; // import the defer! macro
45///
46/// fn main() {
47/// defer! { println!("Second"); }
48/// println!("First");
49/// }
50/// ```
51///
52/// Multiple statements:
53///
54/// ```rust
55/// use defer_lite::defer;
56///
57/// fn main() {
58/// defer! {
59/// println!("Second");
60/// println!("Third");
61/// }
62/// println!("First");
63/// }
64/// ```
65///
66/// In Go, the `defer` code runs when the function exits. In this Rust
67/// implementation, however, the code runs when the surrounding scope ends –
68/// this makes it possible to use `defer` inside loops:
69///
70/// ```rust
71/// use defer_lite::defer;
72///
73/// fn main() {
74/// defer! { println!("End"); }
75/// println!("Before");
76///
77/// for i in 0..2 {
78/// defer! { println!("Defer {}", i); }
79/// println!("Loop {}", i);
80/// }
81///
82/// println!("After");
83/// }
84/// ```
85#[macro_export]
86macro_rules! defer {
87 ( $($tt:tt)* ) => {
88 let _deferred = $crate::Defer::new(|| { $($tt)* });
89 };
90}