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