1use super::attributes::AttributeLocation;
2use super::{utils::*, Attribute, Visibility};
3use crate::prelude::{Delimiter, Ident, Literal, Span, TokenTree};
4use crate::{Error, Result};
5use std::iter::Peekable;
6
7#[derive(Debug)]
9pub struct StructBody {
10 pub fields: Option<Fields>,
12}
13
14impl StructBody {
15 pub(crate) fn take(input: &mut Peekable<impl Iterator<Item = TokenTree>>) -> Result<Self> {
16 match input.peek() {
17 Some(TokenTree::Group(_)) => {}
18 Some(TokenTree::Punct(p)) if p.as_char() == ';' => {
19 return Ok(StructBody { fields: None })
20 }
21 token => return Error::wrong_token(token, "group or punct"),
22 }
23 let group = assume_group(input.next());
24 let mut stream = group.stream().into_iter().peekable();
25 let fields = match group.delimiter() {
26 Delimiter::Brace => {
27 let fields = UnnamedField::parse_with_name(&mut stream)?;
28 Some(Fields::Struct(fields))
29 }
30 Delimiter::Parenthesis => {
31 let fields = UnnamedField::parse(&mut stream)?;
32 Some(Fields::Tuple(fields))
33 }
34 found => {
35 return Err(Error::InvalidRustSyntax {
36 span: group.span(),
37 expected: format!("brace or parenthesis, found {:?}", found),
38 })
39 }
40 };
41 Ok(StructBody { fields })
42 }
43}
44
45#[test]
46fn test_struct_body_take() {
47 use crate::token_stream;
48
49 let stream = &mut token_stream(
50 "struct Foo { pub bar: u8, pub(crate) baz: u32, bla: Vec<Box<dyn Future<Output = ()>>> }",
51 );
52 let (data_type, ident) = super::DataType::take(stream).unwrap();
53 assert_eq!(data_type, super::DataType::Struct);
54 assert_eq!(ident, "Foo");
55 let body = StructBody::take(stream).unwrap();
56 let fields = body.fields.as_ref().unwrap();
57
58 assert_eq!(fields.len(), 3);
59 let (ident, field) = fields.get(0).unwrap();
60 assert_eq!(ident.unwrap(), "bar");
61 assert_eq!(field.vis, Visibility::Pub);
62 assert_eq!(field.type_string(), "u8");
63
64 let (ident, field) = fields.get(1).unwrap();
65 assert_eq!(ident.unwrap(), "baz");
66 assert_eq!(field.vis, Visibility::Pub);
67 assert_eq!(field.type_string(), "u32");
68
69 let (ident, field) = fields.get(2).unwrap();
70 assert_eq!(ident.unwrap(), "bla");
71 assert_eq!(field.vis, Visibility::Default);
72 assert_eq!(field.type_string(), "Vec<Box<dynFuture<Output=()>>>");
73
74 let stream = &mut token_stream(
75 "struct Foo ( pub u8, pub(crate) u32, Vec<Box<dyn Future<Output = ()>>> )",
76 );
77 let (data_type, ident) = super::DataType::take(stream).unwrap();
78 assert_eq!(data_type, super::DataType::Struct);
79 assert_eq!(ident, "Foo");
80 let body = StructBody::take(stream).unwrap();
81 let fields = body.fields.as_ref().unwrap();
82
83 assert_eq!(fields.len(), 3);
84
85 let (ident, field) = fields.get(0).unwrap();
86 assert!(ident.is_none());
87 assert_eq!(field.vis, Visibility::Pub);
88 assert_eq!(field.type_string(), "u8");
89
90 let (ident, field) = fields.get(1).unwrap();
91 assert!(ident.is_none());
92 assert_eq!(field.vis, Visibility::Pub);
93 assert_eq!(field.type_string(), "u32");
94
95 let (ident, field) = fields.get(2).unwrap();
96 assert!(ident.is_none());
97 assert_eq!(field.vis, Visibility::Default);
98 assert_eq!(field.type_string(), "Vec<Box<dynFuture<Output=()>>>");
99
100 let stream = &mut token_stream("struct Foo;");
101 let (data_type, ident) = super::DataType::take(stream).unwrap();
102 assert_eq!(data_type, super::DataType::Struct);
103 assert_eq!(ident, "Foo");
104 let body = StructBody::take(stream).unwrap();
105 assert!(body.fields.is_none());
106
107 let stream = &mut token_stream("struct Foo {}");
108 let (data_type, ident) = super::DataType::take(stream).unwrap();
109 assert_eq!(data_type, super::DataType::Struct);
110 assert_eq!(ident, "Foo");
111 let body = StructBody::take(stream).unwrap();
112 if let Some(Fields::Struct(v)) = body.fields {
113 assert!(v.is_empty());
114 } else {
115 panic!("wrong fields {:?}", body.fields);
116 }
117
118 let stream = &mut token_stream("struct Foo ()");
119 let (data_type, ident) = super::DataType::take(stream).unwrap();
120 assert_eq!(data_type, super::DataType::Struct);
121 assert_eq!(ident, "Foo");
122 let body = StructBody::take(stream).unwrap();
123 if let Some(Fields::Tuple(v)) = body.fields {
124 assert!(v.is_empty());
125 } else {
126 panic!("wrong fields {:?}", body.fields);
127 }
128}
129
130#[test]
131fn issue_77() {
132 use crate::token_stream;
134
135 let stream = &mut token_stream("struct Test(pub [u8; 32])");
136 let (data_type, ident) = super::DataType::take(stream).unwrap();
137 assert_eq!(data_type, super::DataType::Struct);
138 assert_eq!(ident, "Test");
139 let body = StructBody::take(stream).unwrap();
140 let fields = body.fields.unwrap();
141 let Fields::Tuple(t) = fields else {
142 panic!("Fields is not a tuple")
143 };
144 assert_eq!(t.len(), 1);
145 assert_eq!(t[0].r#type[0].to_string(), "[u8 ; 32]");
146
147 let stream = &mut token_stream("struct Foo(pub (u8, ))");
148 let (data_type, ident) = super::DataType::take(stream).unwrap();
149 assert_eq!(data_type, super::DataType::Struct);
150 assert_eq!(ident, "Foo");
151 let body = StructBody::take(stream).unwrap();
152 let fields = body.fields.unwrap();
153 let Fields::Tuple(t) = fields else {
154 panic!("Fields is not a tuple")
155 };
156 assert_eq!(t.len(), 1);
157 assert_eq!(t[0].r#type[0].to_string(), "(u8 ,)");
158}
159
160#[derive(Debug)]
162pub struct EnumBody {
163 pub variants: Vec<EnumVariant>,
165}
166
167impl EnumBody {
168 pub(crate) fn take(input: &mut Peekable<impl Iterator<Item = TokenTree>>) -> Result<Self> {
169 match input.peek() {
170 Some(TokenTree::Group(_)) => {}
171 Some(TokenTree::Punct(p)) if p.as_char() == ';' => {
172 return Ok(EnumBody {
173 variants: Vec::new(),
174 })
175 }
176 token => return Error::wrong_token(token, "group or ;"),
177 }
178 let group = assume_group(input.next());
179 let mut variants = Vec::new();
180 let stream = &mut group.stream().into_iter().peekable();
181 while stream.peek().is_some() {
182 let attributes = Attribute::try_take(AttributeLocation::Variant, stream)?;
183 let ident = match super::utils::consume_ident(stream) {
184 Some(ident) => ident,
185 None => Error::wrong_token(stream.peek(), "ident")?,
186 };
187
188 let mut fields = None;
189 let mut value = None;
190
191 if let Some(TokenTree::Group(_)) = stream.peek() {
192 let group = assume_group(stream.next());
193 let stream = &mut group.stream().into_iter().peekable();
194 match group.delimiter() {
195 Delimiter::Brace => {
196 fields = Some(Fields::Struct(UnnamedField::parse_with_name(stream)?));
197 }
198 Delimiter::Parenthesis => {
199 fields = Some(Fields::Tuple(UnnamedField::parse(stream)?));
200 }
201 delim => {
202 return Err(Error::InvalidRustSyntax {
203 span: group.span(),
204 expected: format!("Brace or parenthesis, found {:?}", delim),
205 })
206 }
207 }
208 }
209 match stream.peek() {
210 Some(TokenTree::Punct(p)) if p.as_char() == '=' => {
211 assume_punct(stream.next(), '=');
212 match stream.next() {
213 Some(TokenTree::Literal(lit)) => {
214 value = Some(lit);
215 }
216 Some(TokenTree::Punct(p)) if p.as_char() == '-' => match stream.next() {
217 Some(TokenTree::Literal(lit)) => {
218 match lit.to_string().parse::<i64>() {
219 Ok(val) => value = Some(Literal::i64_unsuffixed(-val)),
220 Err(_) => {
221 return Err(Error::custom_at(
222 "parse::<i64> failed",
223 lit.span(),
224 ))
225 }
226 };
227 }
228 token => return Error::wrong_token(token.as_ref(), "literal"),
229 },
230 token => return Error::wrong_token(token.as_ref(), "literal"),
231 }
232 }
233 Some(TokenTree::Punct(p)) if p.as_char() == ',' => {
234 }
236 None => {
237 }
239 token => return Error::wrong_token(token, "group, comma or ="),
240 }
241
242 consume_punct_if(stream, ',');
243
244 variants.push(EnumVariant {
245 name: ident,
246 fields,
247 value,
248 attributes,
249 });
250 }
251
252 Ok(EnumBody { variants })
253 }
254}
255
256#[test]
257fn test_enum_body_take() {
258 use crate::token_stream;
259
260 let stream = &mut token_stream("enum Foo { }");
261 let (data_type, ident) = super::DataType::take(stream).unwrap();
262 assert_eq!(data_type, super::DataType::Enum);
263 assert_eq!(ident, "Foo");
264 let body = EnumBody::take(stream).unwrap();
265 assert!(body.variants.is_empty());
266
267 let stream = &mut token_stream("enum Foo { Bar, Baz(u8), Blah { a: u32, b: u128 } }");
268 let (data_type, ident) = super::DataType::take(stream).unwrap();
269 assert_eq!(data_type, super::DataType::Enum);
270 assert_eq!(ident, "Foo");
271 let body = EnumBody::take(stream).unwrap();
272 assert_eq!(3, body.variants.len());
273
274 assert_eq!(body.variants[0].name, "Bar");
275 assert!(body.variants[0].fields.is_none());
276
277 assert_eq!(body.variants[1].name, "Baz");
278 assert!(body.variants[1].fields.is_some());
279 let fields = body.variants[1].fields.as_ref().unwrap();
280 assert_eq!(1, fields.len());
281 let (ident, field) = fields.get(0).unwrap();
282 assert!(ident.is_none());
283 assert_eq!(field.type_string(), "u8");
284
285 assert_eq!(body.variants[2].name, "Blah");
286 assert!(body.variants[2].fields.is_some());
287 let fields = body.variants[2].fields.as_ref().unwrap();
288 assert_eq!(2, fields.len());
289 let (ident, field) = fields.get(0).unwrap();
290 assert_eq!(ident.unwrap(), "a");
291 assert_eq!(field.type_string(), "u32");
292 let (ident, field) = fields.get(1).unwrap();
293 assert_eq!(ident.unwrap(), "b");
294 assert_eq!(field.type_string(), "u128");
295
296 let stream = &mut token_stream("enum Foo { Bar = -1, Baz = 2 }");
297 let (data_type, ident) = super::DataType::take(stream).unwrap();
298 assert_eq!(data_type, super::DataType::Enum);
299 assert_eq!(ident, "Foo");
300 let body = EnumBody::take(stream).unwrap();
301 assert_eq!(2, body.variants.len());
302
303 assert_eq!(body.variants[0].name, "Bar");
304 assert!(body.variants[0].fields.is_none());
305 assert_eq!(body.variants[0].get_integer(), -1);
306
307 assert_eq!(body.variants[1].name, "Baz");
308 assert!(body.variants[1].fields.is_none());
309 assert_eq!(body.variants[1].get_integer(), 2);
310
311 let stream = &mut token_stream("enum Foo { Bar(i32) = -1, Baz { a: i32 } = 2 }");
312 let (data_type, ident) = super::DataType::take(stream).unwrap();
313 assert_eq!(data_type, super::DataType::Enum);
314 assert_eq!(ident, "Foo");
315 let body = EnumBody::take(stream).unwrap();
316 assert_eq!(2, body.variants.len());
317
318 assert_eq!(body.variants[0].name, "Bar");
319 assert!(body.variants[0].fields.is_some());
320 let fields = body.variants[0].fields.as_ref().unwrap();
321 assert_eq!(fields.len(), 1);
322 assert!(matches!(fields.names()[0], IdentOrIndex::Index { index, .. } if index == 0));
323 assert_eq!(body.variants[0].get_integer(), -1);
324
325 assert_eq!(body.variants[1].name, "Baz");
326 assert!(body.variants[1].fields.is_some());
327 let fields = body.variants[1].fields.as_ref().unwrap();
328 assert_eq!(fields.len(), 1);
329 assert_eq!(fields.names().len(), 1);
330 assert!(matches!(&fields.names()[0], IdentOrIndex::Ident { ident, .. } if *ident == "a"));
331 assert_eq!(body.variants[1].get_integer(), 2);
332
333 let stream = &mut token_stream("enum Foo { Round(), Curly{}, Without }");
334 let (data_type, ident) = super::DataType::take(stream).unwrap();
335 assert_eq!(data_type, super::DataType::Enum);
336 assert_eq!(ident, "Foo");
337 let body = EnumBody::take(stream).unwrap();
338 assert_eq!(3, body.variants.len());
339
340 assert_eq!(body.variants[0].name, "Round");
341 assert!(body.variants[0].fields.is_some());
342 let fields = body.variants[0].fields.as_ref().unwrap();
343 assert!(fields.names().is_empty());
344 assert_eq!(fields.len(), 0);
345
346 assert_eq!(body.variants[1].name, "Curly");
347 assert!(body.variants[1].fields.is_some());
348 let fields = body.variants[1].fields.as_ref().unwrap();
349 assert!(fields.names().is_empty());
350 assert_eq!(fields.len(), 0);
351
352 assert_eq!(body.variants[2].name, "Without");
353 assert!(body.variants[2].fields.is_none());
354}
355
356#[derive(Debug)]
358pub struct EnumVariant {
359 pub name: Ident,
361 pub fields: Option<Fields>,
363 pub value: Option<Literal>,
370 pub attributes: Vec<Attribute>,
372}
373
374#[cfg(test)]
375impl EnumVariant {
376 fn get_integer(&self) -> i64 {
377 let value = self.value.as_ref().expect("Variant has no value");
378 value
379 .to_string()
380 .parse()
381 .expect("Value is not a valid integer")
382 }
383}
384
385#[derive(Debug)]
387pub enum Fields {
388 Tuple(Vec<UnnamedField>),
396
397 Struct(Vec<(Ident, UnnamedField)>),
409}
410
411impl Fields {
412 pub fn names(&self) -> Vec<IdentOrIndex> {
420 let result: Vec<IdentOrIndex> = match self {
421 Self::Tuple(fields) => fields
422 .iter()
423 .enumerate()
424 .map(|(index, field)| IdentOrIndex::Index {
425 index,
426 span: field.span(),
427 attributes: field.attributes.clone(),
428 })
429 .collect(),
430 Self::Struct(fields) => fields
431 .iter()
432 .map(|(ident, field)| IdentOrIndex::Ident {
433 ident: ident.clone(),
434 attributes: field.attributes.clone(),
435 })
436 .collect(),
437 };
438 result
439 }
440
441 pub fn delimiter(&self) -> Delimiter {
450 match self {
451 Self::Tuple(_) => Delimiter::Parenthesis,
452 Self::Struct(_) => Delimiter::Brace,
453 }
454 }
455}
456
457#[cfg(test)]
458impl Fields {
459 fn len(&self) -> usize {
460 match self {
461 Self::Tuple(fields) => fields.len(),
462 Self::Struct(fields) => fields.len(),
463 }
464 }
465
466 fn get(&self, index: usize) -> Option<(Option<&Ident>, &UnnamedField)> {
467 match self {
468 Self::Tuple(fields) => fields.get(index).map(|f| (None, f)),
469 Self::Struct(fields) => fields.get(index).map(|(ident, field)| (Some(ident), field)),
470 }
471 }
472}
473
474#[derive(Debug)]
476pub struct UnnamedField {
477 pub vis: Visibility,
479 pub r#type: Vec<TokenTree>,
481 pub attributes: Vec<Attribute>,
483}
484
485impl UnnamedField {
486 pub(crate) fn parse_with_name(
487 input: &mut Peekable<impl Iterator<Item = TokenTree>>,
488 ) -> Result<Vec<(Ident, Self)>> {
489 let mut result = Vec::new();
490 loop {
491 let attributes = Attribute::try_take(AttributeLocation::Field, input)?;
492 let vis = Visibility::try_take(input)?;
493
494 let ident = match input.peek() {
495 Some(TokenTree::Ident(_)) => assume_ident(input.next()),
496 Some(x) => {
497 return Err(Error::InvalidRustSyntax {
498 span: x.span(),
499 expected: format!("ident or end of group, got {:?}", x),
500 })
501 }
502 None => break,
503 };
504 match input.peek() {
505 Some(TokenTree::Punct(p)) if p.as_char() == ':' => {
506 input.next();
507 }
508 token => return Error::wrong_token(token, ":"),
509 }
510 let r#type = read_tokens_until_punct(input, &[','])?;
511 consume_punct_if(input, ',');
512 result.push((
513 ident,
514 Self {
515 vis,
516 r#type,
517 attributes,
518 },
519 ));
520 }
521 Ok(result)
522 }
523
524 pub(crate) fn parse(
525 input: &mut Peekable<impl Iterator<Item = TokenTree>>,
526 ) -> Result<Vec<Self>> {
527 let mut result = Vec::new();
528 while input.peek().is_some() {
529 let attributes = Attribute::try_take(AttributeLocation::Field, input)?;
530 let vis = Visibility::try_take(input)?;
531
532 let r#type = read_tokens_until_punct(input, &[','])?;
533 consume_punct_if(input, ',');
534 result.push(Self {
535 vis,
536 r#type,
537 attributes,
538 });
539 }
540 Ok(result)
541 }
542
543 pub fn type_string(&self) -> String {
547 self.r#type.iter().map(|t| t.to_string()).collect()
548 }
549
550 pub fn span(&self) -> Span {
556 match self.r#type.first() {
569 Some(first) => first.span(),
570 None => Span::call_site(),
571 }
572 }
573}
574
575#[derive(Debug, Clone)]
585pub enum IdentOrIndex {
586 Ident {
588 ident: Ident,
590 attributes: Vec<Attribute>,
592 },
593 Index {
595 index: usize,
597 span: Span,
599 attributes: Vec<Attribute>,
601 },
602}
603
604impl IdentOrIndex {
605 pub fn unwrap_ident(&self) -> Ident {
607 match self {
608 Self::Ident { ident, .. } => ident.clone(),
609 x => panic!("Expected ident, found {:?}", x),
610 }
611 }
612
613 pub fn to_token_tree_with_prefix(&self, prefix: &str) -> TokenTree {
615 TokenTree::Ident(match self {
616 IdentOrIndex::Ident { ident, .. } => (*ident).clone(),
617 IdentOrIndex::Index { index, span, .. } => {
618 let name = format!("{}{}", prefix, index);
619 Ident::new(&name, *span)
620 }
621 })
622 }
623
624 pub fn to_string_with_prefix(&self, prefix: &str) -> String {
626 match self {
627 IdentOrIndex::Ident { ident, .. } => ident.to_string(),
628 IdentOrIndex::Index { index, .. } => {
629 format!("{}{}", prefix, index)
630 }
631 }
632 }
633
634 pub fn attributes(&self) -> &Vec<Attribute> {
636 match self {
637 Self::Ident { attributes, .. } => attributes,
638 Self::Index { attributes, .. } => attributes,
639 }
640 }
641}
642
643impl std::fmt::Display for IdentOrIndex {
644 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
645 match self {
646 IdentOrIndex::Ident { ident, .. } => write!(fmt, "{}", ident),
647 IdentOrIndex::Index { index, .. } => write!(fmt, "{}", index),
648 }
649 }
650}
651
652#[test]
653fn enum_explicit_variants() {
654 use crate::token_stream;
655 let stream = &mut token_stream("{ A = 1, B = 2 }");
656 let body = EnumBody::take(stream).unwrap();
657 assert_eq!(body.variants.len(), 2);
658}