style: Add support for deriving ToShmem.

Differential Revision: https://phabricator.services.mozilla.com/D17189
This commit is contained in:
Cameron McCormack 2019-03-30 00:16:08 +00:00 committed by Emilio Cobos Álvarez
parent d8a758272e
commit f6ef35c5d3
5 changed files with 121 additions and 0 deletions

View file

@ -69,6 +69,7 @@ style_traits = {path = "../style_traits"}
servo_url = {path = "../url", optional = true}
thin-slice = "0.1.0"
to_shmem = {path = "../to_shmem"}
to_shmem_derive = {path = "../to_shmem_derive"}
time = "0.1"
uluru = "0.3"
unicode-bidi = "0.3"

View file

@ -100,6 +100,8 @@ extern crate style_traits;
extern crate thin_slice;
extern crate time;
extern crate to_shmem;
#[macro_use]
extern crate to_shmem_derive;
extern crate uluru;
extern crate unicode_bidi;
#[allow(unused_extern_crates)]

View file

@ -0,0 +1,18 @@
[package]
name = "to_shmem_derive"
version = "0.0.1"
authors = ["The Servo Project Developers"]
license = "MPL-2.0"
publish = false
[lib]
path = "lib.rs"
proc-macro = true
[dependencies]
darling = "0.8"
derive_common = { path = "../derive_common" }
proc-macro2 = "0.4"
quote = "0.6"
syn = { version = "0.15", features = ["visit"] }
synstructure = "0.10"

View file

@ -0,0 +1,26 @@
/* 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/. */
#![recursion_limit = "128"]
#[macro_use]
extern crate darling;
extern crate derive_common;
extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
extern crate synstructure;
use proc_macro::TokenStream;
mod to_shmem;
#[proc_macro_derive(ToShmem, attributes(shmem))]
pub fn derive_to_shmem(stream: TokenStream) -> TokenStream {
let input = syn::parse(stream).unwrap();
to_shmem::derive(input).into()
}

View file

@ -0,0 +1,74 @@
/* 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/. */
use derive_common::cg;
use proc_macro2::TokenStream;
use syn;
use synstructure::{BindStyle, Structure};
pub fn derive(mut input: syn::DeriveInput) -> TokenStream {
let mut where_clause = input.generics.where_clause.take();
let attrs = cg::parse_input_attrs::<ShmemInputAttrs>(&input);
if !attrs.no_bounds {
for param in input.generics.type_params() {
cg::add_predicate(
&mut where_clause,
parse_quote!(#param: ::to_shmem::ToShmem),
);
}
}
for variant in Structure::new(&input).variants() {
for binding in variant.bindings() {
let attrs = cg::parse_field_attrs::<ShmemFieldAttrs>(&binding.ast());
if attrs.field_bound {
let ty = &binding.ast().ty;
cg::add_predicate(
&mut where_clause,
parse_quote!(#ty: ::to_shmem::ToShmem),
)
}
}
}
input.generics.where_clause = where_clause;
let match_body = cg::fmap_match(&input, BindStyle::Ref, |binding| {
quote! {
::std::mem::ManuallyDrop::into_inner(
::to_shmem::ToShmem::to_shmem(#binding, builder)
)
}
});
let name = &input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
quote! {
impl #impl_generics ::to_shmem::ToShmem for #name #ty_generics #where_clause {
#[allow(unused_variables)]
fn to_shmem(
&self,
builder: &mut ::to_shmem::SharedMemoryBuilder,
) -> ::std::mem::ManuallyDrop<Self> {
::std::mem::ManuallyDrop::new(
match *self {
#match_body
}
)
}
}
}
}
#[darling(attributes(shmem), default)]
#[derive(Default, FromDeriveInput)]
pub struct ShmemInputAttrs {
pub no_bounds: bool,
}
#[darling(attributes(shmem), default)]
#[derive(Default, FromField)]
pub struct ShmemFieldAttrs {
pub field_bound: bool,
}