mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
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:
parent
5195eb38f2
commit
7f98d8e017
1 changed files with 83 additions and 16 deletions
|
@ -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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue