diesel_derives/
diesel_public_if.rs

1use quote::quote;
2use syn::Token;
3use syn::{punctuated::Punctuated, DeriveInput};
4
5pub(crate) fn expand(cfg: CfgInput, item: EntryWithVisibility) -> proc_macro2::TokenStream {
6    item.hide_for_cfg(cfg.cfg, cfg.field_list)
7}
8
9pub struct CfgInput {
10    cfg: syn::Meta,
11    field_list: Vec<syn::Ident>,
12}
13
14impl syn::parse::Parse for CfgInput {
15    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
16        let mut cfg = Punctuated::<syn::Meta, Token![,]>::parse_terminated(input)?;
17        if cfg.len() == 1 {
18            Ok(Self {
19                cfg: cfg
20                    .pop()
21                    .expect("There is exactly one element")
22                    .into_value(),
23                field_list: Vec::new(),
24            })
25        } else if cfg.len() == 2 {
26            let value_1 = cfg
27                .pop()
28                .expect("There is exactly one element")
29                .into_value();
30            let value_2 = cfg
31                .pop()
32                .expect("There is exactly one element")
33                .into_value();
34            let (cfg, fields) = if #[allow(non_exhaustive_omitted_patterns)] match &value_1 {
    syn::Meta::List(v) if v.path.is_ident("public_fields") => true,
    _ => false,
}matches!(&value_1, syn::Meta::List(v) if v.path.is_ident("public_fields"))
35            {
36                (value_2, value_1)
37            } else if #[allow(non_exhaustive_omitted_patterns)] match &value_2 {
    syn::Meta::List(v) if v.path.is_ident("public_fields") => true,
    _ => false,
}matches!(&value_2, syn::Meta::List(v) if v.path.is_ident("public_fields")) {
38                (value_1, value_2)
39            } else {
40                {
    ::core::panicking::panic_fmt(format_args!("Incompatible argument list detected. `__diesel_public_if` expects a cfg argument and a optional public_fields"));
}panic!(
41                    "Incompatible argument list detected. `__diesel_public_if` \
42                     expects a cfg argument and a optional public_fields"
43                )
44            };
45            let field_list = if let syn::Meta::List(v) = fields {
46                use syn::parse::Parser;
47                let parser =
48                    syn::punctuated::Punctuated::<syn::Ident, syn::Token![,]>::parse_terminated;
49                let idents = parser.parse2(v.tokens)?;
50                idents.into_iter().collect()
51            } else {
52                ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
53            };
54            Ok(Self { cfg, field_list })
55        } else {
56            {
    ::core::panicking::panic_fmt(format_args!("Incompatible argument list detected. `__diesel_public_if` expects a cfg argument and an optional public_fields"));
}panic!(
57                "Incompatible argument list detected. `__diesel_public_if` \
58                 expects a cfg argument and an optional public_fields"
59            )
60        }
61    }
62}
63
64#[derive(#[automatically_derived]
impl ::core::clone::Clone for EntryWithVisibility {
    #[inline]
    fn clone(&self) -> EntryWithVisibility {
        match self {
            EntryWithVisibility::TraitFunction {
                meta: __self_0, tail: __self_1 } =>
                EntryWithVisibility::TraitFunction {
                    meta: ::core::clone::Clone::clone(__self_0),
                    tail: ::core::clone::Clone::clone(__self_1),
                },
            EntryWithVisibility::Item {
                meta: __self_0, vis: __self_1, tail: __self_2 } =>
                EntryWithVisibility::Item {
                    meta: ::core::clone::Clone::clone(__self_0),
                    vis: ::core::clone::Clone::clone(__self_1),
                    tail: ::core::clone::Clone::clone(__self_2),
                },
            EntryWithVisibility::Struct {
                meta: __self_0,
                vis: __self_1,
                def: __self_2,
                ident: __self_3,
                generics: __self_4 } =>
                EntryWithVisibility::Struct {
                    meta: ::core::clone::Clone::clone(__self_0),
                    vis: ::core::clone::Clone::clone(__self_1),
                    def: ::core::clone::Clone::clone(__self_2),
                    ident: ::core::clone::Clone::clone(__self_3),
                    generics: ::core::clone::Clone::clone(__self_4),
                },
        }
    }
}Clone)]
65pub enum EntryWithVisibility {
66    TraitFunction {
67        meta: Vec<syn::Attribute>,
68        tail: proc_macro2::TokenStream,
69    },
70    Item {
71        meta: Vec<syn::Attribute>,
72        vis: syn::Visibility,
73        tail: proc_macro2::TokenStream,
74    },
75    Struct {
76        meta: Vec<syn::Attribute>,
77        vis: syn::Visibility,
78        def: syn::DataStruct,
79        ident: syn::Ident,
80        generics: syn::Generics,
81    },
82}
83
84impl syn::parse::Parse for EntryWithVisibility {
85    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
86        let meta = syn::Attribute::parse_outer(input)?;
87        if input.peek(::syn::token::FnToken![fn]) || input.peek(::syn::token::TypeToken![type]) {
88            let tail = input.parse()?;
89            Ok(Self::TraitFunction { meta, tail })
90        } else {
91            let vis = input.parse()?;
92            if input.peek(::syn::token::StructToken![struct]) {
93                let s = DeriveInput::parse(input)?;
94                if let syn::Data::Struct(def) = s.data {
95                    Ok(Self::Struct {
96                        meta,
97                        vis,
98                        def,
99                        generics: s.generics,
100                        ident: s.ident,
101                    })
102                } else {
103                    ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
104                }
105            } else {
106                let tail = input.parse()?;
107                Ok(Self::Item { meta, vis, tail })
108            }
109        }
110    }
111}
112
113impl EntryWithVisibility {
114    fn hide_for_cfg(
115        &self,
116        cfg: syn::Meta,
117        field_list: Vec<syn::Ident>,
118    ) -> proc_macro2::TokenStream {
119        match self {
120            EntryWithVisibility::TraitFunction { meta, tail } if field_list.is_empty() => {
    let mut _s = ::quote::__private::TokenStream::new();
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut meta, i) = meta.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let meta =
                match meta.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&meta, &mut _s);
        }
    }
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "cfg_attr");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "not");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&cfg, &mut _s);
                            _s
                        });
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "doc");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "hidden");
                            _s
                        });
                    _s
                });
            _s
        });
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "cfg_attr");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "docsrs");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "doc");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "cfg");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::ToTokens::to_tokens(&cfg, &mut _s);
                                    _s
                                });
                            _s
                        });
                    _s
                });
            _s
        });
    ::quote::ToTokens::to_tokens(&tail, &mut _s);
    _s
}quote! {
121                #(#meta)*
122                #[cfg_attr(not(#cfg), doc(hidden))]
123                #[cfg_attr(docsrs, doc(cfg(#cfg)))]
124                #tail
125            },
126            EntryWithVisibility::Item { meta, vis, tail } if field_list.is_empty() => {
127                {
    let mut _s = ::quote::__private::TokenStream::new();
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut meta, i) = meta.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let meta =
                match meta.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&meta, &mut _s);
        }
    }
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "cfg");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "not");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&cfg, &mut _s);
                            _s
                        });
                    _s
                });
            _s
        });
    ::quote::ToTokens::to_tokens(&vis, &mut _s);
    ::quote::ToTokens::to_tokens(&tail, &mut _s);
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut meta, i) = meta.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let meta =
                match meta.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&meta, &mut _s);
        }
    }
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "cfg");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&cfg, &mut _s);
                    _s
                });
            _s
        });
    ::quote::__private::push_ident(&mut _s, "pub");
    ::quote::ToTokens::to_tokens(&tail, &mut _s);
    _s
}quote! {
128                    #(#meta)*
129                    #[cfg(not(#cfg))]
130                    #vis #tail
131
132                    #(#meta)*
133                    #[cfg(#cfg)]
134                    pub #tail
135                }
136            }
137            EntryWithVisibility::Struct {
138                meta,
139                vis,
140                def,
141                ident,
142                generics,
143            } => {
144                let fields1 = def.fields.iter();
145                let fields2 = def.fields.iter().map(|f| {
146                    let mut ret = f.clone();
147                    if ret
148                        .ident
149                        .as_ref()
150                        .map(|i| field_list.contains(i))
151                        .unwrap_or(false)
152                    {
153                        ret.vis = syn::Visibility::Public(Default::default());
154                    }
155                    ret
156                });
157
158                {
    let mut _s = ::quote::__private::TokenStream::new();
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut meta, i) = meta.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let meta =
                match meta.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&meta, &mut _s);
        }
    }
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "cfg");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "not");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::ToTokens::to_tokens(&cfg, &mut _s);
                            _s
                        });
                    _s
                });
            _s
        });
    ::quote::ToTokens::to_tokens(&vis, &mut _s);
    ::quote::__private::push_ident(&mut _s, "struct");
    ::quote::ToTokens::to_tokens(&ident, &mut _s);
    ::quote::ToTokens::to_tokens(&generics, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            {
                use ::quote::__private::ext::*;
                let has_iter = ::quote::__private::HasIterator::<false>;
                #[allow(unused_mut)]
                let (mut fields1, i) = fields1.quote_into_iter();
                let has_iter = has_iter | i;
                <_ as
                        ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                while true {
                    let fields1 =
                        match fields1.next() {
                            Some(_x) => ::quote::__private::RepInterp(_x),
                            None => break,
                        };
                    ::quote::ToTokens::to_tokens(&fields1, &mut _s);
                    ::quote::__private::push_comma(&mut _s);
                }
            }
            _s
        });
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut meta, i) = meta.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let meta =
                match meta.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&meta, &mut _s);
        }
    }
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "cfg");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&cfg, &mut _s);
                    _s
                });
            _s
        });
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "non_exhaustive");
            _s
        });
    ::quote::__private::push_ident(&mut _s, "pub");
    ::quote::__private::push_ident(&mut _s, "struct");
    ::quote::ToTokens::to_tokens(&ident, &mut _s);
    ::quote::ToTokens::to_tokens(&generics, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            {
                use ::quote::__private::ext::*;
                let has_iter = ::quote::__private::HasIterator::<false>;
                #[allow(unused_mut)]
                let (mut fields2, i) = fields2.quote_into_iter();
                let has_iter = has_iter | i;
                <_ as
                        ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                while true {
                    let fields2 =
                        match fields2.next() {
                            Some(_x) => ::quote::__private::RepInterp(_x),
                            None => break,
                        };
                    ::quote::ToTokens::to_tokens(&fields2, &mut _s);
                    ::quote::__private::push_comma(&mut _s);
                }
            }
            _s
        });
    _s
}quote! {
159                    #(#meta)*
160                    #[cfg(not(#cfg))]
161                    #vis struct #ident #generics {
162                        #(#fields1,)*
163                    }
164
165                    #(#meta)*
166                    #[cfg(#cfg)]
167                    #[non_exhaustive]
168                    pub struct #ident #generics {
169                        #(#fields2,)*
170                    }
171                }
172            }
173            EntryWithVisibility::TraitFunction { .. } | EntryWithVisibility::Item { .. } => {
174                {
    ::core::panicking::panic_fmt(format_args!("Public field list is only supported for structs"));
}panic!("Public field list is only supported for structs")
175            }
176        }
177    }
178}