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}