blob: fdcc4e9b1ad1e06a1ae7cc39145e02fe0881776c [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!(
David Tolnaybd76e572016-10-02 13:43:16 -0700135 keyword!("pub") => { |_| Visibility::Public }
David Tolnayf38cdf62016-09-23 19:07:09 -0700136 |
137 epsilon!() => { |_| Visibility::Inherited }
138 ));
139
140 named!(discriminant -> Discriminant, map!(
141 int,
142 |(value, ty)| Discriminant {
143 value: value,
144 ty: ty,
145 }
146 ));
147}
148
149#[cfg(feature = "printing")]
150mod printing {
151 use super::*;
152 use lit::Lit;
153 use quote::{Tokens, ToTokens};
154
155 impl ToTokens for Variant {
156 fn to_tokens(&self, tokens: &mut Tokens) {
157 for attr in &self.attrs {
158 attr.to_tokens(tokens);
159 }
160 self.ident.to_tokens(tokens);
161 self.data.to_tokens(tokens);
162 if let Some(ref disr) = self.discriminant {
163 tokens.append("=");
164 disr.to_tokens(tokens);
165 }
166 }
167 }
168
169 impl ToTokens for VariantData {
170 fn to_tokens(&self, tokens: &mut Tokens) {
171 match *self {
172 VariantData::Struct(ref fields) => {
173 tokens.append("{");
174 tokens.append_separated(fields, ",");
175 tokens.append("}");
176 }
177 VariantData::Tuple(ref fields) => {
178 tokens.append("(");
179 tokens.append_separated(fields, ",");
180 tokens.append(")");
181 }
182 VariantData::Unit => {}
183 }
184 }
185 }
186
187 impl ToTokens for Field {
188 fn to_tokens(&self, tokens: &mut Tokens) {
189 for attr in &self.attrs {
190 attr.to_tokens(tokens);
191 }
David Tolnay47a877c2016-10-01 16:50:55 -0700192 self.vis.to_tokens(tokens);
David Tolnayf38cdf62016-09-23 19:07:09 -0700193 if let Some(ref ident) = self.ident {
194 ident.to_tokens(tokens);
195 tokens.append(":");
196 }
197 self.ty.to_tokens(tokens);
198 }
199 }
200
David Tolnay47a877c2016-10-01 16:50:55 -0700201 impl ToTokens for Visibility {
202 fn to_tokens(&self, tokens: &mut Tokens) {
203 if let Visibility::Public = *self {
204 tokens.append("pub");
205 }
206 }
207 }
208
David Tolnayf38cdf62016-09-23 19:07:09 -0700209 impl ToTokens for Discriminant {
210 fn to_tokens(&self, tokens: &mut Tokens) {
211 Lit::Int(self.value, self.ty).to_tokens(tokens);
212 }
213 }
214}