aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/flow.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout/flow.rs')
-rw-r--r--components/layout/flow.rs38
1 files changed, 21 insertions, 17 deletions
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index fbcf7866931..990e29e0238 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -44,7 +44,7 @@ use multicol::MulticolFlow;
use parallel::FlowParallelInfo;
use serde::ser::{Serialize, SerializeStruct, Serializer};
use servo_geometry::{au_rect_to_f32_rect, f32_rect_to_au_rect, max_rect};
-use std::{fmt, mem};
+use std::fmt;
use std::iter::Zip;
use std::slice::IterMut;
use std::sync::Arc;
@@ -65,11 +65,19 @@ use table_rowgroup::TableRowGroupFlow;
use table_wrapper::TableWrapperFlow;
use webrender_api::ClipAndScrollInfo;
+/// This marker trait indicates that a type is a struct with `#[repr(C)]` whose first field
+/// is of type `BaseFlow` or some type that also implements this trait.
+///
+/// In other words, the memory representation of `BaseFlow` must be a prefix
+/// of the memory representation of types implementing `HasBaseFlow`.
+#[allow(unsafe_code)]
+pub unsafe trait HasBaseFlow {}
+
/// Virtual methods that make up a float context.
///
/// Note that virtual methods have a cost; we should not overuse them in Servo. Consider adding
/// methods to `ImmutableFlowUtils` or `MutableFlowUtils` before adding more methods here.
-pub trait Flow: fmt::Debug + Sync + Send + 'static {
+pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
// RTTI
//
// TODO(pcwalton): Use Rust's RTTI, once that works.
@@ -451,11 +459,10 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
#[inline(always)]
#[allow(unsafe_code)]
-pub fn base<T: ?Sized + Flow>(this: &T) -> &BaseFlow {
- unsafe {
- let obj = mem::transmute::<&&T, &::TraitObject>(&this);
- mem::transmute::<*mut (), &BaseFlow>(obj.data)
- }
+pub fn base<T: ?Sized + HasBaseFlow>(this: &T) -> &BaseFlow {
+ let ptr: *const T = this;
+ let ptr = ptr as *const BaseFlow;
+ unsafe { &*ptr }
}
/// Iterates over the children of this immutable flow.
@@ -465,11 +472,10 @@ pub fn child_iter<'a>(flow: &'a Flow) -> FlowListIterator {
#[inline(always)]
#[allow(unsafe_code)]
-pub fn mut_base<T: ?Sized + Flow>(this: &mut T) -> &mut BaseFlow {
- unsafe {
- let obj = mem::transmute::<&&mut T, &::TraitObject>(&this);
- mem::transmute::<*mut (), &mut BaseFlow>(obj.data)
- }
+pub fn mut_base<T: ?Sized + HasBaseFlow>(this: &mut T) -> &mut BaseFlow {
+ let ptr: *mut T = this;
+ let ptr = ptr as *mut BaseFlow;
+ unsafe { &mut *ptr }
}
/// Iterates over the children of this flow.
@@ -1419,11 +1425,9 @@ impl ContainingBlockLink {
pub struct OpaqueFlow(pub usize);
impl OpaqueFlow {
- #[allow(unsafe_code)]
pub fn from_flow(flow: &Flow) -> OpaqueFlow {
- unsafe {
- let object = mem::transmute::<&Flow, ::TraitObject>(flow);
- OpaqueFlow(object.data as usize)
- }
+ let object_ptr: *const Flow = flow;
+ let data_ptr = object_ptr as *const ();
+ OpaqueFlow(data_ptr as usize)
}
}