use std::collections::VecDeque;
use malloc_size_of_derive::MallocSizeOf;
use serde::{Deserialize, Serialize};
use servo_base::id::MessagePortId;
use strum::EnumIter;
use crate::PortMessageTask;
#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
pub struct TransformStreamData {
pub readable: (MessagePortId, MessagePortImpl),
pub writable: (MessagePortId, MessagePortImpl),
}
#[derive(Clone, Copy, Debug, EnumIter)]
pub enum Transferrable {
ImageBitmap,
MessagePort,
OffscreenCanvas,
ReadableStream,
WritableStream,
TransformStream,
}
#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
enum MessagePortState {
Detached,
Enabled(bool),
Disabled(bool),
}
#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
pub struct MessagePortImpl {
state: MessagePortState,
entangled_port: Option<MessagePortId>,
message_buffer: Option<VecDeque<PortMessageTask>>,
message_port_id: MessagePortId,
}
impl MessagePortImpl {
pub fn new(port_id: MessagePortId) -> MessagePortImpl {
MessagePortImpl {
state: MessagePortState::Disabled(false),
entangled_port: None,
message_buffer: None,
message_port_id: port_id,
}
}
pub fn message_port_id(&self) -> &MessagePortId {
&self.message_port_id
}
pub fn entangled_port_id(&self) -> Option<MessagePortId> {
self.entangled_port
}
pub fn disentangle(&mut self) -> Option<MessagePortId> {
self.entangled_port.take()
}
pub fn entangle(&mut self, other_id: MessagePortId) {
self.entangled_port = Some(other_id);
}
pub fn enabled(&self) -> bool {
matches!(self.state, MessagePortState::Enabled(_))
}
pub fn set_has_been_shipped(&mut self) {
match self.state {
MessagePortState::Detached => {
panic!("Messageport set_has_been_shipped called in detached state")
},
MessagePortState::Enabled(_) => self.state = MessagePortState::Enabled(true),
MessagePortState::Disabled(_) => self.state = MessagePortState::Disabled(true),
}
}
pub fn complete_transfer(&mut self, mut tasks: VecDeque<PortMessageTask>) {
match self.state {
MessagePortState::Detached => return,
MessagePortState::Enabled(_) => self.state = MessagePortState::Enabled(false),
MessagePortState::Disabled(_) => self.state = MessagePortState::Disabled(false),
}
match self.message_buffer {
Some(ref mut incoming_buffer) => {
while let Some(task) = tasks.pop_back() {
incoming_buffer.push_front(task);
}
},
None => self.message_buffer = Some(tasks),
}
}
pub fn handle_incoming(&mut self, task: PortMessageTask) -> Option<PortMessageTask> {
let should_dispatch = match self.state {
MessagePortState::Detached => return None,
MessagePortState::Enabled(in_transfer) => !in_transfer,
MessagePortState::Disabled(_) => false,
};
if should_dispatch {
Some(task)
} else {
match self.message_buffer {
Some(ref mut buffer) => {
buffer.push_back(task);
},
None => {
let mut queue = VecDeque::new();
queue.push_back(task);
self.message_buffer = Some(queue);
},
}
None
}
}
pub fn start(&mut self) -> Option<VecDeque<PortMessageTask>> {
match self.state {
MessagePortState::Detached => return None,
MessagePortState::Enabled(_) => {},
MessagePortState::Disabled(in_transfer) => {
self.state = MessagePortState::Enabled(in_transfer);
},
}
if let MessagePortState::Enabled(true) = self.state {
return None;
}
self.message_buffer.take()
}
pub fn close(&mut self) {
self.state = MessagePortState::Detached;
}
}
#[derive(Debug, Deserialize, MallocSizeOf, Serialize)]
pub struct TransferableOffscreenCanvas {
pub width: u64,
pub height: u64,
}