Bug 1922351 - Move ffi serde serialization from Servo into somewhere usable by other crates in the tree. r=nika

Differential Revision: https://phabricator.services.mozilla.com/D224394
This commit is contained in:
Emilio Cobos Álvarez
2024-10-04 07:51:46 +00:00
parent ec9c48daeb
commit c7589efeac
15 changed files with 166 additions and 155 deletions

10
Cargo.lock generated
View File

@@ -2273,11 +2273,11 @@ name = "geckoservo"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"atomic_refcell", "atomic_refcell",
"bincode",
"cssparser", "cssparser",
"cstr", "cstr",
"dom", "dom",
"gecko-profiler", "gecko-profiler",
"ipdl_utils",
"lazy_static", "lazy_static",
"libc", "libc",
"log", "log",
@@ -2402,6 +2402,7 @@ dependencies = [
"gkrust_utils", "gkrust_utils",
"http_sfv", "http_sfv",
"idna_glue", "idna_glue",
"ipdl_utils",
"jog", "jog",
"jsrust_shared", "jsrust_shared",
"kvstore", "kvstore",
@@ -3191,6 +3192,13 @@ dependencies = [
"sha2", "sha2",
] ]
[[package]]
name = "ipdl_utils"
version = "0.1.0"
dependencies = [
"bincode",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.5" version = "0.10.5"

View File

@@ -45,6 +45,7 @@ exclude = [
"tools/fuzzing/rust", "tools/fuzzing/rust",
"dom/base/rust", "dom/base/rust",
"dom/origin-trials/ffi", "dom/origin-trials/ffi",
"ipc/rust/ipdl_utils",
# Excluded because we don't want to vendor their dependencies. # Excluded because we don't want to vendor their dependencies.
"intl/l10n/rust/l10nregistry-tests", "intl/l10n/rust/l10nregistry-tests",

View File

@@ -21,6 +21,7 @@
#include "mozilla/dom/WebGLIpdl.h" #include "mozilla/dom/WebGLIpdl.h"
#include "mozilla/ipc/ByteBuf.h" #include "mozilla/ipc/ByteBuf.h"
#include "mozilla/ipc/ProtocolMessageUtils.h" #include "mozilla/ipc/ProtocolMessageUtils.h"
#include "mozilla/ipc/RustMessageUtils.h"
#include "mozilla/layers/APZInputBridge.h" #include "mozilla/layers/APZInputBridge.h"
#include "mozilla/layers/AsyncDragMetrics.h" #include "mozilla/layers/AsyncDragMetrics.h"
#include "mozilla/layers/CompositorOptions.h" #include "mozilla/layers/CompositorOptions.h"
@@ -1159,44 +1160,23 @@ struct ParamTraits<mozilla::layers::DoubleTapToZoomMetrics> {
} }
}; };
#define IMPL_PARAMTRAITS_BY_SERDE(type_) \
template <> \
struct ParamTraits<mozilla::type_> { \
typedef mozilla::type_ paramType; \
static void Write(MessageWriter* aWriter, const paramType& aParam) { \
mozilla::ipc::ByteBuf v; \
mozilla::DebugOnly<bool> rv = Servo_##type_##_Serialize(&aParam, &v); \
MOZ_ASSERT(rv, "Serialize ##type_## failed"); \
WriteParam(aWriter, std::move(v)); \
} \
static ReadResult<paramType> Read(MessageReader* aReader) { \
mozilla::ipc::ByteBuf in; \
ReadResult<paramType> result; \
if (!ReadParam(aReader, &in) || !in.mData) { \
return result; \
} \
/* TODO: Should be able to initialize `result` in-place instead */ \
mozilla::AlignedStorage2<paramType> value; \
if (!Servo_##type_##_Deserialize(&in, value.addr())) { \
return result; \
} \
result = std::move(*value.addr()); \
value.addr()->~paramType(); \
return result; \
} \
};
IMPL_PARAMTRAITS_BY_SERDE(LengthPercentage)
IMPL_PARAMTRAITS_BY_SERDE(StyleOffsetPath)
IMPL_PARAMTRAITS_BY_SERDE(StyleOffsetRotate)
IMPL_PARAMTRAITS_BY_SERDE(StylePositionOrAuto)
IMPL_PARAMTRAITS_BY_SERDE(StyleOffsetPosition)
IMPL_PARAMTRAITS_BY_SERDE(StyleRotate)
IMPL_PARAMTRAITS_BY_SERDE(StyleScale)
IMPL_PARAMTRAITS_BY_SERDE(StyleTranslate)
IMPL_PARAMTRAITS_BY_SERDE(StyleTransform)
IMPL_PARAMTRAITS_BY_SERDE(StyleComputedTimingFunction)
} /* namespace IPC */ } /* namespace IPC */
#define DEFINE_SERVO_PARAMTRAITS(ty_) \
MOZ_DEFINE_RUST_PARAMTRAITS(mozilla::ty_, Servo_##ty_##_Serialize, \
Servo_##ty_##_Deserialize)
DEFINE_SERVO_PARAMTRAITS(LengthPercentage)
DEFINE_SERVO_PARAMTRAITS(StyleOffsetPath)
DEFINE_SERVO_PARAMTRAITS(StyleOffsetRotate)
DEFINE_SERVO_PARAMTRAITS(StylePositionOrAuto)
DEFINE_SERVO_PARAMTRAITS(StyleOffsetPosition)
DEFINE_SERVO_PARAMTRAITS(StyleRotate)
DEFINE_SERVO_PARAMTRAITS(StyleScale)
DEFINE_SERVO_PARAMTRAITS(StyleTranslate)
DEFINE_SERVO_PARAMTRAITS(StyleTransform)
DEFINE_SERVO_PARAMTRAITS(StyleComputedTimingFunction)
#undef DEFINE_SERVO_PARAMTRAITS
#endif /* mozilla_layers_LayersMessageUtils */ #endif /* mozilla_layers_LayersMessageUtils */

View File

@@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_ipc_RustMessageUtils_h
#define mozilla_ipc_RustMessageUtils_h
#include "chrome/common/ipc_message_utils.h"
// Some macros for rust integrations. See ipc/rust/ipdl_utils
#define MOZ_DEFINE_RUST_PARAMTRAITS(type_, serializer_, deserializer_) \
extern "C" uint8_t* serializer_(const type_*, size_t* len, size_t* cap); \
extern "C" bool deserializer_(const uint8_t*, size_t len, type_*); \
\
template <> \
struct IPC::ParamTraits<type_> { \
using paramType = type_; \
static void Write(IPC::MessageWriter* aWriter, const paramType& aParam) { \
size_t len, cap; \
uint8_t* buf = serializer_(&aParam, &cap, &len); \
MOZ_DIAGNOSTIC_ASSERT(buf, #type_ " serialization failed"); \
WriteParam(aWriter, mozilla::ipc::ByteBuf(buf, len, cap)); \
} \
static IPC::ReadResult<paramType> Read(IPC::MessageReader* aReader) { \
mozilla::ipc::ByteBuf in; \
IPC::ReadResult<paramType> result; \
if (!ReadParam(aReader, &in) || !in.mData) { \
return result; \
} \
/* TODO: Should be able to initialize `result` in-place instead */ \
mozilla::AlignedStorage2<paramType> value; \
if (!deserializer_(in.mData, in.mLen, value.addr())) { \
return result; \
} \
result = std::move(*value.addr()); \
value.addr()->~paramType(); \
return result; \
} \
};
#endif

View File

@@ -54,6 +54,7 @@ EXPORTS.mozilla.ipc += [
"ProtocolUtils.h", "ProtocolUtils.h",
"RandomAccessStreamUtils.h", "RandomAccessStreamUtils.h",
"RawShmem.h", "RawShmem.h",
"RustMessageUtils.h",
"ScopedPort.h", "ScopedPort.h",
"SerializedStructuredCloneBuffer.h", "SerializedStructuredCloneBuffer.h",
"SharedMemory.h", "SharedMemory.h",

View File

@@ -0,0 +1,14 @@
[package]
name = "ipdl_utils"
version = "0.1.0"
edition = "2021"
authors = [
"Emilio Cobos Álvarez <emilio@crisal.io>",
]
license = "MPL-2.0"
[lib]
path = "lib.rs"
[dependencies]
bincode = "1"

View File

@@ -0,0 +1,47 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#[doc(hidden)]
pub use bincode as _bincode;
/// Takes a type, a serializer, and a deserializer name. The type must implement serde::Serialize.
/// Defines a pair of ffi functions that go along with the MOZ_DEFINE_RUST_PARAMTRAITS macro.
#[macro_export]
macro_rules! define_ffi_serializer {
($ty:ty, $serializer:ident, $deserializer:ident) => {
#[no_mangle]
pub extern "C" fn $serializer(
v: &$ty,
out_len: &mut usize,
out_cap: &mut usize,
) -> *mut u8 {
*out_len = 0;
*out_cap = 0;
let mut buf = match $crate::_bincode::serialize(v) {
Ok(buf) => buf,
Err(..) => return std::ptr::null_mut(),
};
*out_len = buf.len();
*out_cap = buf.capacity();
let ptr = buf.as_mut_ptr();
std::mem::forget(buf);
ptr
}
#[no_mangle]
pub unsafe extern "C" fn $deserializer(
input: *const u8,
len: usize,
out: *mut $ty,
) -> bool {
let slice = std::slice::from_raw_parts(input, len);
let element = match $crate::_bincode::deserialize(slice) {
Ok(buf) => buf,
Err(..) => return false,
};
std::ptr::write(out, element);
true
}
};
}

View File

@@ -103,23 +103,6 @@ BASIC_RULE_FUNCS_LOCKED(NestedDeclarations)
#undef BASIC_RULE_FUNCS_WITHOUT_GETTER_UNLOCKED #undef BASIC_RULE_FUNCS_WITHOUT_GETTER_UNLOCKED
#undef BASIC_RULE_FUNCS_WITHOUT_GETTER_WITH_PREFIX #undef BASIC_RULE_FUNCS_WITHOUT_GETTER_WITH_PREFIX
#define BASIC_SERDE_FUNCS(type_) \
bool Servo_##type_##_Deserialize(mozilla::ipc::ByteBuf* input, type_* v); \
bool Servo_##type_##_Serialize(const type_* v, mozilla::ipc::ByteBuf* output);
BASIC_SERDE_FUNCS(LengthPercentage)
BASIC_SERDE_FUNCS(StyleRotate)
BASIC_SERDE_FUNCS(StyleScale)
BASIC_SERDE_FUNCS(StyleTranslate)
BASIC_SERDE_FUNCS(StyleTransform)
BASIC_SERDE_FUNCS(StyleOffsetPath)
BASIC_SERDE_FUNCS(StyleOffsetRotate)
BASIC_SERDE_FUNCS(StylePositionOrAuto)
BASIC_SERDE_FUNCS(StyleOffsetPosition)
BASIC_SERDE_FUNCS(StyleComputedTimingFunction)
#undef BASIC_SERDE_FUNCS
void Servo_CounterStyleRule_GetDescriptorCssText( void Servo_CounterStyleRule_GetDescriptorCssText(
const StyleLockedCounterStyleRule* rule, nsCSSCounterDesc desc, const StyleLockedCounterStyleRule* rule, nsCSSCounterDesc desc,
nsACString* result); nsACString* result);

View File

@@ -12,7 +12,6 @@ headers = [
"mozilla/dom/MediaList.h", "mozilla/dom/MediaList.h",
"mozilla/dom/ShadowRoot.h", "mozilla/dom/ShadowRoot.h",
"mozilla/gfx/FontFeature.h", "mozilla/gfx/FontFeature.h",
"mozilla/ipc/ByteBuf.h",
"mozilla/AnimationPropertySegment.h", "mozilla/AnimationPropertySegment.h",
"mozilla/ComputedTiming.h", "mozilla/ComputedTiming.h",
"mozilla/CORSMode.h", "mozilla/CORSMode.h",
@@ -209,7 +208,6 @@ allowlist-types = [
"mozilla::dom::IterationCompositeOperation", "mozilla::dom::IterationCompositeOperation",
"mozilla::dom::StyleChildrenIterator", "mozilla::dom::StyleChildrenIterator",
"mozilla::HalfCorner", "mozilla::HalfCorner",
"mozilla::ipc::ByteBuf",
"mozilla::MallocSizeOf", "mozilla::MallocSizeOf",
"mozilla::OriginFlags", "mozilla::OriginFlags",
"mozilla::PropertyStyleAnimationValuePair", "mozilla::PropertyStyleAnimationValuePair",

View File

@@ -125,10 +125,6 @@ class ImageTracker;
} // namespace dom } // namespace dom
namespace ipc {
class ByteBuf;
} // namespace ipc
// Replacement for a Rust Box<T> for a non-dynamically-sized-type. // Replacement for a Rust Box<T> for a non-dynamically-sized-type.
// //
// TODO(emilio): If this was some sort of nullable box then this could be made // TODO(emilio): If this was some sort of nullable box then this could be made

View File

@@ -3,6 +3,7 @@ name = "geckoservo"
version = "0.0.1" version = "0.0.1"
authors = ["The Servo Project Developers"] authors = ["The Servo Project Developers"]
license = "MPL-2.0" license = "MPL-2.0"
edition = "2021"
[lib] [lib]
name = "geckoservo" name = "geckoservo"
@@ -14,10 +15,10 @@ gecko_refcount_logging = ["style/gecko_refcount_logging", "servo_arc/gecko_refco
[dependencies] [dependencies]
atomic_refcell = "0.1" atomic_refcell = "0.1"
bincode = "1.0"
cssparser = "0.34" cssparser = "0.34"
cstr = "0.2" cstr = "0.2"
dom = { path = "../../../dom/base/rust" } dom = { path = "../../../dom/base/rust" }
ipdl_utils = { path = "../../../ipc/rust/ipdl_utils" }
gecko-profiler = { path = "../../../tools/profiler/rust-api" } gecko-profiler = { path = "../../../tools/profiler/rust-api" }
libc = "0.2" libc = "0.2"
log = {version = "0.4", features = ["release_max_level_info"]} log = {version = "0.4", features = ["release_max_level_info"]}

View File

@@ -4,7 +4,6 @@
use super::error_reporter::ErrorReporter; use super::error_reporter::ErrorReporter;
use super::stylesheet_loader::{AsyncStylesheetParser, StylesheetLoader}; use super::stylesheet_loader::{AsyncStylesheetParser, StylesheetLoader};
use bincode::{deserialize, serialize};
use cssparser::ToCss as ParserToCss; use cssparser::ToCss as ParserToCss;
use cssparser::{ use cssparser::{
BasicParseError, ParseError as CssParseError, Parser, ParserInput, ParserState, SourceLocation, BasicParseError, ParseError as CssParseError, Parser, ParserInput, ParserState, SourceLocation,
@@ -60,7 +59,6 @@ use style::gecko_bindings::bindings::Gecko_HaveSeenPtr;
use style::gecko_bindings::structs; use style::gecko_bindings::structs;
use style::gecko_bindings::structs::gfx::FontPaletteValueSet; use style::gecko_bindings::structs::gfx::FontPaletteValueSet;
use style::gecko_bindings::structs::gfxFontFeatureValueSet; use style::gecko_bindings::structs::gfxFontFeatureValueSet;
use style::gecko_bindings::structs::ipc::ByteBuf;
use style::gecko_bindings::structs::nsAtom; use style::gecko_bindings::structs::nsAtom;
use style::gecko_bindings::structs::nsCSSCounterDesc; use style::gecko_bindings::structs::nsCSSCounterDesc;
use style::gecko_bindings::structs::nsCSSFontDesc; use style::gecko_bindings::structs::nsCSSFontDesc;
@@ -994,110 +992,64 @@ pub extern "C" fn Servo_AnimationValue_Uncompute(
.into() .into()
} }
#[inline] ipdl_utils::define_ffi_serializer!(
fn create_byte_buf_from_vec(mut v: Vec<u8>) -> ByteBuf { computed::LengthPercentage,
let w = ByteBuf {
mData: v.as_mut_ptr(),
mLen: v.len(),
mCapacity: v.capacity(),
};
std::mem::forget(v);
w
}
#[inline]
fn view_byte_buf(b: &ByteBuf) -> &[u8] {
if b.mData.is_null() {
debug_assert_eq!(b.mCapacity, 0);
return &[];
}
unsafe { std::slice::from_raw_parts(b.mData, b.mLen) }
}
macro_rules! impl_basic_serde_funcs {
($ser_name:ident, $de_name:ident, $computed_type:ty) => {
#[no_mangle]
pub extern "C" fn $ser_name(v: &$computed_type, output: &mut ByteBuf) -> bool {
let buf = match serialize(v) {
Ok(buf) => buf,
Err(..) => return false,
};
*output = create_byte_buf_from_vec(buf);
true
}
#[no_mangle]
pub unsafe extern "C" fn $de_name(input: &ByteBuf, v: *mut $computed_type) -> bool {
let buf = match deserialize(view_byte_buf(input)) {
Ok(buf) => buf,
Err(..) => return false,
};
std::ptr::write(v, buf);
true
}
};
}
impl_basic_serde_funcs!(
Servo_LengthPercentage_Serialize, Servo_LengthPercentage_Serialize,
Servo_LengthPercentage_Deserialize, Servo_LengthPercentage_Deserialize
computed::LengthPercentage
); );
impl_basic_serde_funcs!( ipdl_utils::define_ffi_serializer!(
computed::transform::Rotate,
Servo_StyleRotate_Serialize, Servo_StyleRotate_Serialize,
Servo_StyleRotate_Deserialize, Servo_StyleRotate_Deserialize
computed::transform::Rotate
); );
impl_basic_serde_funcs!( ipdl_utils::define_ffi_serializer!(
computed::transform::Scale,
Servo_StyleScale_Serialize, Servo_StyleScale_Serialize,
Servo_StyleScale_Deserialize, Servo_StyleScale_Deserialize
computed::transform::Scale
); );
impl_basic_serde_funcs!( ipdl_utils::define_ffi_serializer!(
computed::transform::Translate,
Servo_StyleTranslate_Serialize, Servo_StyleTranslate_Serialize,
Servo_StyleTranslate_Deserialize, Servo_StyleTranslate_Deserialize
computed::transform::Translate
); );
impl_basic_serde_funcs!( ipdl_utils::define_ffi_serializer!(
computed::transform::Transform,
Servo_StyleTransform_Serialize, Servo_StyleTransform_Serialize,
Servo_StyleTransform_Deserialize, Servo_StyleTransform_Deserialize
computed::transform::Transform
); );
impl_basic_serde_funcs!( ipdl_utils::define_ffi_serializer!(
computed::motion::OffsetPath,
Servo_StyleOffsetPath_Serialize, Servo_StyleOffsetPath_Serialize,
Servo_StyleOffsetPath_Deserialize, Servo_StyleOffsetPath_Deserialize
computed::motion::OffsetPath
); );
impl_basic_serde_funcs!( ipdl_utils::define_ffi_serializer!(
computed::motion::OffsetRotate,
Servo_StyleOffsetRotate_Serialize, Servo_StyleOffsetRotate_Serialize,
Servo_StyleOffsetRotate_Deserialize, Servo_StyleOffsetRotate_Deserialize
computed::motion::OffsetRotate
); );
impl_basic_serde_funcs!( ipdl_utils::define_ffi_serializer!(
computed::position::PositionOrAuto,
Servo_StylePositionOrAuto_Serialize, Servo_StylePositionOrAuto_Serialize,
Servo_StylePositionOrAuto_Deserialize, Servo_StylePositionOrAuto_Deserialize
computed::position::PositionOrAuto
); );
impl_basic_serde_funcs!( ipdl_utils::define_ffi_serializer!(
computed::motion::OffsetPosition,
Servo_StyleOffsetPosition_Serialize, Servo_StyleOffsetPosition_Serialize,
Servo_StyleOffsetPosition_Deserialize, Servo_StyleOffsetPosition_Deserialize
computed::motion::OffsetPosition
); );
impl_basic_serde_funcs!( ipdl_utils::define_ffi_serializer!(
ComputedTimingFunction,
Servo_StyleComputedTimingFunction_Serialize, Servo_StyleComputedTimingFunction_Serialize,
Servo_StyleComputedTimingFunction_Deserialize, Servo_StyleComputedTimingFunction_Deserialize
ComputedTimingFunction
); );
// Return the ComputedValues by a base ComputedValues and the rules. // Return the ComputedValues by a base ComputedValues and the rules.

View File

@@ -2,28 +2,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
extern crate bincode;
extern crate cssparser;
#[macro_use] #[macro_use]
extern crate cstr; extern crate cstr;
extern crate dom;
#[macro_use] #[macro_use]
extern crate gecko_profiler; extern crate gecko_profiler;
extern crate libc;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
extern crate malloc_size_of;
extern crate nsstring;
extern crate num_traits;
extern crate selectors;
extern crate servo_arc;
extern crate smallvec;
#[macro_use] #[macro_use]
extern crate style; extern crate style;
extern crate style_traits;
extern crate thin_vec;
extern crate to_shmem;
extern crate lazy_static;
mod error_reporter; mod error_reporter;
#[allow(non_snake_case)] #[allow(non_snake_case)]

View File

@@ -55,6 +55,7 @@ fog_control = { path = "../../../components/glean" }
app_services_logger = { path = "../../../../services/common/app_services_logger" } app_services_logger = { path = "../../../../services/common/app_services_logger" }
http_sfv = { path = "../../../../netwerk/base/http-sfv" } http_sfv = { path = "../../../../netwerk/base/http-sfv" }
idna_glue = { path = "../../../../netwerk/base/idna_glue" } idna_glue = { path = "../../../../netwerk/base/idna_glue" }
ipdl_utils = { path = "../../../../ipc/rust/ipdl_utils" }
unic-langid = { version = "0.9", features = ["likelysubtags"] } unic-langid = { version = "0.9", features = ["likelysubtags"] }
unic-langid-ffi = { path = "../../../../intl/locale/rust/unic-langid-ffi" } unic-langid-ffi = { path = "../../../../intl/locale/rust/unic-langid-ffi" }
fluent-langneg = { version = "0.13", features = ["cldr"] } fluent-langneg = { version = "0.13", features = ["cldr"] }

View File

@@ -32,6 +32,7 @@ extern crate gecko_profiler;
extern crate gkrust_utils; extern crate gkrust_utils;
extern crate http_sfv; extern crate http_sfv;
extern crate idna_glue; extern crate idna_glue;
extern crate ipdl_utils;
extern crate jog; extern crate jog;
extern crate jsrust_shared; extern crate jsrust_shared;
extern crate kvstore; extern crate kvstore;