blob: f21bfd8a707ddae87cacecaa4b07b0f15c7b5841 [file] [log] [blame]
David Tolnayf38cdf62016-09-23 19:07:09 -07001use super::*;
2
Clar Charrd22b5702017-03-10 15:24:56 -05003/// An enum variant.
David Tolnay9bf4af82017-01-07 11:17:46 -08004#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayf38cdf62016-09-23 19:07:09 -07005pub struct Variant {
Clar Charrd22b5702017-03-10 15:24:56 -05006 /// Name of the variant.
David Tolnayf38cdf62016-09-23 19:07:09 -07007 pub ident: Ident,
Clar Charrd22b5702017-03-10 15:24:56 -05008
9 /// Attributes tagged on the variant.
David Tolnayf38cdf62016-09-23 19:07:09 -070010 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -050011
12 /// Type of variant.
David Tolnayf38cdf62016-09-23 19:07:09 -070013 pub data: VariantData,
Clar Charrd22b5702017-03-10 15:24:56 -050014
David Tolnayf38cdf62016-09-23 19:07:09 -070015 /// Explicit discriminant, e.g. `Foo = 1`
David Tolnay3cb23a92016-10-07 23:02:21 -070016 pub discriminant: Option<ConstExpr>,
David Tolnayf38cdf62016-09-23 19:07:09 -070017}
18
Clar Charrd22b5702017-03-10 15:24:56 -050019/// Data stored within an enum variant or struct.
David Tolnay9bf4af82017-01-07 11:17:46 -080020#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayf38cdf62016-09-23 19:07:09 -070021pub enum VariantData {
Clar Charrd22b5702017-03-10 15:24:56 -050022 /// Struct variant, e.g. `Point { x: f64, y: f64 }`.
David Tolnayf38cdf62016-09-23 19:07:09 -070023 Struct(Vec<Field>),
Clar Charrd22b5702017-03-10 15:24:56 -050024
25 /// Tuple variant, e.g. `Some(T)`.
David Tolnayf38cdf62016-09-23 19:07:09 -070026 Tuple(Vec<Field>),
Clar Charrd22b5702017-03-10 15:24:56 -050027
28 /// Unit variant, e.g. `None`.
David Tolnayf38cdf62016-09-23 19:07:09 -070029 Unit,
30}
31
32impl VariantData {
Clar Charrd22b5702017-03-10 15:24:56 -050033 /// Slice containing the fields stored in the variant.
David Tolnayf38cdf62016-09-23 19:07:09 -070034 pub fn fields(&self) -> &[Field] {
35 match *self {
36 VariantData::Struct(ref fields) |
37 VariantData::Tuple(ref fields) => fields,
38 VariantData::Unit => &[],
39 }
40 }
Sean Griffin15085c42016-10-03 11:40:31 -040041
Clar Charrd22b5702017-03-10 15:24:56 -050042 /// Mutable slice containing the fields stored in the variant.
Sean Griffin15085c42016-10-03 11:40:31 -040043 pub fn fields_mut(&mut self) -> &mut [Field] {
44 match *self {
45 VariantData::Struct(ref mut fields) |
46 VariantData::Tuple(ref mut fields) => fields,
47 VariantData::Unit => &mut [],
48 }
49 }
David Tolnayf38cdf62016-09-23 19:07:09 -070050}
51
Clar Charrd22b5702017-03-10 15:24:56 -050052/// A field of a struct or enum variant.
David Tolnay9bf4af82017-01-07 11:17:46 -080053#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayf38cdf62016-09-23 19:07:09 -070054pub struct Field {
Clar Charrd22b5702017-03-10 15:24:56 -050055 /// Name of the field, if any.
56 ///
57 /// Fields of tuple structs have no names.
David Tolnayf38cdf62016-09-23 19:07:09 -070058 pub ident: Option<Ident>,
Clar Charrd22b5702017-03-10 15:24:56 -050059
60 /// Visibility of the field.
David Tolnayf38cdf62016-09-23 19:07:09 -070061 pub vis: Visibility,
Clar Charrd22b5702017-03-10 15:24:56 -050062
63 /// Attributes tagged on the field.
David Tolnayf38cdf62016-09-23 19:07:09 -070064 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -050065
66 /// Type of the field.
David Tolnayf38cdf62016-09-23 19:07:09 -070067 pub ty: Ty,
68}
69
Clar Charrd22b5702017-03-10 15:24:56 -050070
71/// Visibility level of an item.
David Tolnay9bf4af82017-01-07 11:17:46 -080072#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayf38cdf62016-09-23 19:07:09 -070073pub enum Visibility {
Clar Charrd22b5702017-03-10 15:24:56 -050074 /// Public, i.e. `pub`.
David Tolnayf38cdf62016-09-23 19:07:09 -070075 Public,
Clar Charrd22b5702017-03-10 15:24:56 -050076
77 /// Crate-visible, i.e. `pub(crate)`.
David Tolnaye07f9e02016-10-30 17:05:55 -070078 Crate,
Clar Charrd22b5702017-03-10 15:24:56 -050079
80 /// Restricted, e.g. `pub(some::module)`.
David Tolnaye07f9e02016-10-30 17:05:55 -070081 Restricted(Box<Path>),
Clar Charrd22b5702017-03-10 15:24:56 -050082
83 /// Inherited, i.e. private.
David Tolnayf38cdf62016-09-23 19:07:09 -070084 Inherited,
85}
86
David Tolnayf38cdf62016-09-23 19:07:09 -070087#[cfg(feature = "parsing")]
88pub mod parsing {
89 use super::*;
David Tolnay28c1db62016-10-27 22:48:18 -070090 use WhereClause;
David Tolnay514f1292017-02-27 12:30:57 -080091 #[cfg(feature = "full")]
92 use ConstExpr;
David Tolnay4a51dc72016-10-01 00:40:31 -070093 use attr::parsing::outer_attr;
David Tolnayf945fb52017-02-27 12:53:54 -080094 #[cfg(feature = "full")]
David Tolnay3cb23a92016-10-07 23:02:21 -070095 use constant::parsing::const_expr;
David Tolnay514f1292017-02-27 12:30:57 -080096 #[cfg(feature = "full")]
97 use expr::parsing::expr;
David Tolnay28c1db62016-10-27 22:48:18 -070098 use generics::parsing::where_clause;
David Tolnayf38cdf62016-09-23 19:07:09 -070099 use ident::parsing::ident;
David Tolnaye07f9e02016-10-30 17:05:55 -0700100 use ty::parsing::{path, ty};
David Tolnayf38cdf62016-09-23 19:07:09 -0700101
David Tolnay28c1db62016-10-27 22:48:18 -0700102 named!(pub struct_body -> (WhereClause, VariantData), alt!(
103 do_parse!(
104 wh: where_clause >>
105 body: struct_like_body >>
106 (wh, VariantData::Struct(body))
107 )
David Tolnayf38cdf62016-09-23 19:07:09 -0700108 |
David Tolnay28c1db62016-10-27 22:48:18 -0700109 do_parse!(
110 body: tuple_like_body >>
111 wh: where_clause >>
112 punct!(";") >>
113 (wh, VariantData::Tuple(body))
114 )
David Tolnayf38cdf62016-09-23 19:07:09 -0700115 |
David Tolnay28c1db62016-10-27 22:48:18 -0700116 do_parse!(
117 wh: where_clause >>
118 punct!(";") >>
119 (wh, VariantData::Unit)
120 )
David Tolnayf38cdf62016-09-23 19:07:09 -0700121 ));
122
David Tolnay28c1db62016-10-27 22:48:18 -0700123 named!(pub enum_body -> (WhereClause, Vec<Variant>), do_parse!(
124 wh: where_clause >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700125 punct!("{") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700126 variants: terminated_list!(punct!(","), variant) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700127 punct!("}") >>
David Tolnay28c1db62016-10-27 22:48:18 -0700128 (wh, variants)
David Tolnayf38cdf62016-09-23 19:07:09 -0700129 ));
130
131 named!(variant -> Variant, do_parse!(
David Tolnay4a51dc72016-10-01 00:40:31 -0700132 attrs: many0!(outer_attr) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700133 id: ident >>
134 data: alt!(
135 struct_like_body => { VariantData::Struct }
136 |
137 tuple_like_body => { VariantData::Tuple }
138 |
139 epsilon!() => { |_| VariantData::Unit }
140 ) >>
David Tolnay514f1292017-02-27 12:30:57 -0800141 disr: option!(preceded!(punct!("="), discriminant)) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700142 (Variant {
143 ident: id,
144 attrs: attrs,
145 data: data,
146 discriminant: disr,
147 })
148 ));
149
David Tolnay514f1292017-02-27 12:30:57 -0800150 #[cfg(not(feature = "full"))]
David Tolnayf945fb52017-02-27 12:53:54 -0800151 use constant::parsing::const_expr as discriminant;
David Tolnay514f1292017-02-27 12:30:57 -0800152
153 #[cfg(feature = "full")]
154 named!(discriminant -> ConstExpr, alt!(
155 terminated!(const_expr, after_discriminant)
156 |
157 terminated!(expr, after_discriminant) => { ConstExpr::Other }
158 ));
159
160 #[cfg(feature = "full")]
161 named!(after_discriminant -> &str, peek!(alt!(punct!(",") | punct!("}"))));
162
David Tolnay2f9fa632016-10-03 22:08:48 -0700163 named!(pub struct_like_body -> Vec<Field>, do_parse!(
David Tolnayf38cdf62016-09-23 19:07:09 -0700164 punct!("{") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700165 fields: terminated_list!(punct!(","), struct_field) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700166 punct!("}") >>
167 (fields)
168 ));
169
170 named!(tuple_like_body -> Vec<Field>, do_parse!(
171 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700172 fields: terminated_list!(punct!(","), tuple_field) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700173 punct!(")") >>
174 (fields)
175 ));
176
177 named!(struct_field -> Field, do_parse!(
David Tolnay4a51dc72016-10-01 00:40:31 -0700178 attrs: many0!(outer_attr) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700179 vis: visibility >>
180 id: ident >>
181 punct!(":") >>
182 ty: ty >>
183 (Field {
184 ident: Some(id),
185 vis: vis,
186 attrs: attrs,
187 ty: ty,
188 })
189 ));
190
191 named!(tuple_field -> Field, do_parse!(
David Tolnay4a51dc72016-10-01 00:40:31 -0700192 attrs: many0!(outer_attr) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700193 vis: visibility >>
194 ty: ty >>
195 (Field {
196 ident: None,
197 vis: vis,
198 attrs: attrs,
199 ty: ty,
200 })
201 ));
202
203 named!(pub visibility -> Visibility, alt!(
David Tolnaye07f9e02016-10-30 17:05:55 -0700204 do_parse!(
205 keyword!("pub") >>
206 punct!("(") >>
207 keyword!("crate") >>
208 punct!(")") >>
209 (Visibility::Crate)
210 )
211 |
212 do_parse!(
213 keyword!("pub") >>
214 punct!("(") >>
215 restricted: path >>
216 punct!(")") >>
217 (Visibility::Restricted(Box::new(restricted)))
218 )
219 |
David Tolnaybd76e572016-10-02 13:43:16 -0700220 keyword!("pub") => { |_| Visibility::Public }
David Tolnayf38cdf62016-09-23 19:07:09 -0700221 |
222 epsilon!() => { |_| Visibility::Inherited }
223 ));
David Tolnayf38cdf62016-09-23 19:07:09 -0700224}
225
226#[cfg(feature = "printing")]
227mod printing {
228 use super::*;
David Tolnayf38cdf62016-09-23 19:07:09 -0700229 use quote::{Tokens, ToTokens};
230
231 impl ToTokens for Variant {
232 fn to_tokens(&self, tokens: &mut Tokens) {
233 for attr in &self.attrs {
234 attr.to_tokens(tokens);
235 }
236 self.ident.to_tokens(tokens);
237 self.data.to_tokens(tokens);
238 if let Some(ref disr) = self.discriminant {
239 tokens.append("=");
240 disr.to_tokens(tokens);
241 }
242 }
243 }
244
245 impl ToTokens for VariantData {
246 fn to_tokens(&self, tokens: &mut Tokens) {
247 match *self {
248 VariantData::Struct(ref fields) => {
249 tokens.append("{");
250 tokens.append_separated(fields, ",");
251 tokens.append("}");
252 }
253 VariantData::Tuple(ref fields) => {
254 tokens.append("(");
255 tokens.append_separated(fields, ",");
256 tokens.append(")");
257 }
258 VariantData::Unit => {}
259 }
260 }
261 }
262
263 impl ToTokens for Field {
264 fn to_tokens(&self, tokens: &mut Tokens) {
265 for attr in &self.attrs {
266 attr.to_tokens(tokens);
267 }
David Tolnay47a877c2016-10-01 16:50:55 -0700268 self.vis.to_tokens(tokens);
David Tolnayf38cdf62016-09-23 19:07:09 -0700269 if let Some(ref ident) = self.ident {
270 ident.to_tokens(tokens);
271 tokens.append(":");
272 }
273 self.ty.to_tokens(tokens);
274 }
275 }
276
David Tolnay47a877c2016-10-01 16:50:55 -0700277 impl ToTokens for Visibility {
278 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye07f9e02016-10-30 17:05:55 -0700279 match *self {
280 Visibility::Public => tokens.append("pub"),
281 Visibility::Crate => {
282 tokens.append("pub");
283 tokens.append("(");
284 tokens.append("crate");
285 tokens.append(")");
286 }
287 Visibility::Restricted(ref path) => {
288 tokens.append("pub");
289 tokens.append("(");
290 path.to_tokens(tokens);
291 tokens.append(")");
292 }
293 Visibility::Inherited => {}
David Tolnay47a877c2016-10-01 16:50:55 -0700294 }
295 }
296 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700297}