rust-chg: reimplement uihandler by using async-trait and tokio-0.2
authorYuya Nishihara <yuya@tcha.org>
Fri, 10 Apr 2020 22:23:10 +0900
changeset 44750 c794d0da5fb2
parent 44749 cb5822e6e545
child 44751 94cace4b80ea
rust-chg: reimplement uihandler by using async-trait and tokio-0.2 We no longer have to consume self and arguments. Differential Revision: https://phab.mercurial-scm.org/D8444
rust/chg/src/lib.rs
rust/chg/src/uihandler.rs
--- a/rust/chg/src/lib.rs	Fri Apr 10 23:08:57 2020 +0900
+++ b/rust/chg/src/lib.rs	Fri Apr 10 22:23:10 2020 +0900
@@ -9,7 +9,7 @@
 pub mod message;
 pub mod procutil;
 //mod runcommand;
-//mod uihandler;
+mod uihandler;
 
 //pub use clientext::ChgClientExt;
-//pub use uihandler::{ChgUiHandler, SystemHandler};
+pub use uihandler::{ChgUiHandler, SystemHandler};
--- a/rust/chg/src/uihandler.rs	Fri Apr 10 23:08:57 2020 +0900
+++ b/rust/chg/src/uihandler.rs	Fri Apr 10 22:23:10 2020 +0900
@@ -3,8 +3,7 @@
 // This software may be used and distributed according to the terms of the
 // GNU General Public License version 2 or any later version.
 
-use futures::future::IntoFuture;
-use futures::Future;
+use async_trait::async_trait;
 use std::io;
 use std::os::unix::io::AsRawFd;
 use std::os::unix::process::ExitStatusExt;
@@ -16,20 +15,19 @@
 use crate::procutil;
 
 /// Callback to process shell command requests received from server.
-pub trait SystemHandler: Sized {
+#[async_trait]
+pub trait SystemHandler {
     type PagerStdin: AsRawFd;
-    type SpawnPagerResult: IntoFuture<Item = (Self, Self::PagerStdin), Error = io::Error>;
-    type RunSystemResult: IntoFuture<Item = (Self, i32), Error = io::Error>;
 
     /// Handles pager command request.
     ///
     /// Returns the pipe to be attached to the server if the pager is spawned.
-    fn spawn_pager(self, spec: CommandSpec) -> Self::SpawnPagerResult;
+    async fn spawn_pager(&mut self, spec: &CommandSpec) -> io::Result<Self::PagerStdin>;
 
     /// Handles system command request.
     ///
     /// Returns command exit code (positive) or signal number (negative).
-    fn run_system(self, spec: CommandSpec) -> Self::RunSystemResult;
+    async fn run_system(&mut self, spec: &CommandSpec) -> io::Result<i32>;
 }
 
 /// Default cHg implementation to process requests received from server.
@@ -41,12 +39,11 @@
     }
 }
 
+#[async_trait]
 impl SystemHandler for ChgUiHandler {
     type PagerStdin = ChildStdin;
-    type SpawnPagerResult = io::Result<(Self, Self::PagerStdin)>;
-    type RunSystemResult = Box<dyn Future<Item = (Self, i32), Error = io::Error> + Send>;
 
-    fn spawn_pager(self, spec: CommandSpec) -> Self::SpawnPagerResult {
+    async fn spawn_pager(&mut self, spec: &CommandSpec) -> io::Result<Self::PagerStdin> {
         let mut pager = new_shell_command(&spec).stdin(Stdio::piped()).spawn()?;
         let pin = pager.stdin.take().unwrap();
         procutil::set_blocking_fd(pin.as_raw_fd())?;
@@ -54,23 +51,22 @@
         // otherwise the server won't get SIGPIPE if it does not write
         // anything. (issue5278)
         // kill(peerpid, SIGPIPE);
-        tokio::spawn(pager.map(|_| ()).map_err(|_| ())); // just ignore errors
-        Ok((self, pin))
+        tokio::spawn(async { pager.await }); // just ignore errors
+        Ok(pin)
     }
 
-    fn run_system(self, spec: CommandSpec) -> Self::RunSystemResult {
-        let fut = new_shell_command(&spec)
-            .spawn()
-            .into_future()
-            .flatten()
-            .map(|status| {
+    async fn run_system(&mut self, spec: &CommandSpec) -> io::Result<i32> {
+        let status = new_shell_command(&spec).spawn()?.await?;
+        // TODO: unindent
+        {
+            {
                 let code = status
                     .code()
                     .or_else(|| status.signal().map(|n| -n))
                     .expect("either exit code or signal should be set");
-                (self, code)
-            });
-        Box::new(fut)
+                Ok(code)
+            }
+        }
     }
 }