-
Notifications
You must be signed in to change notification settings - Fork 12
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
Support converting WritableStream to AsyncWrite #9
Comments
Indeed, the futures crate only supports converting from To convert from
It's possible to write such an adapter, but you'll need to copy the borrowed slice from use std::pin::Pin;
use std::task::{Context, Poll};
use futures::io::AsyncWrite;
use futures::ready;
use futures::sink::Sink;
use pin_project_lite::pin_project;
pin_project! {
#[derive(Debug)]
#[must_use = "writers do nothing unless polled"]
pub struct IntoAsyncWrite<Si>
{
#[pin]
sink: Si
}
}
impl<Si> IntoAsyncWrite<Si> {
#[inline]
pub(super) fn new(sink: Si) -> Self {
Self { sink }
}
}
impl<Si> AsyncWrite for IntoAsyncWrite<Si>
where
Si: Sink<Box<[u8]>, Error = std::io::Error>,
{
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<std::io::Result<usize>> {
let mut this = self.project();
ready!(this.sink.as_mut().poll_ready(cx))?;
this.sink.as_mut().start_send(buf.into())?; // buf.into() copies the slice to a `Box<[u8]>`
Poll::Ready(Ok(buf.len()))
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
let mut this = self.project();
this.sink.as_mut().poll_flush(cx).map_ok(|_| ())
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
let mut this = self.project();
this.sink.as_mut().poll_close(cx).map_ok(|_| ())
}
} This allows you to turn any Of course, to get such a let sink = writable
.into_sink()
.with(|buf: Box<[u8]>| -> futures::future::Ready<Result<JsValue, JsValue>> {
futures::future::ready(Ok(Uint8Array::from(buf.as_ref()).into()))
})
// TODO if _err is a JS `Error` object, use its error message in the std::io::Error
.sink_map_err(|_err| std::io::Error::new(ErrorKind::Other, "foo"));
let async_write = IntoAsyncWrite::new(sink); I don't know if this is something
Not sure yet... 🤔 |
I decided that it is worth adding to |
Well, that was fast! I'll test it and get back to you 😃 |
Turns out that async_io_stream also supports converting a I'm still going to ship my own version though, just to avoid that extra copy when going from |
Hi again. Ha, I missed that crate. That is reassuring indeed. I have tested this in my code and it seems to work fine! :) |
It seems to perform reasonably well too (at least, my bottleneck is Web Crypto not supporting either streaming authenticated encryption or an incremental hash API). |
That's great to hear! I'll get this merged and shipped into a new release then. 😄 |
I'm trying to use this library and wasm-bindgen to connect the Streams API with my rust library (specifically, encryption).
The goal is to use these bindings in web apps/or email clients for example. This way we pass the result of
fetch()
or a mail body straight into decryption.My library offers a simple asynchronous API that looks like this:
Basically the plaintext is read from an
AsyncRead
and the ciphertext is written to anAsyncWrite
.Converting the JS
ReadableStream
to a RustAsyncRead
was easy as this was features in the examples:This readable can then be used in the function our library exposes. Great!
However, converting the
WritableStream
parameter given by the JS side to anAsyncWrite
is not so easy.Converting the JS stream to a
Sink
via theinto_sink()
method seems like a logical first step.If I understand correctly we end up with a
Sink
to which we can sendJsValue
s. Now I see no way to convert this into anAsyncWrite
to use in my library. Rust'sfutures::Sink
and other helpers (e.g., tokio-util) only support converting fromAsyncRead
/AsyncWrite
into eitherStream
orSink
, but I cannot find the inverses of these adapters. Should my library expose an API usingStream
/Sink
instead ofAsyncRead
/AsyncWrite
? Any other ideas?The text was updated successfully, but these errors were encountered: