1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
use std::marker::PhantomData; use wasm_bindgen::JsValue; use super::{sys, IntoSink, WritableStream}; use crate::util::promise_to_void_future; /// A [`WritableStreamDefaultWriter`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultWriter) /// that can be used to write chunks to a [`WritableStream`](WritableStream). /// /// This is returned by the [`get_writer`](WritableStream::get_writer) method. /// /// When the writer is dropped, it automatically [releases its lock](https://streams.spec.whatwg.org/#release-a-lock). #[derive(Debug)] pub struct WritableStreamDefaultWriter<'stream> { raw: sys::WritableStreamDefaultWriter, _stream: PhantomData<&'stream mut WritableStream>, } impl<'stream> WritableStreamDefaultWriter<'stream> { pub(crate) fn new(stream: &mut WritableStream) -> Result<Self, js_sys::Error> { Ok(Self { raw: stream.as_raw().get_writer()?, _stream: PhantomData, }) } /// Acquires a reference to the underlying [JavaScript writer](sys::WritableStreamDefaultWriter). #[inline] pub fn as_raw(&self) -> &sys::WritableStreamDefaultWriter { &self.raw } /// Waits for the stream to become closed. /// /// This returns an error if the stream ever errors, or if the writer's lock is /// [released](https://streams.spec.whatwg.org/#release-a-lock) before the stream finishes /// closing. pub async fn closed(&self) -> Result<(), JsValue> { promise_to_void_future(self.as_raw().closed()).await } /// Returns the desired size to fill the stream's internal queue. /// /// * It can be negative, if the queue is over-full. /// A producer can use this information to determine the right amount of data to write. /// * It will be `None` if the stream cannot be successfully written to /// (due to either being errored, or having an abort queued up). /// * It will return zero if the stream is closed. #[inline] pub fn desired_size(&self) -> Option<f64> { self.as_raw().desired_size() } /// Waits until the desired size to fill the stream's internal queue transitions /// from non-positive to positive, signaling that it is no longer applying backpressure. /// /// Once the desired size to fill the stream's internal queue dips back to zero or below, /// this will return a new future that stays pending until the next transition. /// /// This returns an error if the stream ever errors, or if the writer's lock is /// [released](https://streams.spec.whatwg.org/#release-a-lock) before the stream finishes /// closing. pub async fn ready(&self) -> Result<(), JsValue> { promise_to_void_future(self.as_raw().ready()).await } /// [Aborts](https://streams.spec.whatwg.org/#abort-a-writable-stream) the stream, /// signaling that the producer can no longer successfully write to the stream. /// /// Equivalent to [`WritableStream.abort`](WritableStream::abort). pub async fn abort(&mut self) -> Result<(), JsValue> { promise_to_void_future(self.as_raw().abort()).await } /// [Aborts](https://streams.spec.whatwg.org/#abort-a-writable-stream) the stream with the /// given `reason`, signaling that the producer can no longer successfully write to the stream. /// /// Equivalent to [`WritableStream.abort_with_reason`](WritableStream::abort_with_reason). pub async fn abort_with_reason(&mut self, reason: &JsValue) -> Result<(), JsValue> { promise_to_void_future(self.as_raw().abort_with_reason(reason)).await } /// Writes the given `chunk` to the writable stream, by waiting until any previous writes /// have finished successfully, and then sending the chunk to the underlying sink's `write()` /// method. /// /// This returns `Ok(())` upon a successful write, or `Err(error)` if the write fails or stream /// becomes errored before the writing process is initiated. /// /// Note that what "success" means is up to the underlying sink; it might indicate simply /// that the chunk has been accepted, and not necessarily that it is safely saved to /// its ultimate destination. pub async fn write(&mut self, chunk: JsValue) -> Result<(), JsValue> { promise_to_void_future(self.as_raw().write(chunk)).await } /// Closes the stream. /// /// The underlying sink will finish processing any previously-written chunks, before invoking /// its close behavior. During this time any further attempts to write will fail /// (without erroring the stream). /// /// This returns `Ok(())` if all remaining chunks are successfully written and the stream /// successfully closes, or `Err(error)` if an error is encountered during this process. pub async fn close(&mut self) -> Result<(), JsValue> { promise_to_void_future(self.as_raw().close()).await } /// Converts this `WritableStreamDefaultWriter` into a [`Sink`](Sink). /// /// This is similar to [`WritableStream.into_sink`](WritableStream::into_sink), /// except that after the returned `Sink` is dropped, the original `WritableStream` is still /// usable. This allows writing only a few chunks through the `Sink`, while still allowing /// another writer to write more chunks later on. #[inline] pub fn into_sink(self) -> IntoSink<'stream> { IntoSink::new(self) } } impl Drop for WritableStreamDefaultWriter<'_> { fn drop(&mut self) { self.as_raw().release_lock() } }