From a572c0d70be538b702472355e3e2d6da87018f90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 3 Jun 2024 16:40:08 +0000 Subject: [PATCH] Bug 1899949 - Add the ability to have a custom parse function to derived variants. r=jwatt Differential Revision: https://phabricator.services.mozilla.com/D212448 --- servo/components/style/parser.rs | 3 +++ servo/components/style_derive/parse.rs | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/servo/components/style/parser.rs b/servo/components/style/parser.rs index e9977fde1b75..f639f5d49f9f 100644 --- a/servo/components/style/parser.rs +++ b/servo/components/style/parser.rs @@ -178,6 +178,9 @@ impl<'a> ParserContext<'a> { /// * `#[parse(condition = "function")]` can be used to make the parsing of the /// value conditional on `function`, which needs to fulfill /// `fn(&ParserContext) -> bool`. +/// +/// * `#[parse(parse_fn = "function")]` can be used to specify a function other than Parser::parse +/// for a particular variant. pub trait Parse: Sized { /// Parse a value of this type. /// diff --git a/servo/components/style_derive/parse.rs b/servo/components/style_derive/parse.rs index b1a1213435c5..7e71302fe36c 100644 --- a/servo/components/style_derive/parse.rs +++ b/servo/components/style_derive/parse.rs @@ -14,6 +14,7 @@ use synstructure::{Structure, VariantInfo}; pub struct ParseVariantAttrs { pub aliases: Option, pub condition: Option, + pub parse_fn: Option, } #[derive(Default, FromField)] @@ -109,6 +110,7 @@ fn parse_non_keyword_variant( if let Some(ref bitflags) = variant_attrs.bitflags { assert!(skip_try, "Should be the only variant"); + assert!(parse_attrs.parse_fn.is_none(), "should not be needed"); assert!( parse_attrs.condition.is_none(), "Should be the only variant" @@ -118,18 +120,25 @@ fn parse_non_keyword_variant( } let field_attrs = cg::parse_field_attrs::(binding_ast); + if field_attrs.field_bound { cg::add_predicate(where_clause, parse_quote!(#ty: crate::parser::Parse)); } - let mut parse = if skip_try { + let mut parse = if let Some(ref parse_fn) = parse_attrs.parse_fn { + quote! { #parse_fn(context, input) } + } else { + quote! { <#ty as crate::parser::Parse>::parse(context, input) } + }; + + parse = if skip_try { quote! { - let v = <#ty as crate::parser::Parse>::parse(context, input)?; + let v = #parse?; return Ok(#name::#variant_name(v)); } } else { quote! { - if let Ok(v) = input.try(|i| <#ty as crate::parser::Parse>::parse(context, i)) { + if let Ok(v) = input.try(|input| #parse) { return Ok(#name::#variant_name(v)); } } @@ -188,6 +197,8 @@ pub fn derive(mut input: DeriveInput) -> TokenStream { continue; } + assert!(parse_attrs.parse_fn.is_none()); + let identifier = cg::to_css_identifier( &css_variant_attrs .keyword