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}