constellation_traits/structured_data/
transferable.rs1use std::collections::VecDeque;
10
11use base::id::MessagePortId;
12use malloc_size_of_derive::MallocSizeOf;
13use serde::{Deserialize, Serialize};
14use strum::EnumIter;
15
16use crate::PortMessageTask;
17
18#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
19pub struct TransformStreamData {
20 pub readable: (MessagePortId, MessagePortImpl),
21 pub writable: (MessagePortId, MessagePortImpl),
22}
23
24#[derive(Clone, Copy, Debug, EnumIter)]
26pub enum Transferrable {
27 ImageBitmap,
29 MessagePort,
31 OffscreenCanvas,
33 ReadableStream,
35 WritableStream,
37 TransformStream,
39}
40
41#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
42enum MessagePortState {
43 Detached,
45 Enabled(bool),
49 Disabled(bool),
53}
54
55#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
56pub struct MessagePortImpl {
58 state: MessagePortState,
60
61 entangled_port: Option<MessagePortId>,
63
64 message_buffer: Option<VecDeque<PortMessageTask>>,
66
67 message_port_id: MessagePortId,
69}
70
71impl MessagePortImpl {
72 pub fn new(port_id: MessagePortId) -> MessagePortImpl {
74 MessagePortImpl {
75 state: MessagePortState::Disabled(false),
76 entangled_port: None,
77 message_buffer: None,
78 message_port_id: port_id,
79 }
80 }
81
82 pub fn message_port_id(&self) -> &MessagePortId {
84 &self.message_port_id
85 }
86
87 pub fn entangled_port_id(&self) -> Option<MessagePortId> {
89 self.entangled_port
90 }
91
92 pub fn disentangle(&mut self) -> Option<MessagePortId> {
94 self.entangled_port.take()
95 }
96
97 pub fn entangle(&mut self, other_id: MessagePortId) {
99 self.entangled_port = Some(other_id);
100 }
101
102 pub fn enabled(&self) -> bool {
104 matches!(self.state, MessagePortState::Enabled(_))
105 }
106
107 pub fn set_has_been_shipped(&mut self) {
110 match self.state {
111 MessagePortState::Detached => {
112 panic!("Messageport set_has_been_shipped called in detached state")
113 },
114 MessagePortState::Enabled(_) => self.state = MessagePortState::Enabled(true),
115 MessagePortState::Disabled(_) => self.state = MessagePortState::Disabled(true),
116 }
117 }
118
119 pub fn complete_transfer(&mut self, mut tasks: VecDeque<PortMessageTask>) {
122 match self.state {
123 MessagePortState::Detached => return,
124 MessagePortState::Enabled(_) => self.state = MessagePortState::Enabled(false),
125 MessagePortState::Disabled(_) => self.state = MessagePortState::Disabled(false),
126 }
127
128 match self.message_buffer {
133 Some(ref mut incoming_buffer) => {
134 while let Some(task) = tasks.pop_back() {
135 incoming_buffer.push_front(task);
136 }
137 },
138 None => self.message_buffer = Some(tasks),
139 }
140 }
141
142 pub fn handle_incoming(&mut self, task: PortMessageTask) -> Option<PortMessageTask> {
145 let should_dispatch = match self.state {
146 MessagePortState::Detached => return None,
147 MessagePortState::Enabled(in_transfer) => !in_transfer,
148 MessagePortState::Disabled(_) => false,
149 };
150
151 if should_dispatch {
152 Some(task)
153 } else {
154 match self.message_buffer {
155 Some(ref mut buffer) => {
156 buffer.push_back(task);
157 },
158 None => {
159 let mut queue = VecDeque::new();
160 queue.push_back(task);
161 self.message_buffer = Some(queue);
162 },
163 }
164 None
165 }
166 }
167
168 pub fn start(&mut self) -> Option<VecDeque<PortMessageTask>> {
171 match self.state {
172 MessagePortState::Detached => return None,
173 MessagePortState::Enabled(_) => {},
174 MessagePortState::Disabled(in_transfer) => {
175 self.state = MessagePortState::Enabled(in_transfer);
176 },
177 }
178 if let MessagePortState::Enabled(true) = self.state {
179 return None;
180 }
181 self.message_buffer.take()
182 }
183
184 pub fn close(&mut self) {
186 self.state = MessagePortState::Detached;
188 }
189}
190
191#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
192pub struct TransferableOffscreenCanvas {
196 pub width: u64,
197 pub height: u64,
198}