1use super::attributes::AttributeLocation;
2use super::{Attribute, Visibility, utils::*};
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 mut variant_stream = group.stream().into_iter().peekable();
181 let stream = &mut variant_stream;
182 while stream.peek().is_some() {
183 let attributes = Attribute::try_take(AttributeLocation::Variant, stream)?;
184 let ident = match super::utils::consume_ident(stream) {
185 Some(ident) => ident,
186 None => Error::wrong_token(stream.peek(), "ident")?,
187 };
188
189 let mut fields = None;
190 let mut value = None;
191
192 if let Some(TokenTree::Group(_)) = stream.peek() {
193 let group = assume_group(stream.next());
194 let mut inner_stream = group.stream().into_iter().peekable();
195 let stream_ref = &mut inner_stream;
196 match group.delimiter() {
197 Delimiter::Brace => {
198 fields = Some(Fields::Struct(UnnamedField::parse_with_name(stream_ref)?));
199 }
200 Delimiter::Parenthesis => {
201 fields = Some(Fields::Tuple(UnnamedField::parse(stream_ref)?));
202 }
203 delim => {
204 return Err(Error::InvalidRustSyntax {
205 span: group.span(),
206 expected: format!("Brace or parenthesis, found {:?}", delim),
207 });
208 }
209 }
210 }
211 match stream.peek() {
212 Some(TokenTree::Punct(p)) if p.as_char() == '=' => {
213 assume_punct(stream.next(), '=');
214
215 let first_val_token = stream.next(); match first_val_token {
217 Some(TokenTree::Literal(lit)) => {
218 value = Some(lit);
219 }
220 Some(TokenTree::Punct(p)) if p.as_char() == '-' => {
221 let second_val_token = stream.next(); match second_val_token {
223 Some(TokenTree::Literal(lit)) => {
224 match lit.to_string().parse::<i64>() {
225 Ok(val) => value = Some(Literal::i64_unsuffixed(-val)),
226 Err(_) => {
227 return Err(Error::custom_at(
228 "parse::<i64> failed",
229 lit.span(),
230 ));
231 }
232 };
233 }
234 token => return Error::wrong_token(token.as_ref(), "literal"),
235 }
236 }
237 token => return Error::wrong_token(token.as_ref(), "literal"),
238 }
239 }
240 Some(TokenTree::Punct(p)) if p.as_char() == ',' => {
241 }
243 None => {
244 }
246 token => return Error::wrong_token(token, "group, comma or ="),
247 }
248
249 consume_punct_if(stream, ',');
250
251 variants.push(EnumVariant {
252 name: ident,
253 fields,
254 value,
255 attributes,
256 });
257 }
258
259 Ok(EnumBody { variants })
260 }
261}
262
263#[test]
264fn test_enum_body_take() {
265 use crate::token_stream;
266
267 let stream = &mut token_stream("enum Foo { }");
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!(body.variants.is_empty());
273
274 let stream = &mut token_stream("enum Foo { Bar, Baz(u8), Blah { a: u32, b: u128 } }");
275 let (data_type, ident) = super::DataType::take(stream).unwrap();
276 assert_eq!(data_type, super::DataType::Enum);
277 assert_eq!(ident, "Foo");
278 let body = EnumBody::take(stream).unwrap();
279 assert_eq!(3, body.variants.len());
280
281 assert_eq!(body.variants[0].name, "Bar");
282 assert!(body.variants[0].fields.is_none());
283
284 assert_eq!(body.variants[1].name, "Baz");
285 assert!(body.variants[1].fields.is_some());
286 let fields = body.variants[1].fields.as_ref().unwrap();
287 assert_eq!(1, fields.len());
288 let (ident, field) = fields.get(0).unwrap();
289 assert!(ident.is_none());
290 assert_eq!(field.type_string(), "u8");
291
292 assert_eq!(body.variants[2].name, "Blah");
293 assert!(body.variants[2].fields.is_some());
294 let fields = body.variants[2].fields.as_ref().unwrap();
295 assert_eq!(2, fields.len());
296 let (ident, field) = fields.get(0).unwrap();
297 assert_eq!(ident.unwrap(), "a");
298 assert_eq!(field.type_string(), "u32");
299 let (ident, field) = fields.get(1).unwrap();
300 assert_eq!(ident.unwrap(), "b");
301 assert_eq!(field.type_string(), "u128");
302
303 let stream = &mut token_stream("enum Foo { Bar = -1, Baz = 2 }");
304 let (data_type, ident) = super::DataType::take(stream).unwrap();
305 assert_eq!(data_type, super::DataType::Enum);
306 assert_eq!(ident, "Foo");
307 let body = EnumBody::take(stream).unwrap();
308 assert_eq!(2, body.variants.len());
309
310 assert_eq!(body.variants[0].name, "Bar");
311 assert!(body.variants[0].fields.is_none());
312 assert_eq!(body.variants[0].get_integer(), -1);
313
314 assert_eq!(body.variants[1].name, "Baz");
315 assert!(body.variants[1].fields.is_none());
316 assert_eq!(body.variants[1].get_integer(), 2);
317
318 let stream = &mut token_stream("enum Foo { Bar(i32) = -1, Baz { a: i32 } = 2 }");
319 let (data_type, ident) = super::DataType::take(stream).unwrap();
320 assert_eq!(data_type, super::DataType::Enum);
321 assert_eq!(ident, "Foo");
322 let body = EnumBody::take(stream).unwrap();
323 assert_eq!(2, body.variants.len());
324
325 assert_eq!(body.variants[0].name, "Bar");
326 assert!(body.variants[0].fields.is_some());
327 let fields = body.variants[0].fields.as_ref().unwrap();
328 assert_eq!(fields.len(), 1);
329 assert!(matches!(fields.names()[0], IdentOrIndex::Index { index, .. } if index == 0));
330 assert_eq!(body.variants[0].get_integer(), -1);
331
332 assert_eq!(body.variants[1].name, "Baz");
333 assert!(body.variants[1].fields.is_some());
334 let fields = body.variants[1].fields.as_ref().unwrap();
335 assert_eq!(fields.len(), 1);
336 assert_eq!(fields.names().len(), 1);
337 assert!(matches!(&fields.names()[0], IdentOrIndex::Ident { ident, .. } if *ident == "a"));
338 assert_eq!(body.variants[1].get_integer(), 2);
339
340 let stream = &mut token_stream("enum Foo { Round(), Curly{}, Without }");
341 let (data_type, ident) = super::DataType::take(stream).unwrap();
342 assert_eq!(data_type, super::DataType::Enum);
343 assert_eq!(ident, "Foo");
344 let body = EnumBody::take(stream).unwrap();
345 assert_eq!(3, body.variants.len());
346
347 assert_eq!(body.variants[0].name, "Round");
348 assert!(body.variants[0].fields.is_some());
349 let fields = body.variants[0].fields.as_ref().unwrap();
350 assert!(fields.names().is_empty());
351 assert_eq!(fields.len(), 0);
352
353 assert_eq!(body.variants[1].name, "Curly");
354 assert!(body.variants[1].fields.is_some());
355 let fields = body.variants[1].fields.as_ref().unwrap();
356 assert!(fields.names().is_empty());
357 assert_eq!(fields.len(), 0);
358
359 assert_eq!(body.variants[2].name, "Without");
360 assert!(body.variants[2].fields.is_none());
361}
362
363#[derive(Debug)]
365pub struct EnumVariant {
366 pub name: Ident,
368 pub fields: Option<Fields>,
370 pub value: Option<Literal>,
377 pub attributes: Vec<Attribute>,
379}
380
381#[cfg(test)]
382impl EnumVariant {
383 fn get_integer(&self) -> i64 {
384 let value = self.value.as_ref().expect("Variant has no value");
385 value
386 .to_string()
387 .parse()
388 .expect("Value is not a valid integer")
389 }
390}
391
392#[derive(Debug)]
394pub enum Fields {
395 Tuple(Vec<UnnamedField>),
403
404 Struct(Vec<(Ident, UnnamedField)>),
416}
417
418impl Fields {
419 pub fn names(&self) -> Vec<IdentOrIndex> {
427 let result: Vec<IdentOrIndex> = match self {
428 Self::Tuple(fields) => fields
429 .iter()
430 .enumerate()
431 .map(|(index, field)| IdentOrIndex::Index {
432 index,
433 span: field.span(),
434 attributes: field.attributes.clone(),
435 })
436 .collect(),
437 Self::Struct(fields) => fields
438 .iter()
439 .map(|(ident, field)| IdentOrIndex::Ident {
440 ident: ident.clone(),
441 attributes: field.attributes.clone(),
442 })
443 .collect(),
444 };
445 result
446 }
447
448 pub fn delimiter(&self) -> Delimiter {
457 match self {
458 Self::Tuple(_) => Delimiter::Parenthesis,
459 Self::Struct(_) => Delimiter::Brace,
460 }
461 }
462}
463
464#[cfg(test)]
465impl Fields {
466 fn len(&self) -> usize {
467 match self {
468 Self::Tuple(fields) => fields.len(),
469 Self::Struct(fields) => fields.len(),
470 }
471 }
472
473 fn get(&self, index: usize) -> Option<(Option<&Ident>, &UnnamedField)> {
474 match self {
475 Self::Tuple(fields) => fields.get(index).map(|f| (None, f)),
476 Self::Struct(fields) => fields.get(index).map(|(ident, field)| (Some(ident), field)),
477 }
478 }
479}
480
481#[derive(Debug)]
483pub struct UnnamedField {
484 pub vis: Visibility,
486 pub r#type: Vec<TokenTree>,
488 pub attributes: Vec<Attribute>,
490}
491
492impl UnnamedField {
493 pub(crate) fn parse_with_name(
494 input: &mut Peekable<impl Iterator<Item = TokenTree>>,
495 ) -> Result<Vec<(Ident, Self)>> {
496 let mut result = Vec::new();
497 loop {
498 let attributes = Attribute::try_take(AttributeLocation::Field, input)?;
499 let vis = Visibility::try_take(input)?;
500
501 let ident = match input.peek() {
502 Some(TokenTree::Ident(_)) => assume_ident(input.next()),
503 Some(x) => {
504 return Err(Error::InvalidRustSyntax {
505 span: x.span(),
506 expected: format!("ident or end of group, got {:?}", x),
507 });
508 }
509 None => break,
510 };
511 match input.peek() {
512 Some(TokenTree::Punct(p)) if p.as_char() == ':' => {
513 input.next();
514 }
515 token => return Error::wrong_token(token, ":"),
516 }
517 let r#type = read_tokens_until_punct(input, &[','])?;
518 consume_punct_if(input, ',');
519 result.push((
520 ident,
521 Self {
522 vis,
523 r#type,
524 attributes,
525 },
526 ));
527 }
528 Ok(result)
529 }
530
531 pub(crate) fn parse(
532 input: &mut Peekable<impl Iterator<Item = TokenTree>>,
533 ) -> Result<Vec<Self>> {
534 let mut result = Vec::new();
535 while input.peek().is_some() {
536 let attributes = Attribute::try_take(AttributeLocation::Field, input)?;
537 let vis = Visibility::try_take(input)?;
538
539 let r#type = read_tokens_until_punct(input, &[','])?;
540 consume_punct_if(input, ',');
541 result.push(Self {
542 vis,
543 r#type,
544 attributes,
545 });
546 }
547 Ok(result)
548 }
549
550 pub fn type_string(&self) -> String {
554 self.r#type.iter().map(|t| t.to_string()).collect()
555 }
556
557 pub fn span(&self) -> Span {
563 match self.r#type.first() {
576 Some(first) => first.span(),
577 None => Span::call_site(),
578 }
579 }
580}
581
582#[derive(Debug, Clone)]
592pub enum IdentOrIndex {
593 Ident {
595 ident: Ident,
597 attributes: Vec<Attribute>,
599 },
600 Index {
602 index: usize,
604 span: Span,
606 attributes: Vec<Attribute>,
608 },
609}
610
611impl IdentOrIndex {
612 pub fn unwrap_ident(&self) -> Ident {
614 match self {
615 Self::Ident { ident, .. } => ident.clone(),
616 x => panic!("Expected ident, found {:?}", x),
617 }
618 }
619
620 pub fn to_token_tree_with_prefix(&self, prefix: &str) -> TokenTree {
622 TokenTree::Ident(match self {
623 IdentOrIndex::Ident { ident, .. } => (*ident).clone(),
624 IdentOrIndex::Index { index, span, .. } => {
625 let name = format!("{}{}", prefix, index);
626 Ident::new(&name, *span)
627 }
628 })
629 }
630
631 pub fn to_string_with_prefix(&self, prefix: &str) -> String {
633 match self {
634 IdentOrIndex::Ident { ident, .. } => ident.to_string(),
635 IdentOrIndex::Index { index, .. } => {
636 format!("{}{}", prefix, index)
637 }
638 }
639 }
640
641 pub fn attributes(&self) -> &Vec<Attribute> {
643 match self {
644 Self::Ident { attributes, .. } => attributes,
645 Self::Index { attributes, .. } => attributes,
646 }
647 }
648}
649
650impl std::fmt::Display for IdentOrIndex {
651 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
652 match self {
653 IdentOrIndex::Ident { ident, .. } => write!(fmt, "{}", ident),
654 IdentOrIndex::Index { index, .. } => write!(fmt, "{}", index),
655 }
656 }
657}
658
659#[test]
660fn enum_explicit_variants() {
661 use crate::token_stream;
662 let stream = &mut token_stream("{ A = 1, B = 2 }");
663 let body = EnumBody::take(stream).unwrap();
664 assert_eq!(body.variants.len(), 2);
665}