1use super::Attribute;
2use super::Visibility;
3use super::attributes::AttributeLocation;
4use super::utils::assume_group;
5use super::utils::assume_ident;
6use super::utils::assume_punct;
7use super::utils::consume_punct_if;
8use super::utils::read_tokens_until_punct;
9use crate::Error;
10use crate::Result;
11use crate::prelude::Delimiter;
12use crate::prelude::Ident;
13use crate::prelude::Literal;
14use crate::prelude::Span;
15use crate::prelude::TokenTree;
16use std::iter::Peekable;
17
18#[derive(Debug)]
20pub struct StructBody {
21 pub fields: Option<Fields>,
23}
24
25impl StructBody {
26 pub(crate) fn take(input: &mut Peekable<impl Iterator<Item = TokenTree>>) -> Result<Self> {
27 match input.peek() {
28 | Some(TokenTree::Group(_)) => {},
29 | Some(TokenTree::Punct(p)) if p.as_char() == ';' => {
30 return Ok(Self { fields: None });
31 },
32 | token => return Error::wrong_token(token, "group or punct"),
33 }
34 let group = assume_group(input.next());
35 let mut stream = group.stream().into_iter().peekable();
36 let fields = match group.delimiter() {
37 | Delimiter::Brace => {
38 let fields = UnnamedField::parse_with_name(&mut stream)?;
39 Some(Fields::Struct(fields))
40 },
41 | Delimiter::Parenthesis => {
42 let fields = UnnamedField::parse(&mut stream)?;
43 Some(Fields::Tuple(fields))
44 },
45 | found => {
46 return Err(Error::InvalidRustSyntax {
47 span: group.span(),
48 expected: format!("brace or parenthesis, found {found:?}"),
49 });
50 },
51 };
52 Ok(Self { fields })
53 }
54}
55
56#[test]
57fn test_struct_body_take() {
58 use crate::token_stream;
59
60 let stream = &mut token_stream(
61 "struct Foo { pub bar: u8, pub(crate) baz: u32, bla: Vec<Box<dyn Future<Output = ()>>> }",
62 );
63 let (data_type, ident) = super::DataType::take(stream).unwrap();
64 assert_eq!(data_type, super::DataType::Struct);
65 assert_eq!(ident, "Foo");
66 let body = StructBody::take(stream).unwrap();
67 let fields = body.fields.as_ref().unwrap();
68
69 assert_eq!(fields.len(), 3);
70 let (ident, field) = fields.get(0).unwrap();
71 assert_eq!(ident.unwrap(), "bar");
72 assert_eq!(field.vis, Visibility::Pub);
73 assert_eq!(field.type_string(), "u8");
74
75 let (ident, field) = fields.get(1).unwrap();
76 assert_eq!(ident.unwrap(), "baz");
77 assert_eq!(field.vis, Visibility::Pub);
78 assert_eq!(field.type_string(), "u32");
79
80 let (ident, field) = fields.get(2).unwrap();
81 assert_eq!(ident.unwrap(), "bla");
82 assert_eq!(field.vis, Visibility::Default);
83 assert_eq!(field.type_string(), "Vec<Box<dynFuture<Output=()>>>");
84
85 let stream = &mut token_stream(
86 "struct Foo ( pub u8, pub(crate) u32, Vec<Box<dyn Future<Output = ()>>> )",
87 );
88 let (data_type, ident) = super::DataType::take(stream).unwrap();
89 assert_eq!(data_type, super::DataType::Struct);
90 assert_eq!(ident, "Foo");
91 let body = StructBody::take(stream).unwrap();
92 let fields = body.fields.as_ref().unwrap();
93
94 assert_eq!(fields.len(), 3);
95
96 let (ident, field) = fields.get(0).unwrap();
97 assert!(ident.is_none());
98 assert_eq!(field.vis, Visibility::Pub);
99 assert_eq!(field.type_string(), "u8");
100
101 let (ident, field) = fields.get(1).unwrap();
102 assert!(ident.is_none());
103 assert_eq!(field.vis, Visibility::Pub);
104 assert_eq!(field.type_string(), "u32");
105
106 let (ident, field) = fields.get(2).unwrap();
107 assert!(ident.is_none());
108 assert_eq!(field.vis, Visibility::Default);
109 assert_eq!(field.type_string(), "Vec<Box<dynFuture<Output=()>>>");
110
111 let stream = &mut token_stream("struct Foo;");
112 let (data_type, ident) = super::DataType::take(stream).unwrap();
113 assert_eq!(data_type, super::DataType::Struct);
114 assert_eq!(ident, "Foo");
115 let body = StructBody::take(stream).unwrap();
116 assert!(body.fields.is_none());
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::Struct(v)) = body.fields {
124 assert!(v.is_empty());
125 } else {
126 panic!("wrong fields {:?}", body.fields);
127 }
128
129 let stream = &mut token_stream("struct Foo ()");
130 let (data_type, ident) = super::DataType::take(stream).unwrap();
131 assert_eq!(data_type, super::DataType::Struct);
132 assert_eq!(ident, "Foo");
133 let body = StructBody::take(stream).unwrap();
134 if let Some(Fields::Tuple(v)) = body.fields {
135 assert!(v.is_empty());
136 } else {
137 panic!("wrong fields {:?}", body.fields);
138 }
139}
140
141#[test]
142fn issue_77() {
143 use crate::token_stream;
145
146 let stream = &mut token_stream("struct Test(pub [u8; 32])");
147 let (data_type, ident) = super::DataType::take(stream).unwrap();
148 assert_eq!(data_type, super::DataType::Struct);
149 assert_eq!(ident, "Test");
150 let body = StructBody::take(stream).unwrap();
151 let fields = body.fields.unwrap();
152 let Fields::Tuple(t) = fields else {
153 panic!("Fields is not a tuple")
154 };
155 assert_eq!(t.len(), 1);
156 assert_eq!(t[0].r#type[0].to_string(), "[u8 ; 32]");
157
158 let stream = &mut token_stream("struct Foo(pub (u8, ))");
159 let (data_type, ident) = super::DataType::take(stream).unwrap();
160 assert_eq!(data_type, super::DataType::Struct);
161 assert_eq!(ident, "Foo");
162 let body = StructBody::take(stream).unwrap();
163 let fields = body.fields.unwrap();
164 let Fields::Tuple(t) = fields else {
165 panic!("Fields is not a tuple")
166 };
167 assert_eq!(t.len(), 1);
168 assert_eq!(t[0].r#type[0].to_string(), "(u8 ,)");
169}
170
171#[derive(Debug)]
173pub struct EnumBody {
174 pub variants: Vec<EnumVariant>,
176}
177
178impl EnumBody {
179 pub(crate) fn take(input: &mut Peekable<impl Iterator<Item = TokenTree>>) -> Result<Self> {
180 match input.peek() {
181 | Some(TokenTree::Group(_)) => {},
182 | Some(TokenTree::Punct(p)) if p.as_char() == ';' => {
183 return Ok(Self { variants: Vec::new() });
184 },
185 | token => return Error::wrong_token(token, "group or ;"),
186 }
187 let group = assume_group(input.next());
188 let mut variants = Vec::new();
189 let mut variant_stream = group.stream().into_iter().peekable();
190 let stream = &mut variant_stream;
191 while stream.peek().is_some() {
192 let attributes = Attribute::try_take(AttributeLocation::Variant, stream)?;
193 let ident = match super::utils::consume_ident(stream) {
194 | Some(ident) => ident,
195 | None => Error::wrong_token(stream.peek(), "ident")?,
196 };
197
198 let mut fields = None;
199 let mut value = None;
200
201 if let Some(TokenTree::Group(_)) = stream.peek() {
202 let group = assume_group(stream.next());
203 let mut inner_stream = group.stream().into_iter().peekable();
204 let stream_ref = &mut inner_stream;
205 match group.delimiter() {
206 | Delimiter::Brace => {
207 fields = Some(Fields::Struct(UnnamedField::parse_with_name(stream_ref)?));
208 },
209 | Delimiter::Parenthesis => {
210 fields = Some(Fields::Tuple(UnnamedField::parse(stream_ref)?));
211 },
212 | delim => {
213 return Err(Error::InvalidRustSyntax {
214 span: group.span(),
215 expected: format!("Brace or parenthesis, found {delim:?}"),
216 });
217 },
218 }
219 }
220 match stream.peek() {
221 | Some(TokenTree::Punct(p)) if p.as_char() == '=' => {
222 assume_punct(stream.next(), '=');
223
224 let first_val_token = stream.next(); match first_val_token {
226 | Some(TokenTree::Literal(lit)) => {
227 value = Some(lit);
228 },
229 | Some(TokenTree::Punct(p)) if p.as_char() == '-' => {
230 let second_val_token = stream.next(); match second_val_token {
232 | Some(TokenTree::Literal(lit)) => {
233 match lit.to_string().parse::<i64>() {
234 | Ok(val) => value = Some(Literal::i64_unsuffixed(-val)),
235 | Err(_) => {
236 return Err(Error::custom_at(
237 "parse::<i64> failed",
238 lit.span(),
239 ));
240 },
241 }
242 },
243 | token => return Error::wrong_token(token.as_ref(), "literal"),
244 }
245 },
246 | token => return Error::wrong_token(token.as_ref(), "literal"),
247 }
248 },
249 | Some(TokenTree::Punct(p)) if p.as_char() == ',' => {
250 },
252 | None => {
253 },
255 | token => return Error::wrong_token(token, "group, comma or ="),
256 }
257
258 consume_punct_if(stream, ',');
259
260 variants.push(EnumVariant {
261 name: ident,
262 fields,
263 value,
264 attributes,
265 });
266 }
267
268 Ok(Self { variants })
269 }
270}
271
272#[test]
273fn test_enum_body_take() {
274 use crate::token_stream;
275
276 let stream = &mut token_stream("enum Foo { }");
277 let (data_type, ident) = super::DataType::take(stream).unwrap();
278 assert_eq!(data_type, super::DataType::Enum);
279 assert_eq!(ident, "Foo");
280 let body = EnumBody::take(stream).unwrap();
281 assert!(body.variants.is_empty());
282
283 let stream = &mut token_stream("enum Foo { Bar, Baz(u8), Blah { a: u32, b: u128 } }");
284 let (data_type, ident) = super::DataType::take(stream).unwrap();
285 assert_eq!(data_type, super::DataType::Enum);
286 assert_eq!(ident, "Foo");
287 let body = EnumBody::take(stream).unwrap();
288 assert_eq!(3, body.variants.len());
289
290 assert_eq!(body.variants[0].name, "Bar");
291 assert!(body.variants[0].fields.is_none());
292
293 assert_eq!(body.variants[1].name, "Baz");
294 assert!(body.variants[1].fields.is_some());
295 let fields = body.variants[1].fields.as_ref().unwrap();
296 assert_eq!(1, fields.len());
297 let (ident, field) = fields.get(0).unwrap();
298 assert!(ident.is_none());
299 assert_eq!(field.type_string(), "u8");
300
301 assert_eq!(body.variants[2].name, "Blah");
302 assert!(body.variants[2].fields.is_some());
303 let fields = body.variants[2].fields.as_ref().unwrap();
304 assert_eq!(2, fields.len());
305 let (ident, field) = fields.get(0).unwrap();
306 assert_eq!(ident.unwrap(), "a");
307 assert_eq!(field.type_string(), "u32");
308 let (ident, field) = fields.get(1).unwrap();
309 assert_eq!(ident.unwrap(), "b");
310 assert_eq!(field.type_string(), "u128");
311
312 let stream = &mut token_stream("enum Foo { Bar = -1, Baz = 2 }");
313 let (data_type, ident) = super::DataType::take(stream).unwrap();
314 assert_eq!(data_type, super::DataType::Enum);
315 assert_eq!(ident, "Foo");
316 let body = EnumBody::take(stream).unwrap();
317 assert_eq!(2, body.variants.len());
318
319 assert_eq!(body.variants[0].name, "Bar");
320 assert!(body.variants[0].fields.is_none());
321 assert_eq!(body.variants[0].get_integer(), -1);
322
323 assert_eq!(body.variants[1].name, "Baz");
324 assert!(body.variants[1].fields.is_none());
325 assert_eq!(body.variants[1].get_integer(), 2);
326
327 let stream = &mut token_stream("enum Foo { Bar(i32) = -1, Baz { a: i32 } = 2 }");
328 let (data_type, ident) = super::DataType::take(stream).unwrap();
329 assert_eq!(data_type, super::DataType::Enum);
330 assert_eq!(ident, "Foo");
331 let body = EnumBody::take(stream).unwrap();
332 assert_eq!(2, body.variants.len());
333
334 assert_eq!(body.variants[0].name, "Bar");
335 assert!(body.variants[0].fields.is_some());
336 let fields = body.variants[0].fields.as_ref().unwrap();
337 assert_eq!(fields.len(), 1);
338 assert!(matches!(fields.names()[0], IdentOrIndex::Index { index, .. } if index == 0));
339 assert_eq!(body.variants[0].get_integer(), -1);
340
341 assert_eq!(body.variants[1].name, "Baz");
342 assert!(body.variants[1].fields.is_some());
343 let fields = body.variants[1].fields.as_ref().unwrap();
344 assert_eq!(fields.len(), 1);
345 assert_eq!(fields.names().len(), 1);
346 assert!(matches!(&fields.names()[0], IdentOrIndex::Ident { ident, .. } if *ident == "a"));
347 assert_eq!(body.variants[1].get_integer(), 2);
348
349 let stream = &mut token_stream("enum Foo { Round(), Curly{}, Without }");
350 let (data_type, ident) = super::DataType::take(stream).unwrap();
351 assert_eq!(data_type, super::DataType::Enum);
352 assert_eq!(ident, "Foo");
353 let body = EnumBody::take(stream).unwrap();
354 assert_eq!(3, body.variants.len());
355
356 assert_eq!(body.variants[0].name, "Round");
357 assert!(body.variants[0].fields.is_some());
358 let fields = body.variants[0].fields.as_ref().unwrap();
359 assert!(fields.names().is_empty());
360 assert_eq!(fields.len(), 0);
361
362 assert_eq!(body.variants[1].name, "Curly");
363 assert!(body.variants[1].fields.is_some());
364 let fields = body.variants[1].fields.as_ref().unwrap();
365 assert!(fields.names().is_empty());
366 assert_eq!(fields.len(), 0);
367
368 assert_eq!(body.variants[2].name, "Without");
369 assert!(body.variants[2].fields.is_none());
370}
371
372#[derive(Debug)]
374pub struct EnumVariant {
375 pub name: Ident,
377 pub fields: Option<Fields>,
379 pub value: Option<Literal>,
386 pub attributes: Vec<Attribute>,
388}
389
390#[cfg(test)]
391impl EnumVariant {
392 fn get_integer(&self) -> i64 {
393 let value = self.value.as_ref().expect("Variant has no value");
394 value
395 .to_string()
396 .parse()
397 .expect("Value is not a valid integer")
398 }
399}
400
401#[derive(Debug)]
403pub enum Fields {
404 Tuple(Vec<UnnamedField>),
412
413 Struct(Vec<(Ident, UnnamedField)>),
425}
426
427impl Fields {
428 #[must_use]
436 pub fn names(&self) -> Vec<IdentOrIndex> {
437 let result: Vec<IdentOrIndex> = match self {
438 | Self::Tuple(fields) => {
439 fields
440 .iter()
441 .enumerate()
442 .map(|(index, field)| {
443 IdentOrIndex::Index {
444 index,
445 span: field.span(),
446 attributes: field.attributes.clone(),
447 }
448 })
449 .collect()
450 },
451 | Self::Struct(fields) => {
452 fields
453 .iter()
454 .map(|(ident, field)| {
455 IdentOrIndex::Ident {
456 ident: ident.clone(),
457 attributes: field.attributes.clone(),
458 }
459 })
460 .collect()
461 },
462 };
463 result
464 }
465
466 #[must_use]
475 pub const fn delimiter(&self) -> Delimiter {
476 match self {
477 | Self::Tuple(_) => Delimiter::Parenthesis,
478 | Self::Struct(_) => Delimiter::Brace,
479 }
480 }
481}
482
483#[cfg(test)]
484impl Fields {
485 fn len(&self) -> usize {
486 match self {
487 | Self::Tuple(fields) => fields.len(),
488 | Self::Struct(fields) => fields.len(),
489 }
490 }
491
492 fn get(
493 &self,
494 index: usize,
495 ) -> Option<(Option<&Ident>, &UnnamedField)> {
496 match self {
497 | Self::Tuple(fields) => fields.get(index).map(|f| (None, f)),
498 | Self::Struct(fields) => fields.get(index).map(|(ident, field)| (Some(ident), field)),
499 }
500 }
501}
502
503#[derive(Debug)]
505pub struct UnnamedField {
506 pub vis: Visibility,
508 pub r#type: Vec<TokenTree>,
510 pub attributes: Vec<Attribute>,
512}
513
514impl UnnamedField {
515 pub(crate) fn parse_with_name(
516 input: &mut Peekable<impl Iterator<Item = TokenTree>>
517 ) -> Result<Vec<(Ident, Self)>> {
518 let mut result = Vec::new();
519 loop {
520 let attributes = Attribute::try_take(AttributeLocation::Field, input)?;
521 let vis = Visibility::try_take(input)?;
522
523 let ident = match input.peek() {
524 | Some(TokenTree::Ident(_)) => assume_ident(input.next()),
525 | Some(x) => {
526 return Err(Error::InvalidRustSyntax {
527 span: x.span(),
528 expected: format!("ident or end of group, got {x:?}"),
529 });
530 },
531 | None => break,
532 };
533 match input.peek() {
534 | Some(TokenTree::Punct(p)) if p.as_char() == ':' => {
535 input.next();
536 },
537 | token => return Error::wrong_token(token, ":"),
538 }
539 let r#type = read_tokens_until_punct(input, &[','])?;
540 consume_punct_if(input, ',');
541 result.push((
542 ident,
543 Self {
544 vis,
545 r#type,
546 attributes,
547 },
548 ));
549 }
550 Ok(result)
551 }
552
553 pub(crate) fn parse(
554 input: &mut Peekable<impl Iterator<Item = TokenTree>>
555 ) -> Result<Vec<Self>> {
556 let mut result = Vec::new();
557 while input.peek().is_some() {
558 let attributes = Attribute::try_take(AttributeLocation::Field, input)?;
559 let vis = Visibility::try_take(input)?;
560
561 let r#type = read_tokens_until_punct(input, &[','])?;
562 consume_punct_if(input, ',');
563 result.push(Self {
564 vis,
565 r#type,
566 attributes,
567 });
568 }
569 Ok(result)
570 }
571
572 #[must_use]
580 pub fn type_string(&self) -> String {
581 self.r#type
582 .iter()
583 .map(std::string::ToString::to_string)
584 .collect()
585 }
586
587 #[must_use]
597 pub fn span(&self) -> Span {
598 match self.r#type.first() {
611 | Some(first) => first.span(),
612 | None => Span::call_site(),
613 }
614 }
615}
616
617#[derive(Debug, Clone)]
627pub enum IdentOrIndex {
628 Ident {
630 ident: Ident,
632 attributes: Vec<Attribute>,
634 },
635 Index {
637 index: usize,
639 span: Span,
641 attributes: Vec<Attribute>,
643 },
644}
645
646impl IdentOrIndex {
647 #[must_use]
653 pub fn unwrap_ident(&self) -> Ident {
654 match self {
655 | Self::Ident { ident, .. } => ident.clone(),
656 | x => panic!("Expected ident, found {x:?}"),
657 }
658 }
659
660 #[must_use]
662 pub fn to_token_tree_with_prefix(
663 &self,
664 prefix: &str,
665 ) -> TokenTree {
666 TokenTree::Ident(match self {
667 | Self::Ident { ident, .. } => (*ident).clone(),
668 | Self::Index { index, span, .. } => {
669 let name = format!("{prefix}{index}");
670 Ident::new(&name, *span)
671 },
672 })
673 }
674
675 #[must_use]
677 pub fn to_string_with_prefix(
678 &self,
679 prefix: &str,
680 ) -> String {
681 match self {
682 | Self::Ident { ident, .. } => ident.to_string(),
683 | Self::Index { index, .. } => {
684 format!("{prefix}{index}")
685 },
686 }
687 }
688
689 #[allow(clippy::match_same_arms)]
695 #[must_use]
696 pub const fn attributes(&self) -> &Vec<Attribute> {
697 match self {
698 | Self::Ident { attributes, .. } => attributes,
699 | Self::Index { attributes, .. } => attributes,
700 }
701 }
702}
703
704impl std::fmt::Display for IdentOrIndex {
705 fn fmt(
706 &self,
707 fmt: &mut std::fmt::Formatter<'_>,
708 ) -> std::fmt::Result {
709 match self {
710 | Self::Ident { ident, .. } => write!(fmt, "{ident}"),
711 | Self::Index { index, .. } => write!(fmt, "{index}"),
712 }
713 }
714}
715
716#[test]
717fn enum_explicit_variants() {
718 use crate::token_stream;
719 let stream = &mut token_stream("{ A = 1, B = 2 }");
720 let body = EnumBody::take(stream).unwrap();
721 assert_eq!(body.variants.len(), 2);
722}