From f6ef35c5d323bef6fdc3d9fbd6048d4a350ef2cb Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Sat, 30 Mar 2019 00:16:08 +0000 Subject: [PATCH] style: Add support for deriving ToShmem. Differential Revision: https://phabricator.services.mozilla.com/D17189 --- components/style/Cargo.toml | 1 + components/style/lib.rs | 2 + components/to_shmem_derive/Cargo.toml | 18 +++++++ components/to_shmem_derive/lib.rs | 26 +++++++++ components/to_shmem_derive/to_shmem.rs | 74 ++++++++++++++++++++++++++ 5 files changed, 121 insertions(+) create mode 100644 components/to_shmem_derive/Cargo.toml create mode 100644 components/to_shmem_derive/lib.rs create mode 100644 components/to_shmem_derive/to_shmem.rs diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index c0dbc02a1863..005924cec21b 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -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" diff --git a/components/style/lib.rs b/components/style/lib.rs index 294b8634d565..bd33dbeafe42 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -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)] diff --git a/components/to_shmem_derive/Cargo.toml b/components/to_shmem_derive/Cargo.toml new file mode 100644 index 000000000000..e5aac7e0aafe --- /dev/null +++ b/components/to_shmem_derive/Cargo.toml @@ -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" diff --git a/components/to_shmem_derive/lib.rs b/components/to_shmem_derive/lib.rs new file mode 100644 index 000000000000..b820e7f85d03 --- /dev/null +++ b/components/to_shmem_derive/lib.rs @@ -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() +} diff --git a/components/to_shmem_derive/to_shmem.rs b/components/to_shmem_derive/to_shmem.rs new file mode 100644 index 000000000000..5021476aad46 --- /dev/null +++ b/components/to_shmem_derive/to_shmem.rs @@ -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::(&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::(&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 { + ::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, +}