Skip to main content

diesel_derives/
diesel_public_if.rs

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