diff --git a/futures-sink/Cargo.toml b/futures-sink/Cargo.toml index 56b5cad762..72cfd79e24 100644 --- a/futures-sink/Cargo.toml +++ b/futures-sink/Cargo.toml @@ -11,9 +11,10 @@ The asynchronous `Sink` trait for the futures-rs library. """ [features] -std = ["futures-core/std", "futures-channel/std"] +std = ["either/use_std", "futures-core/std", "futures-channel/std"] default = ["std"] [dependencies] +either = { version = "1.4", default-features = false, optional = true } futures-core = { path = "../futures-core", version = "0.2.0", default-features = false } futures-channel = { path = "../futures-channel", version = "0.2.0", default-features = false } diff --git a/futures-sink/src/lib.rs b/futures-sink/src/lib.rs index 1dc2867023..0da8a92215 100644 --- a/futures-sink/src/lib.rs +++ b/futures-sink/src/lib.rs @@ -23,6 +23,48 @@ macro_rules! if_std { use futures_core::{Poll, task}; +#[cfg(feature = "either")] +extern crate either; +#[cfg(feature = "either")] +use either::Either; +#[cfg(feature = "either")] +impl Sink for Either + where A: Sink, + B: Sink::SinkItem, + SinkError=::SinkError> +{ + type SinkItem = ::SinkItem; + type SinkError = ::SinkError; + + fn poll_ready(&mut self, cx: &mut task::Context) -> Poll<(), Self::SinkError> { + match *self { + Either::Left(ref mut x) => x.poll_ready(cx), + Either::Right(ref mut x) => x.poll_ready(cx), + } + } + + fn start_send(&mut self, item: Self::SinkItem) -> Result<(), Self::SinkError> { + match *self { + Either::Left(ref mut x) => x.start_send(item), + Either::Right(ref mut x) => x.start_send(item), + } + } + + fn poll_flush(&mut self, cx: &mut task::Context) -> Poll<(), Self::SinkError> { + match *self { + Either::Left(ref mut x) => x.poll_flush(cx), + Either::Right(ref mut x) => x.poll_flush(cx), + } + } + + fn poll_close(&mut self, cx: &mut task::Context) -> Poll<(), Self::SinkError> { + match *self { + Either::Left(ref mut x) => x.poll_close(cx), + Either::Right(ref mut x) => x.poll_close(cx), + } + } +} + if_std! { mod channel_impls; diff --git a/futures-util/Cargo.toml b/futures-util/Cargo.toml index 56f4b927ad..31eab056f0 100644 --- a/futures-util/Cargo.toml +++ b/futures-util/Cargo.toml @@ -12,7 +12,7 @@ Common utilities and extension traits for the futures-rs library. [features] std = ["futures-core/std", "futures-io/std", "futures-sink/std", "either/use_std"] -default = ["std", "futures-core/either"] +default = ["std", "futures-core/either", "futures-sink/either"] bench = [] [dependencies] diff --git a/futures-util/src/future/mod.rs b/futures-util/src/future/mod.rs index ccc2775c9d..121bd8ff48 100644 --- a/futures-util/src/future/mod.rs +++ b/futures-util/src/future/mod.rs @@ -509,6 +509,7 @@ pub trait FutureExt: Future { /// assert_eq!(x, block_on(future).unwrap()); /// # } /// ``` + #[deprecated(note = "use `left_future` instead")] fn left(self) -> Either where B: Future, Self: Sized @@ -516,10 +517,41 @@ pub trait FutureExt: Future { Either::Left(self) } + /// Wrap this future in an `Either` future, making it the left-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `right_future` method to write `if` + /// statements that evaluate to different futures in different branches. + /// + /// # Examples + /// + /// ``` + /// # extern crate futures; + /// use futures::executor::block_on; + /// use futures::future::*; + /// + /// # fn main() { + /// let x = 6; + /// let future = if x < 10 { + /// ok::<_, bool>(x).left_future() + /// } else { + /// empty().right_future() + /// }; + /// + /// assert_eq!(x, block_on(future).unwrap()); + /// # } + /// ``` + fn left_future(self) -> Either + where B: Future, + Self: Sized + { + Either::Left(self) + } + /// Wrap this future in an `Either` future, making it the right-hand variant /// of that `Either`. /// - /// This can be used in combination with the `left` method to write `if` + /// This can be used in combination with the `left_future` method to write `if` /// statements that evaluate to different futures in different branches. /// /// # Examples @@ -540,6 +572,7 @@ pub trait FutureExt: Future { /// assert_eq!(x, block_on(future).unwrap()); /// # } /// ``` + #[deprecated(note = "use `right_future` instead")] fn right(self) -> Either where A: Future, Self: Sized, @@ -547,6 +580,37 @@ pub trait FutureExt: Future { Either::Right(self) } + /// Wrap this future in an `Either` future, making it the right-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `left_future` method to write `if` + /// statements that evaluate to different futures in different branches. + /// + /// # Examples + /// + /// ``` + /// # extern crate futures; + /// use futures::executor::block_on; + /// use futures::future::*; + /// + /// # fn main() { + /// let x = 6; + /// let future = if x < 10 { + /// ok::<_, bool>(x).left_future() + /// } else { + /// empty().right_future() + /// }; + /// + /// assert_eq!(x, block_on(future).unwrap()); + /// # } + /// ``` + fn right_future(self) -> Either + where A: Future, + Self: Sized, + { + Either::Right(self) + } + /// Convert this future into a single element stream. /// /// The returned stream contains single success if this future resolves to diff --git a/futures-util/src/sink/mod.rs b/futures-util/src/sink/mod.rs index 275c748531..9f951c6fc7 100644 --- a/futures-util/src/sink/mod.rs +++ b/futures-util/src/sink/mod.rs @@ -5,6 +5,7 @@ use futures_core::{Stream, IntoFuture}; use futures_sink::Sink; +use super::future::Either; mod close; mod fanout; @@ -219,4 +220,28 @@ pub trait SinkExt: Sink { { send_all::new(self, stream) } + + /// Wrap this sink in an `Either` sink, making it the left-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `right_sink` method to write `if` + /// statements that evaluate to different streams in different branches. + fn left_sink(self) -> Either + where B: Sink, + Self: Sized + { + Either::Left(self) + } + + /// Wrap this stream in an `Either` stream, making it the right-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `left_sink` method to write `if` + /// statements that evaluate to different streams in different branches. + fn right_sink(self) -> Either + where B: Sink, + Self: Sized + { + Either::Right(self) + } } diff --git a/futures-util/src/stream/mod.rs b/futures-util/src/stream/mod.rs index e3c9aaa35c..1a6d65ae89 100644 --- a/futures-util/src/stream/mod.rs +++ b/futures-util/src/stream/mod.rs @@ -962,12 +962,12 @@ pub trait StreamExt: Stream { recover::new(self, f) } - /// Wrap this stream in an `Either` stream, making it the left-hand variant /// of that `Either`. /// /// This can be used in combination with the `right` method to write `if` /// statements that evaluate to different streams in different branches. + #[deprecated(note = "use `left_stream` instead")] fn left(self) -> Either where B: Stream, Self: Sized @@ -980,10 +980,35 @@ pub trait StreamExt: Stream { /// /// This can be used in combination with the `left` method to write `if` /// statements that evaluate to different streams in different branches. + #[deprecated(note = "use `right_stream` instead")] fn right(self) -> Either where B: Stream, Self: Sized { Either::Right(self) } + + /// Wrap this stream in an `Either` stream, making it the left-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `right_stream` method to write `if` + /// statements that evaluate to different streams in different branches. + fn left_stream(self) -> Either + where B: Stream, + Self: Sized + { + Either::Left(self) + } + + /// Wrap this stream in an `Either` stream, making it the right-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `left_stream` method to write `if` + /// statements that evaluate to different streams in different branches. + fn right_stream(self) -> Either + where B: Stream, + Self: Sized + { + Either::Right(self) + } } diff --git a/futures/tests/sink.rs b/futures/tests/sink.rs index 603633684d..17ec5277ba 100644 --- a/futures/tests/sink.rs +++ b/futures/tests/sink.rs @@ -18,6 +18,17 @@ use futures::sink::SinkErrInto; mod support; use support::*; +#[test] +fn either_sink() { + let mut s = if true { + Vec::::new().left_sink() + } else { + VecDeque::::new().right_sink() + }; + + s.start_send(0).unwrap(); +} + #[test] fn vec_sink() { let mut v = Vec::new();