File: parse.rs

package info (click to toggle)
thunderbird 1%3A60.9.0-1~deb9u1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 2,339,492 kB
  • sloc: cpp: 5,457,040; ansic: 2,360,385; python: 596,167; asm: 340,963; java: 326,296; xml: 258,830; sh: 84,445; makefile: 23,705; perl: 17,317; objc: 3,768; yacc: 1,766; ada: 1,681; lex: 1,364; pascal: 1,264; cs: 879; exp: 527; php: 436; lisp: 258; ruby: 153; awk: 152; sed: 53; csh: 27
file content (94 lines) | stat: -rw-r--r-- 2,858 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/* 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 cg;
use quote::Tokens;
use syn::DeriveInput;
use synstructure;
use to_css::CssVariantAttrs;

pub fn derive(input: DeriveInput) -> Tokens {
    let name = &input.ident;
    let s = synstructure::Structure::new(&input);

    let match_body = s.variants().iter().fold(quote!(), |match_body, variant| {
        let bindings = variant.bindings();
        assert!(
            bindings.is_empty(),
            "Parse is only supported for single-variant enums for now"
        );

        let variant_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(&variant.ast());
        let identifier = cg::to_css_identifier(
            &variant_attrs.keyword.unwrap_or(variant.ast().ident.as_ref().into()),
        );
        let ident = &variant.ast().ident;

        let mut body = quote! {
            #match_body
            #identifier => Ok(#name::#ident),
        };


        let aliases = match variant_attrs.aliases {
            Some(aliases) => aliases,
            None => return body,
        };

        for alias in aliases.split(",") {
            body = quote! {
                #body
                #alias => Ok(#name::#ident),
            };
        }

        body
    });

    let parse_trait_impl = quote! {
        impl ::parser::Parse for #name {
            #[inline]
            fn parse<'i, 't>(
                _: &::parser::ParserContext,
                input: &mut ::cssparser::Parser<'i, 't>,
            ) -> Result<Self, ::style_traits::ParseError<'i>> {
                Self::parse(input)
            }
        }
    };

    // TODO(emilio): It'd be nice to get rid of these, but that makes the
    // conversion harder...
    let methods_impl = quote! {
        impl #name {
            /// Parse this keyword.
            #[inline]
            pub fn parse<'i, 't>(
                input: &mut ::cssparser::Parser<'i, 't>,
            ) -> Result<Self, ::style_traits::ParseError<'i>> {
                let location = input.current_source_location();
                let ident = input.expect_ident()?;
                Self::from_ident(ident.as_ref()).map_err(|()| {
                    location.new_unexpected_token_error(
                        ::cssparser::Token::Ident(ident.clone())
                    )
                })
            }

            /// Parse this keyword from a string slice.
            #[inline]
            pub fn from_ident(ident: &str) -> Result<Self, ()> {
                match_ignore_ascii_case! { ident,
                    #match_body
                    _ => Err(()),
                }
            }
        }
    };

    quote! {
        #parse_trait_impl
        #methods_impl
    }
}