From 03c64a1a21571961e66828e19f214329dc7d70e5 Mon Sep 17 00:00:00 2001
From: Georgy Moshkin <gmoshkin@picodata.io>
Date: Wed, 28 Feb 2024 19:55:05 +0300
Subject: [PATCH] chore: ScopeGuard

---
 src/util.rs | 48 ++++++++++++++++++++++++++++++++++++------------
 1 file changed, 36 insertions(+), 12 deletions(-)

diff --git a/src/util.rs b/src/util.rs
index 5ed1afd60a..2b69578896 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -471,18 +471,8 @@ pub fn prompt_password(prompt: &str) -> Result<String, std::io::Error> {
     let tty_fd = tty.as_raw_fd();
     let tcattr_old = tcgetattr(tty_fd)?;
 
-    // Restore old terminal settings when `_d` is dropped
-    let _d = Defer(Some(|| {
-        tcsetattr(tty_fd, TCSADRAIN, &tcattr_old).unwrap_or(())
-    }));
-    struct Defer<F: FnOnce()>(Option<F>);
-    impl<F: FnOnce()> Drop for Defer<F> {
-        fn drop(&mut self) {
-            if let Some(f) = self.0.take() {
-                f()
-            }
-        }
-    }
+    // Restore old terminal settings when `_guard` is dropped
+    let _guard = on_scope_exit(|| tcsetattr(tty_fd, TCSADRAIN, &tcattr_old).unwrap_or(()));
 
     // Disable echo while prompting a password
     let mut tcattr_new = tcattr_old.clone();
@@ -718,6 +708,40 @@ impl<T> std::ops::DerefMut for NoYieldsRefMut<'_, T> {
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// ScopeGuard
+////////////////////////////////////////////////////////////////////////////////
+// TODO: this one is copied from tarantool-module, it should instead be export from there
+
+#[derive(Debug)]
+#[must_use = "The callback is invoked when the `ScopeGuard` is dropped"]
+pub struct ScopeGuard<F>
+where
+    F: FnOnce(),
+{
+    cb: Option<F>,
+}
+
+impl<F> Drop for ScopeGuard<F>
+where
+    F: FnOnce(),
+{
+    #[inline(always)]
+    fn drop(&mut self) {
+        if let Some(cb) = self.cb.take() {
+            cb()
+        }
+    }
+}
+
+#[inline(always)]
+pub fn on_scope_exit<F>(cb: F) -> ScopeGuard<F>
+where
+    F: FnOnce(),
+{
+    ScopeGuard { cb: Some(cb) }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // ...
 ////////////////////////////////////////////////////////////////////////////////
-- 
GitLab