blob: 64c893dbb076a49b623d36433c5d04f06430255d [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::*;
52 use attr::parsing::attribute;
53 use ident::parsing::ident;
54 use lit::parsing::int;
55 use ty::parsing::ty;
56 use nom::multispace;
57
58 named!(pub struct_body -> VariantData, alt!(
59 struct_like_body => { VariantData::Struct }
60 |
61 terminated!(tuple_like_body, punct!(";")) => { VariantData::Tuple }
62 |
63 punct!(";") => { |_| VariantData::Unit }
64 ));
65
66 named!(pub enum_body -> Vec<Variant>, do_parse!(
67 punct!("{") >>
68 variants: separated_list!(punct!(","), variant) >>
69 option!(punct!(",")) >>
70 punct!("}") >>
71 (variants)
72 ));
73
74 named!(variant -> Variant, do_parse!(
75 attrs: many0!(attribute) >>
76 id: ident >>
77 data: alt!(
78 struct_like_body => { VariantData::Struct }
79 |
80 tuple_like_body => { VariantData::Tuple }
81 |
82 epsilon!() => { |_| VariantData::Unit }
83 ) >>
84 disr: option!(preceded!(punct!("="), discriminant)) >>
85 (Variant {
86 ident: id,
87 attrs: attrs,
88 data: data,
89 discriminant: disr,
90 })
91 ));
92
93 named!(struct_like_body -> Vec<Field>, do_parse!(
94 punct!("{") >>
95 fields: separated_list!(punct!(","), struct_field) >>
96 option!(punct!(",")) >>
97 punct!("}") >>
98 (fields)
99 ));
100
101 named!(tuple_like_body -> Vec<Field>, do_parse!(
102 punct!("(") >>
103 fields: separated_list!(punct!(","), tuple_field) >>
104 option!(punct!(",")) >>
105 punct!(")") >>
106 (fields)
107 ));
108
109 named!(struct_field -> Field, do_parse!(
110 attrs: many0!(attribute) >>
111 vis: visibility >>
112 id: ident >>
113 punct!(":") >>
114 ty: ty >>
115 (Field {
116 ident: Some(id),
117 vis: vis,
118 attrs: attrs,
119 ty: ty,
120 })
121 ));
122
123 named!(tuple_field -> Field, do_parse!(
124 attrs: many0!(attribute) >>
125 vis: visibility >>
126 ty: ty >>
127 (Field {
128 ident: None,
129 vis: vis,
130 attrs: attrs,
131 ty: ty,
132 })
133 ));
134
135 named!(pub visibility -> Visibility, alt!(
136 do_parse!(
137 punct!("pub") >>
138 multispace >>
139 (Visibility::Public)
140 )
141 |
142 epsilon!() => { |_| Visibility::Inherited }
143 ));
144
145 named!(discriminant -> Discriminant, map!(
146 int,
147 |(value, ty)| Discriminant {
148 value: value,
149 ty: ty,
150 }
151 ));
152}
153
154#[cfg(feature = "printing")]
155mod printing {
156 use super::*;
157 use lit::Lit;
158 use quote::{Tokens, ToTokens};
159
160 impl ToTokens for Variant {
161 fn to_tokens(&self, tokens: &mut Tokens) {
162 for attr in &self.attrs {
163 attr.to_tokens(tokens);
164 }
165 self.ident.to_tokens(tokens);
166 self.data.to_tokens(tokens);
167 if let Some(ref disr) = self.discriminant {
168 tokens.append("=");
169 disr.to_tokens(tokens);
170 }
171 }
172 }
173
174 impl ToTokens for VariantData {
175 fn to_tokens(&self, tokens: &mut Tokens) {
176 match *self {
177 VariantData::Struct(ref fields) => {
178 tokens.append("{");
179 tokens.append_separated(fields, ",");
180 tokens.append("}");
181 }
182 VariantData::Tuple(ref fields) => {
183 tokens.append("(");
184 tokens.append_separated(fields, ",");
185 tokens.append(")");
186 }
187 VariantData::Unit => {}
188 }
189 }
190 }
191
192 impl ToTokens for Field {
193 fn to_tokens(&self, tokens: &mut Tokens) {
194 for attr in &self.attrs {
195 attr.to_tokens(tokens);
196 }
197 if let Visibility::Public = self.vis {
198 tokens.append("pub");
199 }
200 if let Some(ref ident) = self.ident {
201 ident.to_tokens(tokens);
202 tokens.append(":");
203 }
204 self.ty.to_tokens(tokens);
205 }
206 }
207
208 impl ToTokens for Discriminant {
209 fn to_tokens(&self, tokens: &mut Tokens) {
210 Lit::Int(self.value, self.ty).to_tokens(tokens);
211 }
212 }
213}