blob: 7082363880eed7327a2285115d9f79ecb9d0e674 [file] [log] [blame]
David Tolnayf38cdf62016-09-23 19:07:09 -07001use super::*;
2
3#[derive(Debug, Clone, Eq, PartialEq)]
4pub struct Variant {
5 pub ident: Ident,
6 pub attrs: Vec<Attribute>,
7 pub data: VariantData,
8 /// Explicit discriminant, e.g. `Foo = 1`
9 pub discriminant: Option<Discriminant>,
10}
11
12#[derive(Debug, Clone, Eq, PartialEq)]
13pub enum VariantData {
14 Struct(Vec<Field>),
15 Tuple(Vec<Field>),
16 Unit,
17}
18
19impl VariantData {
20 pub fn fields(&self) -> &[Field] {
21 match *self {
22 VariantData::Struct(ref fields) |
23 VariantData::Tuple(ref fields) => fields,
24 VariantData::Unit => &[],
25 }
26 }
27}
28
29#[derive(Debug, Clone, Eq, PartialEq)]
30pub struct Field {
31 pub ident: Option<Ident>,
32 pub vis: Visibility,
33 pub attrs: Vec<Attribute>,
34 pub ty: Ty,
35}
36
37#[derive(Debug, Copy, Clone, Eq, PartialEq)]
38pub enum Visibility {
39 Public,
40 Inherited,
41}
42
43#[derive(Debug, Copy, Clone, Eq, PartialEq)]
44pub struct Discriminant {
45 pub value: u64,
46 pub ty: IntTy,
47}
48
49#[cfg(feature = "parsing")]
50pub mod parsing {
51 use super::*;
David Tolnay4a51dc72016-10-01 00:40:31 -070052 use attr::parsing::outer_attr;
David Tolnayf38cdf62016-09-23 19:07:09 -070053 use ident::parsing::ident;
54 use lit::parsing::int;
55 use ty::parsing::ty;
David Tolnayf38cdf62016-09-23 19:07:09 -070056
57 named!(pub struct_body -> VariantData, alt!(
58 struct_like_body => { VariantData::Struct }
59 |
60 terminated!(tuple_like_body, punct!(";")) => { VariantData::Tuple }
61 |
62 punct!(";") => { |_| VariantData::Unit }
63 ));
64
65 named!(pub enum_body -> Vec<Variant>, do_parse!(
66 punct!("{") >>
67 variants: separated_list!(punct!(","), variant) >>
68 option!(punct!(",")) >>
69 punct!("}") >>
70 (variants)
71 ));
72
73 named!(variant -> Variant, do_parse!(
David Tolnay4a51dc72016-10-01 00:40:31 -070074 attrs: many0!(outer_attr) >>
David Tolnayf38cdf62016-09-23 19:07:09 -070075 id: ident >>
76 data: alt!(
77 struct_like_body => { VariantData::Struct }
78 |
79 tuple_like_body => { VariantData::Tuple }
80 |
81 epsilon!() => { |_| VariantData::Unit }
82 ) >>
83 disr: option!(preceded!(punct!("="), discriminant)) >>
84 (Variant {
85 ident: id,
86 attrs: attrs,
87 data: data,
88 discriminant: disr,
89 })
90 ));
91
92 named!(struct_like_body -> Vec<Field>, do_parse!(
93 punct!("{") >>
94 fields: separated_list!(punct!(","), struct_field) >>
95 option!(punct!(",")) >>
96 punct!("}") >>
97 (fields)
98 ));
99
100 named!(tuple_like_body -> Vec<Field>, do_parse!(
101 punct!("(") >>
102 fields: separated_list!(punct!(","), tuple_field) >>
103 option!(punct!(",")) >>
104 punct!(")") >>
105 (fields)
106 ));
107
108 named!(struct_field -> Field, do_parse!(
David Tolnay4a51dc72016-10-01 00:40:31 -0700109 attrs: many0!(outer_attr) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700110 vis: visibility >>
111 id: ident >>
112 punct!(":") >>
113 ty: ty >>
114 (Field {
115 ident: Some(id),
116 vis: vis,
117 attrs: attrs,
118 ty: ty,
119 })
120 ));
121
122 named!(tuple_field -> Field, do_parse!(
David Tolnay4a51dc72016-10-01 00:40:31 -0700123 attrs: many0!(outer_attr) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700124 vis: visibility >>
125 ty: ty >>
126 (Field {
127 ident: None,
128 vis: vis,
129 attrs: attrs,
130 ty: ty,
131 })
132 ));
133
134 named!(pub visibility -> Visibility, alt!(
135 do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700136 keyword!("pub") >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700137 (Visibility::Public)
138 )
139 |
140 epsilon!() => { |_| Visibility::Inherited }
141 ));
142
143 named!(discriminant -> Discriminant, map!(
144 int,
145 |(value, ty)| Discriminant {
146 value: value,
147 ty: ty,
148 }
149 ));
150}
151
152#[cfg(feature = "printing")]
153mod printing {
154 use super::*;
155 use lit::Lit;
156 use quote::{Tokens, ToTokens};
157
158 impl ToTokens for Variant {
159 fn to_tokens(&self, tokens: &mut Tokens) {
160 for attr in &self.attrs {
161 attr.to_tokens(tokens);
162 }
163 self.ident.to_tokens(tokens);
164 self.data.to_tokens(tokens);
165 if let Some(ref disr) = self.discriminant {
166 tokens.append("=");
167 disr.to_tokens(tokens);
168 }
169 }
170 }
171
172 impl ToTokens for VariantData {
173 fn to_tokens(&self, tokens: &mut Tokens) {
174 match *self {
175 VariantData::Struct(ref fields) => {
176 tokens.append("{");
177 tokens.append_separated(fields, ",");
178 tokens.append("}");
179 }
180 VariantData::Tuple(ref fields) => {
181 tokens.append("(");
182 tokens.append_separated(fields, ",");
183 tokens.append(")");
184 }
185 VariantData::Unit => {}
186 }
187 }
188 }
189
190 impl ToTokens for Field {
191 fn to_tokens(&self, tokens: &mut Tokens) {
192 for attr in &self.attrs {
193 attr.to_tokens(tokens);
194 }
195 if let Visibility::Public = self.vis {
196 tokens.append("pub");
197 }
198 if let Some(ref ident) = self.ident {
199 ident.to_tokens(tokens);
200 tokens.append(":");
201 }
202 self.ty.to_tokens(tokens);
203 }
204 }
205
206 impl ToTokens for Discriminant {
207 fn to_tokens(&self, tokens: &mut Tokens) {
208 Lit::Int(self.value, self.ty).to_tokens(tokens);
209 }
210 }
211}