Skip to content

Commit 8a04b51

Browse files
authored
Implement Clone for With combinator (#2290)
Consider the following use-case of mpsc channels. There are two categories of producers which produce items of two distinct types, later unified in one using `With` combinator: ``` let (sender, receiver) = mspc::channel(100); let download_status = sender.clone().with(|item| { futures::future::ok(Status::Download(item)) }); let unpack_status = sender.clone().with(|item| { futures::future::ok(Status::Unpack(item)) }); ``` It would be convenient for `With` combinator to implement `Clone`, since the underlying sink, `futures::channel::mpsc::Sender`, implements it.
1 parent da71932 commit 8a04b51

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

futures-util/src/sink/with.rs

+16
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,22 @@ where Si: Sink<Item>,
5353
}
5454
}
5555

56+
impl<Si, Item, U, Fut, F> Clone for With<Si, Item, U, Fut, F>
57+
where
58+
Si: Clone,
59+
F: Clone,
60+
Fut: Clone,
61+
{
62+
fn clone(&self) -> Self {
63+
Self {
64+
state: self.state.clone(),
65+
sink: self.sink.clone(),
66+
f: self.f.clone(),
67+
_phantom: PhantomData,
68+
}
69+
}
70+
}
71+
5672
// Forwarding impl of Stream from the underlying sink
5773
impl<S, Item, U, Fut, F> Stream for With<S, Item, U, Fut, F>
5874
where S: Stream + Sink<Item>,

futures/tests/sink.rs

+35
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,41 @@ fn with_flush_propagate() {
483483
})
484484
}
485485

486+
// test that `Clone` is implemented on `with` sinks
487+
#[test]
488+
fn with_implements_clone() {
489+
use futures::channel::mpsc;
490+
use futures::executor::block_on;
491+
use futures::future;
492+
use futures::{SinkExt, StreamExt};
493+
494+
let (mut tx, rx) = mpsc::channel(5);
495+
496+
{
497+
let mut is_positive = tx
498+
.clone()
499+
.with(|item| future::ok::<bool, mpsc::SendError>(item > 0));
500+
501+
let mut is_long = tx
502+
.clone()
503+
.with(|item: &str| future::ok::<bool, mpsc::SendError>(item.len() > 5));
504+
505+
block_on(is_positive.clone().send(-1)).unwrap();
506+
block_on(is_long.clone().send("123456")).unwrap();
507+
block_on(is_long.send("123")).unwrap();
508+
block_on(is_positive.send(1)).unwrap();
509+
}
510+
511+
block_on(tx.send(false)).unwrap();
512+
513+
block_on(tx.close()).unwrap();
514+
515+
assert_eq!(
516+
block_on(rx.collect::<Vec<_>>()),
517+
vec![false, true, false, true, false]
518+
);
519+
}
520+
486521
// test that a buffer is a no-nop around a sink that always accepts sends
487522
#[test]
488523
fn buffer_noop() {

0 commit comments

Comments
 (0)