1use crate::path::Path;
2use crate::token;
3use alloc::boxed::Box;
4
5ast_enum! {
6 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
15 pub enum Visibility {
16 Public(Token![pub]),
18
19 Restricted(VisRestricted),
22
23 Inherited,
25 }
26}
27
28ast_struct! {
29 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
32 pub struct VisRestricted {
33 pub pub_token: Token![pub],
34 pub paren_token: token::Paren,
35 pub in_token: Option<Token![in]>,
36 pub path: Box<Path>,
37 }
38}
39
40#[cfg(feature = "parsing")]
41pub(crate) mod parsing {
42 use crate::error::Result;
43 use crate::ext::IdentExt as _;
44 use crate::ident::Ident;
45 use crate::parse::discouraged::Speculative as _;
46 use crate::parse::{Parse, ParseStream};
47 use crate::path::Path;
48 use crate::restriction::{VisRestricted, Visibility};
49 use crate::token;
50 use alloc::boxed::Box;
51
52 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
53 impl Parse for Visibility {
54 fn parse(input: ParseStream) -> Result<Self> {
55 if input.peek(token::Group) {
58 let ahead = input.fork();
59 let group = crate::group::parse_group(&ahead)?;
60 if group.content.is_empty() {
61 input.advance_to(&ahead);
62 return Ok(Visibility::Inherited);
63 }
64 }
65
66 if input.peek(Token![pub]) {
67 Self::parse_pub(input)
68 } else {
69 Ok(Visibility::Inherited)
70 }
71 }
72 }
73
74 impl Visibility {
75 fn parse_pub(input: ParseStream) -> Result<Self> {
76 let pub_token = input.parse::<Token![pub]>()?;
77
78 if input.peek(token::Paren) {
79 let ahead = input.fork();
80
81 let content;
82 let paren_token = parenthesized!(content in ahead);
83 if content.peek(Token![crate])
84 || content.peek(Token![self])
85 || content.peek(Token![super])
86 {
87 let path = content.call(Ident::parse_any)?;
88
89 if content.is_empty() {
94 input.advance_to(&ahead);
95 return Ok(Visibility::Restricted(VisRestricted {
96 pub_token,
97 paren_token,
98 in_token: None,
99 path: Box::new(Path::from(path)),
100 }));
101 }
102 } else if content.peek(Token![in]) {
103 let in_token: Token![in] = content.parse()?;
104 let path = content.call(Path::parse_mod_style)?;
105
106 input.advance_to(&ahead);
107 return Ok(Visibility::Restricted(VisRestricted {
108 pub_token,
109 paren_token,
110 in_token: Some(in_token),
111 path: Box::new(path),
112 }));
113 }
114 }
115
116 Ok(Visibility::Public(pub_token))
117 }
118
119 #[cfg(feature = "full")]
120 pub(crate) fn is_some(&self) -> bool {
121 match self {
122 Visibility::Inherited => false,
123 _ => true,
124 }
125 }
126 }
127}
128
129#[cfg(feature = "printing")]
130mod printing {
131 use crate::path;
132 use crate::path::printing::PathStyle;
133 use crate::restriction::{VisRestricted, Visibility};
134 use proc_macro2::TokenStream;
135 use quote::ToTokens;
136
137 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
138 impl ToTokens for Visibility {
139 fn to_tokens(&self, tokens: &mut TokenStream) {
140 match self {
141 Visibility::Public(pub_token) => pub_token.to_tokens(tokens),
142 Visibility::Restricted(vis_restricted) => vis_restricted.to_tokens(tokens),
143 Visibility::Inherited => {}
144 }
145 }
146 }
147
148 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
149 impl ToTokens for VisRestricted {
150 fn to_tokens(&self, tokens: &mut TokenStream) {
151 self.pub_token.to_tokens(tokens);
152 self.paren_token.surround(tokens, |tokens| {
153 self.in_token.to_tokens(tokens);
156 path::printing::print_path(tokens, &self.path, PathStyle::Mod);
157 });
158 }
159 }
160}