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}