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 <tw@dtex.org>
This commit is contained in:
Toralf Wittner 2019-02-22 21:23:36 +01:00 committed by Carl Lerche
parent 02a5091885
commit fd22090df8
2 changed files with 76 additions and 0 deletions

View File

@ -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<Self>, WriteHalf<Self>)
where
Self: AsyncWrite + Sized,

View File

@ -12,12 +12,44 @@ pub struct ReadHalf<T> {
handle: BiLock<T>,
}
impl<T: AsyncRead + AsyncWrite> ReadHalf<T> {
/// 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>) -> 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<T> {
handle: BiLock<T>,
}
impl<T: AsyncRead + AsyncWrite> WriteHalf<T> {
/// 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>) -> T {
if let Ok(x) = self.handle.reunite(r.handle) {
x
} else {
panic!("Unrelated `ReadHalf` passed to `WriteHalf::unsplit`.")
}
}
}
pub fn split<T: AsyncRead + AsyncWrite>(t: T) -> (ReadHalf<T>, WriteHalf<T>) {
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);
}
}