mod serializable;
mod transferable;
use log::warn;
use malloc_size_of_derive::MallocSizeOf;
use rustc_hash::{FxBuildHasher, FxHashMap};
use serde::{Deserialize, Serialize};
pub use serializable::*;
use servo_base::id::{
BlobId, DomExceptionId, DomMatrixId, DomPointId, DomQuadId, DomRectId, FileId, FileListId,
ImageBitmapId, ImageDataId, MessagePortId, OffscreenCanvasId, QuotaExceededErrorId,
};
use strum::IntoEnumIterator;
pub use transferable::*;
#[derive(Debug, Default, Deserialize, MallocSizeOf, Serialize)]
pub struct StructuredSerializedData {
pub serialized: Vec<u8>,
pub blobs: Option<FxHashMap<BlobId, BlobImpl>>,
pub files: Option<FxHashMap<FileId, SerializableFile>>,
pub file_lists: Option<FxHashMap<FileListId, SerializableFileList>>,
pub points: Option<FxHashMap<DomPointId, DomPoint>>,
pub rects: Option<FxHashMap<DomRectId, DomRect>>,
pub quads: Option<FxHashMap<DomQuadId, DomQuad>>,
pub matrices: Option<FxHashMap<DomMatrixId, DomMatrix>>,
pub exceptions: Option<FxHashMap<DomExceptionId, DomException>>,
pub quota_exceeded_errors:
Option<FxHashMap<QuotaExceededErrorId, SerializableQuotaExceededError>>,
pub ports: Option<FxHashMap<MessagePortId, MessagePortImpl>>,
pub transform_streams: Option<FxHashMap<MessagePortId, TransformStreamData>>,
pub image_bitmaps: Option<FxHashMap<ImageBitmapId, SerializableImageBitmap>>,
pub transferred_image_bitmaps: Option<FxHashMap<ImageBitmapId, SerializableImageBitmap>>,
pub offscreen_canvases: Option<FxHashMap<OffscreenCanvasId, TransferableOffscreenCanvas>>,
pub image_data: Option<FxHashMap<ImageDataId, SerializableImageData>>,
}
impl StructuredSerializedData {
fn is_empty(&self, val: Transferrable) -> bool {
fn is_field_empty<K, V>(field: &Option<FxHashMap<K, V>>) -> bool {
field.as_ref().is_none_or(|h| h.is_empty())
}
match val {
Transferrable::ImageBitmap => is_field_empty(&self.transferred_image_bitmaps),
Transferrable::MessagePort => is_field_empty(&self.ports),
Transferrable::OffscreenCanvas => is_field_empty(&self.offscreen_canvases),
Transferrable::ReadableStream => is_field_empty(&self.ports),
Transferrable::WritableStream => is_field_empty(&self.ports),
Transferrable::TransformStream => is_field_empty(&self.ports),
}
}
fn clone_all_of_type<T: BroadcastClone>(&self, cloned: &mut StructuredSerializedData) {
let existing = T::source(self);
let Some(existing) = existing else { return };
let mut clones = FxHashMap::with_capacity_and_hasher(existing.len(), FxBuildHasher);
for (original_id, obj) in existing.iter() {
if let Some(clone) = obj.clone_for_broadcast() {
clones.insert(*original_id, clone);
}
}
*T::destination(cloned) = Some(clones);
}
pub fn clone_for_broadcast(&self) -> StructuredSerializedData {
for transferrable in Transferrable::iter() {
if !self.is_empty(transferrable) {
warn!(
"Attempt to broadcast structured serialized data including {:?} (should never happen).",
transferrable,
);
}
}
let serialized = self.serialized.clone();
let mut cloned = StructuredSerializedData {
serialized,
..Default::default()
};
for serializable in Serializable::iter() {
let clone_impl = serializable.clone_values();
clone_impl(self, &mut cloned);
}
cloned
}
}