# lib.rs - source
Source of the Rust file `/home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/inventory-impl-0.1.10/src/lib.rs`.
Keywords: rust, rustlang, rust-lang

     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

    extern crate proc_macro;

    use std::collections::hash_map;
    use std::hash::Hasher;

    use proc_macro2::{Ident, Span, TokenStream};
    use quote::quote;
    use syn::parse::{Parse, ParseStream, Result};
    use syn::{bracketed, parse_macro_input, Path, Token};

    struct Input {
        krate: Option<Path>,
        expr: TokenStream,
    }

    impl Parse for Input {
        fn parse(input: ParseStream) -> Result<Self> {
            Ok(Input {
                krate: {
                    // #![crate = gflags]
                    if input.peek(Token![#]) && input.peek2(Token![!]) {
                        input.parse::<Token![#]>()?;
                        input.parse::<Token![!]>()?;
                        let content;
                        bracketed!(content in input);
                        content.parse::<Token![crate]>()?;
                        content.parse::<Token![=]>()?;
                        let krate = content.parse()?;
                        Some(krate)
                    } else {
                        None
                    }
                },
                expr: input.parse()?,
            })
        }
    }

    #[proc_macro]
    #[doc(hidden)]
    pub fn submit(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
        let input = parse_macro_input!(input as Input);

        let expr = input.expr;
        let init = Ident::new(&format!("__init{}", hash(&expr)), Span::call_site());
        let prefix = match input.krate {
            Some(krate) => quote!(#krate::),
            None => quote!(),
        };

        let expanded = quote! {
            #[allow(non_upper_case_globals)]
            #[#prefix inventory::ctor]
            fn #init() {
                // TODO: once existential type is stable, store the caller's
                // expression into a static and string those statics together into
                // an intrusive linked list without needing allocation.
                //
                //     existential type This;
                //
                //     static mut VALUE: Option<inventory::Node<This>> = None;
                //
                //     fn value() -> This {
                //         #expr
                //     }
                //
                //     unsafe {
                //         VALUE = Some(inventory::Node {
                //             value: value(),
                //             next: None,
                //         });
                //         inventory::submit(VALUE.as_mut().unwrap());
                //     }

                #prefix inventory::submit({ #expr });
            }
        };

        proc_macro::TokenStream::from(expanded)
    }

    fn hash(input: &TokenStream) -> u64 {
        let mut hasher = hash_map::DefaultHasher::new();
        hasher.write(input.to_string().as_bytes());
        hasher.finish()
    }