-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Sink for Sender #12
Comments
This could be easily implemented. I think my main hesitation is that the Sink trait is not very popular and my impression is that its future is uncertain. But maybe it doesn’t matter. Adding a Sink impl probably doesn’t hurt - it can only make things better. cc @yoshuawuyts do you perhaps have an opinion on this? |
I don't particularly like the I would like to recommend that if we add edit (2020-08-24): A good post on sinks vs iterators in C++ was posted by a WG21 member; I think the issues raised translate to Future Sinks vs async Iteration in Rust as well (link). |
There is a |
I had a look at the
So I don't really feel confident proposing a PR on code I don't quite understand. Also the |
I would propose to add an adapter to consume a Stream, like: Would that help? |
@stsydow I don't think that helps when you need an interface. That is if you want to pass the channel to something that takes a |
I proposed it as |
I personally don't like how Sink works either, but until we propose something better, it's the interface we have and most async projects will have the futures lib in their deps anyway, so it doesn't add to much strain. Some discussion was started here, but it hasn't seem much action. |
Is there any movement here? I have a project that takes |
Hi from the future. In the future we still have Futures, and Sink is alive and well.
|
I needed this too. The following seems to work - it does not use any internals of async_channel, but needs a one allocation per sink, and one clone of the sender per send operation. use std::{
pin::Pin,
task::{Context, Poll},
};
use async_channel::{SendError, Sender};
use futures_util::Sink;
use tokio_util::sync::ReusableBoxFuture;
/// A wrapper around [`Sender`] that implements [`Sink`].
///
/// Uses a [`ReusableBoxFuture`] under the hood, so this will allocate once.
/// The [`Sender`] is internally cloned for each send operation.
#[derive(Debug)]
pub struct SenderSink<T> {
sender: Sender<T>,
fut: Option<ReusableBoxFuture<'static, Result<(), SendError<T>>>>,
flushed: bool,
}
impl<T> SenderSink<T> {
/// Creates a new [`SenderSink`].
pub fn new(sender: Sender<T>) -> Self {
Self {
sender,
fut: None,
flushed: true,
}
}
}
impl<T: Send + 'static> Sink<T> for SenderSink<T> {
type Error = SendError<T>;
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.poll_flush(cx)
}
fn start_send(mut self: Pin<&mut Self>, item: T) -> Result<(), Self::Error> {
let sender = self.sender.clone();
let fut = async move { sender.send(item).await };
match self.fut.as_mut() {
None => self.fut = Some(ReusableBoxFuture::new(fut)),
Some(f) => f.set(fut),
}
self.flushed = false;
Ok(())
}
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
if self.flushed {
Poll::Ready(Ok(()))
} else {
match self.fut.as_mut() {
None => Poll::Ready(Ok(())),
Some(fut) => match fut.poll(cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(output) => {
self.flushed = true;
Poll::Ready(output)
}
},
}
}
}
fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.sender.close();
Poll::Ready(Ok(()))
}
} |
My understanding is that |
Is there any information on an ongoing or planned rework of |
I understand the histancy, but |
rust-lang/futures-rs#2207 (cc @taiki-e)
Could you clarify what the use case behind this is? Code these days really shouldn't be using the The |
last real activity on that issue seems from 2021, what indication is there this is moving forward? |
the biggest uses case for Sink I have and have seen in other places is using tokio codec, which is really useful, but unfortunately built on the Sink trait |
At the moment it is blocked on stabilization of the
The biggest factor differentiating |
The
futures
crate contains aSink
trait. This trait allows for a convenient interaction between its implementors and streams using theforward
method on theStreamExt
trait.So I think implementing
Sink
forSender
would improve the ergonomics of the library.The text was updated successfully, but these errors were encountered: