ferrijs_std/stream_web/readable/
controller.rs1use rquickjs::{
2 class::{OwnedBorrowMut, Trace},
3 Ctx, IntoJs, JsLifetime, Promise, Result, Value,
4};
5
6use crate::stream_web::readable::{
7 byte_controller::{ReadableByteStreamControllerClass, ReadableByteStreamControllerOwned},
8 default_controller::{
9 ReadableStreamDefaultControllerClass, ReadableStreamDefaultControllerOwned,
10 },
11 default_reader::ReadableStreamReadRequest,
12 objects::{ReadableStreamDefaultReaderObjects, ReadableStreamObjects},
13 reader::ReadableStreamReader,
14};
15
16pub(crate) trait ReadableStreamController<'js>: Sized {
17 type Class: Clone + Trace<'js>;
18
19 fn with_controller<C, O>(
20 self,
21 ctx: C,
22 default: impl FnOnce(
23 C,
24 ReadableStreamDefaultControllerOwned<'js>,
25 ) -> Result<(O, ReadableStreamDefaultControllerOwned<'js>)>,
26 byte: impl FnOnce(
27 C,
28 ReadableByteStreamControllerOwned<'js>,
29 ) -> Result<(O, ReadableByteStreamControllerOwned<'js>)>,
30 ) -> Result<(O, Self)>;
31
32 fn into_inner(self) -> Self::Class;
33 fn from_class(class: Self::Class) -> Self;
34
35 fn into_erased(self) -> ReadableStreamControllerOwned<'js>;
36 fn try_from_erased(erased: ReadableStreamControllerOwned<'js>) -> Option<Self>;
37
38 fn pull_steps(
39 ctx: &Ctx<'js>,
40 objects: ReadableStreamDefaultReaderObjects<'js, Self>,
41 read_request: impl ReadableStreamReadRequest<'js> + 'js,
42 ) -> Result<ReadableStreamDefaultReaderObjects<'js, Self>>;
43
44 fn cancel_steps<R: ReadableStreamReader<'js>>(
45 ctx: &Ctx<'js>,
46 objects: ReadableStreamObjects<'js, Self, R>,
47 reason: Value<'js>,
48 ) -> Result<(Promise<'js>, ReadableStreamObjects<'js, Self, R>)>;
49
50 fn release_steps(&mut self);
51}
52
53#[derive(JsLifetime, Trace, Clone)]
54pub enum ReadableStreamControllerClass<'js> {
55 ReadableStreamDefaultController(ReadableStreamDefaultControllerClass<'js>),
56 ReadableStreamByteController(ReadableByteStreamControllerClass<'js>),
57 Uninitialised, }
59
60impl<'js> IntoJs<'js> for ReadableStreamControllerClass<'js> {
61 fn into_js(self, ctx: &Ctx<'js>) -> Result<Value<'js>> {
62 match self {
63 Self::ReadableStreamDefaultController(c) => c.into_js(ctx),
64 Self::ReadableStreamByteController(c) => c.into_js(ctx),
65 Self::Uninitialised => {
66 panic!("Tried to convert an uninitialised controller class to JS")
67 },
68 }
69 }
70}
71
72pub(crate) enum ReadableStreamControllerOwned<'js> {
73 ReadableStreamDefaultController(ReadableStreamDefaultControllerOwned<'js>),
74 ReadableStreamByteController(ReadableByteStreamControllerOwned<'js>),
75}
76
77impl<'js> ReadableStreamController<'js> for ReadableStreamControllerOwned<'js> {
78 type Class = ReadableStreamControllerClass<'js>;
79
80 fn with_controller<C, O>(
81 self,
82 ctx: C,
83 default: impl FnOnce(
84 C,
85 ReadableStreamDefaultControllerOwned<'js>,
86 ) -> Result<(O, ReadableStreamDefaultControllerOwned<'js>)>,
87 byob: impl FnOnce(
88 C,
89 ReadableByteStreamControllerOwned<'js>,
90 ) -> Result<(O, ReadableByteStreamControllerOwned<'js>)>,
91 ) -> Result<(O, Self)> {
92 match self {
93 ReadableStreamControllerOwned::ReadableStreamDefaultController(r) => {
94 let (ctx, r) = default(ctx, r)?;
95 Ok((ctx, Self::ReadableStreamDefaultController(r)))
96 },
97 ReadableStreamControllerOwned::ReadableStreamByteController(r) => {
98 let (ctx, r) = byob(ctx, r)?;
99 Ok((ctx, Self::ReadableStreamByteController(r)))
100 },
101 }
102 }
103
104 fn into_inner(self) -> Self::Class {
105 match self {
106 ReadableStreamControllerOwned::ReadableStreamDefaultController(c) => {
107 ReadableStreamControllerClass::ReadableStreamDefaultController(c.into_inner())
108 },
109 ReadableStreamControllerOwned::ReadableStreamByteController(c) => {
110 ReadableStreamControllerClass::ReadableStreamByteController(c.into_inner())
111 },
112 }
113 }
114
115 fn from_class(class: Self::Class) -> Self {
116 match class {
117 ReadableStreamControllerClass::ReadableStreamDefaultController(class) => {
118 ReadableStreamControllerOwned::ReadableStreamDefaultController(
119 OwnedBorrowMut::from_class(class),
120 )
121 },
122 ReadableStreamControllerClass::ReadableStreamByteController(class) => {
123 ReadableStreamControllerOwned::ReadableStreamByteController(
124 OwnedBorrowMut::from_class(class),
125 )
126 },
127 ReadableStreamControllerClass::Uninitialised => {
128 panic!("Tried to borrow an uninitialised controller class")
129 },
130 }
131 }
132
133 fn into_erased(self) -> ReadableStreamControllerOwned<'js> {
134 self
135 }
136
137 fn try_from_erased(erased: ReadableStreamControllerOwned<'js>) -> Option<Self> {
138 Some(erased)
139 }
140
141 fn pull_steps(
142 ctx: &Ctx<'js>,
143 objects: ReadableStreamDefaultReaderObjects<'js, Self>,
144 read_request: impl ReadableStreamReadRequest<'js> + 'js,
145 ) -> Result<ReadableStreamDefaultReaderObjects<'js, Self>> {
146 objects
147 .with_controller(
148 read_request,
149 |read_request, objects| {
150 ReadableStreamDefaultControllerOwned::<'js>::pull_steps(
151 ctx,
152 objects,
153 read_request,
154 )
155 .map(|objects| ((), objects))
156 },
157 |read_request, objects| {
158 ReadableByteStreamControllerOwned::<'js>::pull_steps(ctx, objects, read_request)
159 .map(|objects| ((), objects))
160 },
161 )
162 .map(|((), objects)| objects)
163 }
164
165 fn cancel_steps<R: ReadableStreamReader<'js>>(
166 ctx: &Ctx<'js>,
167 objects: ReadableStreamObjects<'js, Self, R>,
168 reason: Value<'js>,
169 ) -> Result<(Promise<'js>, ReadableStreamObjects<'js, Self, R>)> {
170 objects.with_controller(
171 reason,
172 |reason, objects| {
173 ReadableStreamDefaultControllerOwned::<'js>::cancel_steps(ctx, objects, reason)
174 },
175 |reason, objects| {
176 ReadableByteStreamControllerOwned::<'js>::cancel_steps(ctx, objects, reason)
177 },
178 )
179 }
180
181 fn release_steps(&mut self) {
182 match self {
183 ReadableStreamControllerOwned::ReadableStreamDefaultController(c) => c.release_steps(),
184 ReadableStreamControllerOwned::ReadableStreamByteController(c) => c.release_steps(),
185 }
186 }
187}
188
189impl<'js> From<ReadableStreamDefaultControllerOwned<'js>> for ReadableStreamControllerOwned<'js> {
190 fn from(value: ReadableStreamDefaultControllerOwned<'js>) -> Self {
191 Self::ReadableStreamDefaultController(value)
192 }
193}
194
195impl<'js> From<ReadableByteStreamControllerOwned<'js>> for ReadableStreamControllerOwned<'js> {
196 fn from(value: ReadableByteStreamControllerOwned<'js>) -> Self {
197 Self::ReadableStreamByteController(value)
198 }
199}