blob: df5abe44cbd90fefa4824aead669b7e4df9e68b4 [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
2
David Tolnayb79ee962016-09-04 09:39:20 -07003#[derive(Debug, Clone, Eq, PartialEq)]
4pub struct Item {
5 pub ident: Ident,
6 pub vis: Visibility,
7 pub attrs: Vec<Attribute>,
8 pub generics: Generics,
9 pub body: Body,
10}
11
12#[derive(Debug, Clone, Eq, PartialEq)]
13pub enum Body {
14 Enum(Vec<Variant>),
David Tolnay55337722016-09-11 12:58:56 -070015 Struct(VariantData),
David Tolnayb79ee962016-09-04 09:39:20 -070016}
17
18#[derive(Debug, Clone, Eq, PartialEq)]
19pub struct Variant {
20 pub ident: Ident,
21 pub attrs: Vec<Attribute>,
David Tolnay55337722016-09-11 12:58:56 -070022 pub data: VariantData,
David Tolnayb79ee962016-09-04 09:39:20 -070023}
24
David Tolnay55337722016-09-11 12:58:56 -070025#[derive(Debug, Clone, Eq, PartialEq)]
26pub enum VariantData {
27 Struct(Vec<Field>),
28 Tuple(Vec<Field>),
David Tolnayb79ee962016-09-04 09:39:20 -070029 Unit,
30}
31
David Tolnay55337722016-09-11 12:58:56 -070032impl VariantData {
33 pub fn fields(&self) -> &[Field] {
34 match *self {
35 VariantData::Struct(ref fields) |
36 VariantData::Tuple(ref fields) => fields,
37 VariantData::Unit => &[],
38 }
39 }
40}
41
David Tolnayb79ee962016-09-04 09:39:20 -070042#[derive(Debug, Clone, Eq, PartialEq)]
43pub struct Field {
44 pub ident: Option<Ident>,
45 pub vis: Visibility,
46 pub attrs: Vec<Attribute>,
47 pub ty: Ty,
48}
49
David Tolnay55337722016-09-11 12:58:56 -070050#[derive(Debug, Copy, Clone, Eq, PartialEq)]
51pub enum Visibility {
52 Public,
53 Inherited,
54}
55
David Tolnay86eca752016-09-04 11:26:41 -070056#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -070057pub mod parsing {
58 use super::*;
59 use attr::parsing::attribute;
David Tolnay9d8f1972016-09-04 11:58:48 -070060 use generics::parsing::generics;
David Tolnay55337722016-09-11 12:58:56 -070061 use ident::parsing::ident;
David Tolnay9d8f1972016-09-04 11:58:48 -070062 use ty::parsing::ty;
63 use nom::multispace;
David Tolnayb79ee962016-09-04 09:39:20 -070064
David Tolnay9d8f1972016-09-04 11:58:48 -070065 named!(pub item<&str, Item>, do_parse!(
66 attrs: many0!(attribute) >>
67 vis: visibility >>
David Tolnayf6ccb832016-09-04 15:00:56 -070068 which: alt_complete!(punct!("struct") | punct!("enum")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -070069 multispace >>
David Tolnay55337722016-09-11 12:58:56 -070070 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -070071 generics: generics >>
72 item: switch!(value!(which),
David Tolnayc94c38a2016-09-05 17:02:03 -070073 "struct" => map!(struct_body, move |body| Item {
David Tolnay55337722016-09-11 12:58:56 -070074 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -070075 vis: vis,
76 attrs: attrs,
77 generics: generics,
David Tolnay55337722016-09-11 12:58:56 -070078 body: Body::Struct(body),
David Tolnay9d8f1972016-09-04 11:58:48 -070079 })
80 |
81 "enum" => map!(enum_body, move |body| Item {
David Tolnay55337722016-09-11 12:58:56 -070082 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -070083 vis: vis,
84 attrs: attrs,
85 generics: generics,
David Tolnay55337722016-09-11 12:58:56 -070086 body: Body::Enum(body),
David Tolnay9d8f1972016-09-04 11:58:48 -070087 })
88 ) >>
David Tolnayf6ccb832016-09-04 15:00:56 -070089 option!(multispace) >>
David Tolnay9d8f1972016-09-04 11:58:48 -070090 (item)
91 ));
David Tolnayb79ee962016-09-04 09:39:20 -070092
David Tolnay55337722016-09-11 12:58:56 -070093 named!(struct_body<&str, VariantData>, alt_complete!(
94 struct_like_body => { VariantData::Struct }
David Tolnayb79ee962016-09-04 09:39:20 -070095 |
David Tolnay55337722016-09-11 12:58:56 -070096 terminated!(tuple_like_body, punct!(";")) => { VariantData::Tuple }
David Tolnayb79ee962016-09-04 09:39:20 -070097 |
David Tolnay55337722016-09-11 12:58:56 -070098 punct!(";") => { |_| VariantData::Unit }
David Tolnay9d8f1972016-09-04 11:58:48 -070099 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700100
David Tolnay55337722016-09-11 12:58:56 -0700101 named!(enum_body<&str, Vec<Variant> >, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700102 punct!("{") >>
103 variants: separated_list!(punct!(","), variant) >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700104 option!(punct!(",")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700105 punct!("}") >>
David Tolnay55337722016-09-11 12:58:56 -0700106 (variants)
David Tolnay9d8f1972016-09-04 11:58:48 -0700107 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700108
David Tolnay9d8f1972016-09-04 11:58:48 -0700109 named!(variant<&str, Variant>, do_parse!(
110 attrs: many0!(attribute) >>
David Tolnay55337722016-09-11 12:58:56 -0700111 id: ident >>
112 data: alt_complete!(
113 struct_like_body => { VariantData::Struct }
David Tolnay9d8f1972016-09-04 11:58:48 -0700114 |
David Tolnay55337722016-09-11 12:58:56 -0700115 tuple_like_body => { VariantData::Tuple }
David Tolnay9d8f1972016-09-04 11:58:48 -0700116 |
David Tolnay55337722016-09-11 12:58:56 -0700117 epsilon!() => { |_| VariantData::Unit }
David Tolnay9d8f1972016-09-04 11:58:48 -0700118 ) >>
119 (Variant {
David Tolnay55337722016-09-11 12:58:56 -0700120 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700121 attrs: attrs,
David Tolnay55337722016-09-11 12:58:56 -0700122 data: data,
David Tolnay9d8f1972016-09-04 11:58:48 -0700123 })
124 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700125
David Tolnay9d8f1972016-09-04 11:58:48 -0700126 named!(struct_like_body<&str, Vec<Field> >, do_parse!(
127 punct!("{") >>
128 fields: separated_list!(punct!(","), struct_field) >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700129 option!(punct!(",")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700130 punct!("}") >>
131 (fields)
132 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700133
David Tolnay9d8f1972016-09-04 11:58:48 -0700134 named!(tuple_like_body<&str, Vec<Field> >, do_parse!(
135 punct!("(") >>
136 fields: separated_list!(punct!(","), tuple_field) >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700137 option!(punct!(",")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700138 punct!(")") >>
139 (fields)
140 ));
141
142 named!(struct_field<&str, Field>, do_parse!(
143 attrs: many0!(attribute) >>
144 vis: visibility >>
David Tolnay55337722016-09-11 12:58:56 -0700145 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700146 punct!(":") >>
147 ty: ty >>
148 (Field {
David Tolnay55337722016-09-11 12:58:56 -0700149 ident: Some(id),
David Tolnay9d8f1972016-09-04 11:58:48 -0700150 vis: vis,
151 attrs: attrs,
152 ty: ty,
153 })
154 ));
155
156 named!(tuple_field<&str, Field>, do_parse!(
157 attrs: many0!(attribute) >>
158 vis: visibility >>
159 ty: ty >>
160 (Field {
161 ident: None,
162 vis: vis,
163 attrs: attrs,
164 ty: ty,
165 })
166 ));
David Tolnay55337722016-09-11 12:58:56 -0700167
168 named!(pub visibility<&str, Visibility>, alt_complete!(
169 do_parse!(
170 punct!("pub") >>
171 multispace >>
172 (Visibility::Public)
173 )
174 |
175 epsilon!() => { |_| Visibility::Inherited }
176 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700177}
David Tolnayd5025812016-09-04 14:21:46 -0700178
179#[cfg(feature = "printing")]
180mod printing {
181 use super::*;
David Tolnayd5025812016-09-04 14:21:46 -0700182 use quote::{Tokens, ToTokens};
183
184 impl ToTokens for Item {
185 fn to_tokens(&self, tokens: &mut Tokens) {
186 for attr in &self.attrs {
187 attr.to_tokens(tokens);
188 }
189 if let Visibility::Public = self.vis {
190 tokens.append("pub");
191 }
192 match self.body {
193 Body::Enum(_) => tokens.append("enum"),
David Tolnay55337722016-09-11 12:58:56 -0700194 Body::Struct(_) => tokens.append("struct"),
David Tolnayd5025812016-09-04 14:21:46 -0700195 }
196 self.ident.to_tokens(tokens);
197 self.generics.to_tokens(tokens);
David Tolnay55337722016-09-11 12:58:56 -0700198 self.generics.where_clause.to_tokens(tokens);
David Tolnayd5025812016-09-04 14:21:46 -0700199 self.body.to_tokens(tokens);
200 }
201 }
202
203 impl ToTokens for Body {
204 fn to_tokens(&self, tokens: &mut Tokens) {
205 match *self {
206 Body::Enum(ref variants) => {
207 tokens.append("{");
208 for variant in variants {
209 variant.to_tokens(tokens);
David Tolnay812c2002016-09-04 14:32:19 -0700210 tokens.append(",");
David Tolnayd5025812016-09-04 14:21:46 -0700211 }
212 tokens.append("}");
213 }
David Tolnay55337722016-09-11 12:58:56 -0700214 Body::Struct(ref variant_data) => {
215 variant_data_to_tokens(variant_data, tokens);
216 match *variant_data {
217 VariantData::Struct(_) => { /* no semicolon */ }
218 VariantData::Tuple(_) |
219 VariantData::Unit => tokens.append(";"),
David Tolnayd5025812016-09-04 14:21:46 -0700220 }
221 }
222 }
223 }
224 }
225
226 impl ToTokens for Variant {
227 fn to_tokens(&self, tokens: &mut Tokens) {
228 for attr in &self.attrs {
229 attr.to_tokens(tokens);
230 }
231 self.ident.to_tokens(tokens);
David Tolnay55337722016-09-11 12:58:56 -0700232 variant_data_to_tokens(&self.data, tokens);
David Tolnayd5025812016-09-04 14:21:46 -0700233 }
234 }
235
236 impl ToTokens for Field {
237 fn to_tokens(&self, tokens: &mut Tokens) {
238 for attr in &self.attrs {
239 attr.to_tokens(tokens);
240 }
241 if let Visibility::Public = self.vis {
242 tokens.append("pub");
243 }
244 if let Some(ref ident) = self.ident {
245 ident.to_tokens(tokens);
246 tokens.append(":");
247 }
248 self.ty.to_tokens(tokens);
249 }
250 }
251
David Tolnay55337722016-09-11 12:58:56 -0700252 fn variant_data_to_tokens(data: &VariantData, tokens: &mut Tokens) {
253 match *data {
254 VariantData::Struct(ref fields) => {
David Tolnayd5025812016-09-04 14:21:46 -0700255 tokens.append("{");
256 tokens.append_separated(fields, ",");
257 tokens.append("}");
258 }
David Tolnay55337722016-09-11 12:58:56 -0700259 VariantData::Tuple(ref fields) => {
David Tolnayd5025812016-09-04 14:21:46 -0700260 tokens.append("(");
261 tokens.append_separated(fields, ",");
262 tokens.append(")");
263 }
David Tolnay55337722016-09-11 12:58:56 -0700264 VariantData::Unit => {}
David Tolnayd5025812016-09-04 14:21:46 -0700265 }
266 }
267}