From fd22090df88a2e4420250d865101ea5464133ff3 Mon Sep 17 00:00:00 2001 From: Toralf Wittner Date: Fri, 22 Feb 2019 21:23:36 +0100 Subject: [PATCH] tokio-io: Add `unsplit`. (#807) Provide a way to restore an I/O object from its `ReadHalf` and `WriteHalf`. Closes #803 Co-Authored-By: twittner --- tokio-io/src/async_read.rs | 3 ++ tokio-io/src/split.rs | 73 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/tokio-io/src/async_read.rs b/tokio-io/src/async_read.rs index f136ccea8..d82aa7116 100644 --- a/tokio-io/src/async_read.rs +++ b/tokio-io/src/async_read.rs @@ -143,6 +143,9 @@ pub trait AsyncRead: std_io::Read { /// /// The two halves returned implement the `Read` and `Write` traits, /// respectively. + /// + /// To restore this read/write object from its `ReadHalf` and `WriteHalf` + /// use `unsplit`. fn split(self) -> (ReadHalf, WriteHalf) where Self: AsyncWrite + Sized, diff --git a/tokio-io/src/split.rs b/tokio-io/src/split.rs index 7f743e8f7..ef8f990c8 100644 --- a/tokio-io/src/split.rs +++ b/tokio-io/src/split.rs @@ -12,12 +12,44 @@ pub struct ReadHalf { handle: BiLock, } +impl ReadHalf { + /// Reunite with a previously split `WriteHalf`. + /// + /// # Panics + /// + /// If this `ReadHalf` and the given `WriteHalf` do not originate from + /// the same `AsyncRead::split` operation this method will panic. + pub fn unsplit(self, w: WriteHalf) -> T { + if let Ok(x) = self.handle.reunite(w.handle) { + x + } else { + panic!("Unrelated `WriteHalf` passed to `ReadHalf::unsplit`.") + } + } +} + /// The writable half of an object returned from `AsyncRead::split`. #[derive(Debug)] pub struct WriteHalf { handle: BiLock, } +impl WriteHalf { + /// Reunite with a previously split `ReadHalf`. + /// + /// # panics + /// + /// If this `WriteHalf` and the given `ReadHalf` do not originate from + /// the same `AsyncRead::split` operation this method will panic. + pub fn unsplit(self, r: ReadHalf) -> T { + if let Ok(x) = self.handle.reunite(r.handle) { + x + } else { + panic!("Unrelated `ReadHalf` passed to `WriteHalf::unsplit`.") + } + } +} + pub fn split(t: T) -> (ReadHalf, WriteHalf) { let (a, b) = BiLock::new(t); (ReadHalf { handle: a }, WriteHalf { handle: b }) @@ -171,4 +203,45 @@ mod tests { })) .unwrap(); } + + #[test] + fn unsplit_ok() { + let (r, w) = RW.split(); + r.unsplit(w); + + let (r, w) = RW.split(); + w.unsplit(r); + } + + #[test] + #[should_panic] + fn unsplit_err1() { + let (r, _) = RW.split(); + let (_, w) = RW.split(); + r.unsplit(w); + } + + #[test] + #[should_panic] + fn unsplit_err2() { + let (_, w) = RW.split(); + let (r, _) = RW.split(); + r.unsplit(w); + } + + #[test] + #[should_panic] + fn unsplit_err3() { + let (_, w) = RW.split(); + let (r, _) = RW.split(); + w.unsplit(r); + } + + #[test] + #[should_panic] + fn unsplit_err4() { + let (r, _) = RW.split(); + let (_, w) = RW.split(); + w.unsplit(r); + } }