Implement Clone for PropertyDeclaration by hand 🐉🐲

This makes the enum `#[repr(u16)]` and generate code that shares the same
Clone::clone call for all variants sharing the same field type.
This commit is contained in:
Anthony Ramine 2018-02-05 13:42:46 +01:00
parent 5195eb38f2
commit 7f98d8e017

View file

@ -17,9 +17,10 @@ use custom_properties::CustomPropertiesBuilder;
use servo_arc::{Arc, UniqueArc};
use smallbitvec::SmallBitVec;
use std::borrow::Cow;
use std::{mem, ops};
use std::{ops, ptr};
use std::cell::RefCell;
use std::fmt::{self, Write};
use std::mem::{self, ManuallyDrop};
#[cfg(feature = "servo")] use cssparser::RGBA;
use cssparser::{CowRcStr, Parser, TokenSerializationType, serialize_identifier};
@ -1441,28 +1442,94 @@ impl PropertyId {
}
}
/// Servo's representation for a property declaration.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, PartialEq)]
pub enum PropertyDeclaration {
% for property in data.longhands:
<%
<%
variants = []
for property in data.longhands:
if property.predefined_type and not property.is_vector and not property.is_gecko_size_type_hack:
ty = "::values::specified::{}".format(property.predefined_type)
else:
ty = "longhands::{}::SpecifiedValue".format(property.ident)
if property.boxed:
ty = "Box<{}>".format(ty)
%>
/// ${property.name}
${property.camel_case}(${ty}),
variants.append({
"name": property.camel_case,
"type": ty,
"doc": "`" + property.name + "`",
})
variants += [
{
"name": "CSSWideKeyword",
"type": "WideKeywordDeclaration",
"doc": "A CSS-wide keyword.",
},
{
"name": "WithVariables",
"type": "VariableDeclaration",
"doc": "An unparsed declaration.",
},
{
"name": "Custom",
"type": "CustomDeclaration",
"doc": "A custom property declaration.",
},
]
%>
/// Servo's representation for a property declaration.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(PartialEq)]
#[repr(u16)]
pub enum PropertyDeclaration {
% for variant in variants:
/// ${variant["doc"]}
${variant["name"]}(${variant["type"]}),
% endfor
/// A css-wide keyword.
CSSWideKeyword(WideKeywordDeclaration),
/// An unparsed declaration.
WithVariables(VariableDeclaration),
/// A custom property declaration.
Custom(CustomDeclaration),
}
<%
from itertools import groupby
groups = {}
keyfunc = lambda x: x["type"]
for ty, group in groupby(sorted(variants, key=keyfunc), keyfunc):
groups[ty] = list(group)
%>
impl Clone for PropertyDeclaration {
#[inline]
fn clone(&self) -> Self {
use self::PropertyDeclaration::*;
#[repr(C)]
struct VariantRepr<T> {
tag: u16,
value: T
}
match *self {
% for ty, variants in groups.iteritems():
% if len(variants) == 1:
${variants[0]["name"]}(ref value) => {
${variants[0]["name"]}(value.clone())
}
% else:
${" | ".join("{}(ref value)".format(v["name"]) for v in variants)} => {
unsafe {
let mut out = ManuallyDrop::new(mem::uninitialized());
ptr::write(
&mut out as *mut _ as *mut VariantRepr<${ty}>,
VariantRepr {
tag: *(self as *const _ as *const u16),
value: value.clone(),
},
);
ManuallyDrop::into_inner(out)
}
}
% endif
% endfor
}
}
}
/// A declaration using a CSS-wide keyword.