1use crate::{parse_helpers::*, Errors, Result};
2use proc_macro2::Span;
3use quote::ToTokens;
4use std::{
5 borrow::Borrow,
6 collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque},
7 fmt::{self, Write},
8 hash::Hash,
9};
10use syn::{
11 parse::{Nothing, Parse, ParseBuffer, ParseStream, Peek},
12 punctuated::Punctuated,
13 Token,
14};
15
16#[derive(Debug, Clone, Copy)]
18pub enum ParseMode {
19 Named(Span),
23 Unnamed,
25}
26
27impl ParseMode {
28 #[inline]
32 pub fn to_named(&self, input: ParseStream) -> Self {
33 match self {
34 Self::Unnamed => Self::Named(input.span()),
35 m => *m,
36 }
37 }
38 #[inline]
42 pub fn named_span(&self) -> Option<Span> {
43 match self {
44 Self::Named(s) => Some(*s),
45 _ => None,
46 }
47 }
48 #[inline]
53 pub fn to_span(&self, input: ParseStream) -> Span {
54 self.named_span().unwrap_or_else(|| input.span())
55 }
56 #[inline]
60 pub fn to_full_span<'s, S: Borrow<ParseBuffer<'s>>>(&self, inputs: &[S]) -> Span {
61 self.named_span().unwrap_or_else(|| inputs_span(inputs))
62 }
63}
64
65pub trait ParseMetaItem: Sized {
77 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self>;
91 #[inline]
105 fn parse_meta_item_inline<'s, S: Borrow<ParseBuffer<'s>>>(
106 inputs: &[S],
107 _mode: ParseMode,
108 ) -> Result<Self> {
109 parse_first(inputs, _mode, Self::parse_meta_item)
110 }
111 #[inline]
118 fn parse_meta_item_flag(_span: Span) -> Result<Self> {
119 Err(flag_disallowed_error(_span))
120 }
121 #[inline]
129 fn parse_meta_item_named(input: ParseStream, _name: &str, span: Span) -> Result<Self> {
130 parse_named_meta_item(input, span)
131 }
132 #[inline]
140 fn missing_meta_item(name: &str, span: Span) -> Result<Self> {
141 Err(missing_field_error(name, span))
142 }
143}
144
145pub trait ParseMetaFlatUnnamed: Sized {
153 fn field_count() -> Option<usize>;
159 fn parse_meta_flat_unnamed<'s, S: Borrow<ParseBuffer<'s>>>(
176 inputs: &[S],
177 _mode: ParseMode,
178 index: usize,
179 ) -> Result<Self>;
180}
181
182pub trait ParseMetaFlatNamed: Sized {
190 fn field_names() -> &'static [&'static str];
192 fn parse_meta_flat_named<'s, S: Borrow<ParseBuffer<'s>>>(
207 inputs: &[S],
208 _mode: ParseMode,
209 prefix: &str,
210 validate: bool,
211 ) -> Result<Self>;
212 const ACCEPTS_ALL: bool = false;
216}
217
218pub trait ParseMetaAppend: Sized {
223 fn parse_meta_append<'s, S, I, P>(inputs: &[S], paths: I) -> Result<Self>
228 where
229 S: Borrow<ParseBuffer<'s>>,
230 I: IntoIterator<Item = P>,
231 I::IntoIter: Clone,
232 P: AsRef<str>;
233}
234
235pub trait ParseMetaRest: Sized {
240 fn parse_meta_rest<'s, S: Borrow<ParseBuffer<'s>>>(
245 inputs: &[S],
246 exclude: &[&str],
247 ) -> Result<Self>;
248}
249
250pub trait ToKeyString: Sized {
256 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result;
258 fn with_key_string<R>(&self, f: impl FnOnce(&str) -> R) -> R {
263 f(&key_to_string(self))
264 }
265}
266
267macro_rules! impl_parse_meta_item_primitive {
268 ($ty:ty, $lit:ty, $conv:ident) => {
269 impl ParseMetaItem for $ty {
270 #[inline]
271 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
272 impl_parse_meta_item_primitive!(@conv input, _mode, $lit, $conv)
273 }
274 }
275 impl ToKeyString for $ty {
276 #[inline]
277 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
278 fmt::Display::fmt(self, f)
279 }
280 }
281 };
282 (@conv $input:ident, $mode:ident, $lit:ty, base10_parse) => {
283 $input.parse::<$lit>()?.base10_parse()
284 };
285 (@conv $input:ident, $mode:ident, $lit:ty, value) => {
286 Ok($input.parse::<$lit>()?.value())
287 };
288 (@conv $input:ident, $mode:ident, $lit:ty, from_str) => {
289 $crate::with::from_str::parse_meta_item($input, $mode)
290 };
291}
292
293impl_parse_meta_item_primitive!(i8, syn::LitInt, base10_parse);
294impl_parse_meta_item_primitive!(i16, syn::LitInt, base10_parse);
295impl_parse_meta_item_primitive!(i32, syn::LitInt, base10_parse);
296impl_parse_meta_item_primitive!(i64, syn::LitInt, base10_parse);
297impl_parse_meta_item_primitive!(i128, syn::LitInt, base10_parse);
298impl_parse_meta_item_primitive!(isize, syn::LitInt, base10_parse);
299
300impl ParseMetaItem for u8 {
301 #[inline]
302 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
303 let lookahead = input.lookahead1();
304 if lookahead.peek(syn::LitByte) {
305 Ok(input.parse::<syn::LitByte>()?.value())
306 } else if lookahead.peek(syn::LitInt) {
307 Ok(input.parse::<syn::LitInt>()?.base10_parse()?)
308 } else {
309 Err(lookahead.error())
310 }
311 }
312}
313
314impl_parse_meta_item_primitive!(u16, syn::LitInt, base10_parse);
315impl_parse_meta_item_primitive!(u32, syn::LitInt, base10_parse);
316impl_parse_meta_item_primitive!(u64, syn::LitInt, base10_parse);
317impl_parse_meta_item_primitive!(u128, syn::LitInt, base10_parse);
318impl_parse_meta_item_primitive!(usize, syn::LitInt, base10_parse);
319
320impl_parse_meta_item_primitive!(f32, syn::LitFloat, base10_parse);
321impl_parse_meta_item_primitive!(f64, syn::LitFloat, base10_parse);
322
323impl ParseMetaItem for bool {
324 #[inline]
325 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
326 Ok(input.parse::<syn::LitBool>()?.value())
327 }
328 #[inline]
329 fn parse_meta_item_flag(_: Span) -> Result<Self> {
330 Ok(true)
331 }
332}
333
334impl_parse_meta_item_primitive!(std::num::NonZeroI8, syn::LitInt, base10_parse);
335impl_parse_meta_item_primitive!(std::num::NonZeroI16, syn::LitInt, base10_parse);
336impl_parse_meta_item_primitive!(std::num::NonZeroI32, syn::LitInt, base10_parse);
337impl_parse_meta_item_primitive!(std::num::NonZeroI64, syn::LitInt, base10_parse);
338impl_parse_meta_item_primitive!(std::num::NonZeroI128, syn::LitInt, base10_parse);
339impl_parse_meta_item_primitive!(std::num::NonZeroIsize, syn::LitInt, base10_parse);
340
341impl_parse_meta_item_primitive!(std::num::NonZeroU8, syn::LitInt, base10_parse);
342impl_parse_meta_item_primitive!(std::num::NonZeroU16, syn::LitInt, base10_parse);
343impl_parse_meta_item_primitive!(std::num::NonZeroU32, syn::LitInt, base10_parse);
344impl_parse_meta_item_primitive!(std::num::NonZeroU64, syn::LitInt, base10_parse);
345impl_parse_meta_item_primitive!(std::num::NonZeroU128, syn::LitInt, base10_parse);
346impl_parse_meta_item_primitive!(std::num::NonZeroUsize, syn::LitInt, base10_parse);
347
348impl_parse_meta_item_primitive!(char, syn::LitChar, value);
349
350impl ParseMetaItem for String {
351 #[inline]
352 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
353 Ok(input.parse::<syn::LitStr>()?.value())
354 }
355}
356
357impl ToKeyString for String {
358 #[inline]
359 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
360 fmt::Display::fmt(self, f)
361 }
362 #[inline]
363 fn with_key_string<R>(&self, f: impl FnOnce(&str) -> R) -> R {
364 f(self)
365 }
366}
367
368impl ParseMetaItem for std::path::PathBuf {
369 #[inline]
370 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
371 Ok(Self::from(input.parse::<syn::LitStr>()?.value()))
372 }
373}
374
375impl ToKeyString for std::path::PathBuf {
376 #[inline]
377 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
378 f.write_str(&self.to_string_lossy())
379 }
380 #[inline]
381 fn with_key_string<R>(&self, f: impl FnOnce(&str) -> R) -> R {
382 f(&self.to_string_lossy())
383 }
384}
385
386impl ParseMetaItem for std::ffi::OsString {
387 #[inline]
388 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
389 Ok(Self::from(input.parse::<syn::LitStr>()?.value()))
390 }
391}
392
393impl ToKeyString for std::ffi::OsString {
394 #[inline]
395 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
396 f.write_str(&self.to_string_lossy())
397 }
398 #[inline]
399 fn with_key_string<R>(&self, f: impl FnOnce(&str) -> R) -> R {
400 f(&self.to_string_lossy())
401 }
402}
403
404impl_parse_meta_item_primitive!(std::net::IpAddr, syn::LitStr, from_str);
405impl_parse_meta_item_primitive!(std::net::Ipv4Addr, syn::LitStr, from_str);
406impl_parse_meta_item_primitive!(std::net::Ipv6Addr, syn::LitStr, from_str);
407impl_parse_meta_item_primitive!(std::net::SocketAddr, syn::LitStr, from_str);
408impl_parse_meta_item_primitive!(std::net::SocketAddrV4, syn::LitStr, from_str);
409impl_parse_meta_item_primitive!(std::net::SocketAddrV6, syn::LitStr, from_str);
410
411impl<T: ParseMetaItem> ParseMetaItem for Option<T> {
412 #[inline]
413 fn parse_meta_item(input: ParseStream, mode: ParseMode) -> Result<Self> {
414 match mode {
415 ParseMode::Named(_) => T::parse_meta_item(input, mode).map(Some),
416 ParseMode::Unnamed => {
417 mod keywords {
418 syn::custom_keyword!(Some);
419 syn::custom_keyword!(None);
420 }
421 let lookahead = input.lookahead1();
422 if lookahead.peek(keywords::Some) {
423 input.parse::<keywords::Some>()?;
424 Paren::parse_delimited_meta_item(input, mode).map(Some)
425 } else if lookahead.peek(keywords::None) {
426 input.parse::<keywords::None>()?;
427 Ok(None)
428 } else {
429 Err(lookahead.error())
430 }
431 }
432 }
433 }
434 #[inline]
435 fn parse_meta_item_flag(span: Span) -> Result<Self> {
436 T::parse_meta_item_flag(span).map(Some)
437 }
438 #[inline]
439 fn missing_meta_item(_name: &str, _span: Span) -> Result<Self> {
440 Ok(None)
441 }
442}
443
444impl<T: ToKeyString> ToKeyString for Option<T> {
445 #[inline]
446 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
447 match self {
448 Some(v) => {
449 f.write_str("Some(")?;
450 v.fmt_key_string(f)?;
451 f.write_char(')')
452 }
453 None => f.write_str("None"),
454 }
455 }
456}
457
458impl<T: ParseMetaItem, const N: usize> ParseMetaItem for [T; N] {
459 #[inline]
460 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
461 Bracket::parse_delimited_meta_item(input, ParseMode::Unnamed)
462 }
463 #[inline]
464 fn parse_meta_item_inline<'s, S: Borrow<ParseBuffer<'s>>>(
465 inputs: &[S],
466 _mode: ParseMode,
467 ) -> Result<Self> {
468 Self::parse_meta_flat_unnamed(inputs, _mode, 0)
469 }
470}
471
472impl<T: ParseMetaItem, const N: usize> ParseMetaFlatUnnamed for [T; N] {
473 #[inline]
474 fn field_count() -> Option<usize> {
475 Some(N)
476 }
477 fn parse_meta_flat_unnamed<'s, S: Borrow<ParseBuffer<'s>>>(
478 inputs: &[S],
479 _mode: ParseMode,
480 index: usize,
481 ) -> Result<Self> {
482 let mut a = arrayvec::ArrayVec::<T, N>::new();
483 let errors = Errors::new();
484 let mut failed = 0;
485 errors.push_result(parse_tuple_struct(inputs, N, |stream, _, _| {
486 match errors.push_result(T::parse_meta_item(stream, ParseMode::Unnamed)) {
487 Some(v) => a.push(v),
488 None => {
489 failed += 1;
490 skip_meta_item(stream);
491 }
492 }
493 Ok(())
494 }));
495 if a.len() + failed != N {
496 errors.push(
497 inputs_span(inputs),
498 format!(
499 "Expected array at index {} of length {}, got {}",
500 index,
501 N,
502 a.len() + failed,
503 ),
504 );
505 }
506 errors.check()?;
507 Ok(a.into_inner().unwrap_or_else(|_| unreachable!()))
508 }
509}
510
511impl<T: ToKeyString, const N: usize> ToKeyString for [T; N] {
512 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
513 f.write_char('[')?;
514 for (i, v) in self.iter().enumerate() {
515 if i > 0 {
516 f.write_str(", ")?;
517 }
518 v.fmt_key_string(f)?;
519 }
520 f.write_char(']')
521 }
522}
523
524macro_rules! impl_parse_meta_item_collection {
525 ($ty:ident <$param:ident $(: $bound:tt $(+ $bounds:tt)*)?>, $ident:ident, $item:ident, $push:expr) => {
526 impl<$param: ParseMetaItem $(+ $bound $(+ $bounds)*)?> ParseMetaItem for $ty <$param> {
527 #[inline]
528 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
529 Bracket::parse_delimited_meta_item(input, ParseMode::Unnamed)
530 }
531 #[inline]
532 fn parse_meta_item_inline<'s, S: Borrow<ParseBuffer<'s>>>(inputs: &[S], _mode: ParseMode) -> Result<Self> {
533 Self::parse_meta_flat_unnamed(inputs, _mode, 0)
534 }
535 }
536
537 impl<$param: ParseMetaItem $(+ $bound $(+ $bounds)*)?> ParseMetaFlatUnnamed for $ty <$param> {
538 #[inline]
539 fn field_count() -> Option<usize> {
540 None
541 }
542 fn parse_meta_flat_unnamed<'s, S: Borrow<ParseBuffer<'s>>>(
543 inputs: &[S],
544 _mode: ParseMode,
545 _index: usize
546 ) -> Result<Self> {
547 let mut $ident = Self::new();
548 let errors = Errors::new();
549 for input in inputs {
550 let input = input.borrow();
551 loop {
552 if input.is_empty() {
553 break;
554 }
555 match errors.push_result($param::parse_meta_item(input, ParseMode::Unnamed)) {
556 Some($item) => $push,
557 None => skip_meta_item(input),
558 }
559 if !input.is_empty() {
560 input.parse::<Token![,]>()?;
561 }
562 }
563 }
564 errors.check()?;
565 Ok($ident)
566 }
567 }
568
569 impl<$param: ParseMetaItem $(+ $bound $(+ $bounds)*)?> ParseMetaAppend for $ty <$param> {
570 fn parse_meta_append<'s, S, I, P>(inputs: &[S], paths: I) -> Result<Self>
571 where
572 S: Borrow<ParseBuffer<'s>>,
573 I: IntoIterator<Item = P>,
574 I::IntoIter: Clone,
575 P: AsRef<str>
576 {
577 let mut $ident = Self::new();
578 let errors = Errors::new();
579 let paths = paths.into_iter();
580 errors.push_result(parse_struct(inputs, |input, p, pspan| {
581 if paths.clone().any(|path| path.as_ref() == p) {
582 match errors.push_result(<_>::parse_meta_item_named(input, p, pspan)) {
583 Some($item) => $push,
584 None => skip_meta_item(input),
585 }
586 } else {
587 skip_meta_item(input);
588 }
589 Ok(())
590 }));
591 errors.check()?;
592 Ok($ident)
593 }
594 }
595
596 impl<$param: ToKeyString $(+ $bound $(+ $bounds)*)?> ToKeyString for $ty <$param> {
597 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
598 f.write_char('[')?;
599 for (i, v) in self.iter().enumerate() {
600 if i > 0 {
601 f.write_str(", ")?;
602 }
603 v.fmt_key_string(f)?;
604 }
605 f.write_char(']')
606 }
607 }
608 };
609}
610
611macro_rules! impl_parse_meta_item_set {
612 ($ty:ident <$param:ident $(: $bound:tt $(+ $bounds:tt)*)?>, $ident:ident, $item:ident, $push:expr) => {
613 impl<$param: ParseMetaItem $(+ $bound $(+ $bounds)*)?> ParseMetaItem for $ty <$param> {
614 #[inline]
615 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
616 Bracket::parse_delimited_meta_item(input, ParseMode::Unnamed)
617 }
618 #[inline]
619 fn parse_meta_item_inline<'s, S: Borrow<ParseBuffer<'s>>>(inputs: &[S], _mode: ParseMode) -> Result<Self> {
620 Self::parse_meta_flat_unnamed(inputs, _mode, 0)
621 }
622 }
623
624 impl<$param: ParseMetaItem $(+ $bound $(+ $bounds)*)?> ParseMetaFlatUnnamed for $ty <$param> {
625 #[inline]
626 fn field_count() -> Option<usize> {
627 None
628 }
629 fn parse_meta_flat_unnamed<'s, S: Borrow<ParseBuffer<'s>>>(
630 inputs: &[S],
631 _mode: ParseMode,
632 _index: usize
633 ) -> Result<Self> {
634 let mut $ident = Self::new();
635 let errors = Errors::new();
636 for input in inputs {
637 let input = input.borrow();
638 loop {
639 if input.is_empty() {
640 break;
641 }
642 let span = input.span();
643 match errors.push_result($param::parse_meta_item(input, ParseMode::Unnamed)) {
644 Some($item) => if !$push {
645 let span = input.span().join(span).unwrap_or(span);
646 errors.push(span, "Duplicate key");
647 },
648 None => skip_meta_item(input),
649 }
650 if !input.is_empty() {
651 input.parse::<Token![,]>()?;
652 }
653 }
654 }
655 errors.check()?;
656 Ok($ident)
657 }
658 }
659
660 impl<$param: ParseMetaItem $(+ $bound $(+ $bounds)*)?> ParseMetaAppend for $ty <$param> {
661 fn parse_meta_append<'s, S, I, P>(
662 inputs: &[S],
663 paths: I,
664 ) -> Result<Self>
665 where
666 S: Borrow<ParseBuffer<'s>>,
667 I: IntoIterator<Item = P>,
668 I::IntoIter: Clone,
669 P: AsRef<str>
670 {
671 let errors = Errors::new();
672 let mut $ident = Self::new();
673 let paths = paths.into_iter();
674 parse_struct(inputs, |input, p, pspan| {
675 if paths.clone().any(|path| path.as_ref() == p) {
676 let span = input.span();
677 let $item = <_>::parse_meta_item_named(input, p, pspan);
678 let span = input.span().join(span).unwrap_or(span);
679 match errors.push_result($item) {
680 Some($item) => if !$push {
681 errors.push(span, "Duplicate key");
682 },
683 None => skip_meta_item(input),
684 }
685 } else {
686 skip_meta_item(input);
687 }
688 Ok(())
689 })?;
690 errors.check()?;
691 Ok($ident)
692 }
693 }
694
695 impl<$param: ToKeyString $(+ $bound $(+ $bounds)*)?> ToKeyString for $ty <$param> {
696 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
697 f.write_char('[')?;
698 for (i, v) in self.iter().enumerate() {
699 if i > 0 {
700 f.write_str(", ")?;
701 }
702 v.fmt_key_string(f)?;
703 }
704 f.write_char(']')
705 }
706 }
707 };
708}
709
710macro_rules! impl_parse_meta_item_map {
711 (
712 $ty:ident <$kp:ident $(: $kbound:tt $(+ $kbounds:tt)*)?, $vp:ident>,
713 $ident:ident, $key:ident, $value:ident, $push:expr
714 ) => {
715 impl<$kp, $vp> ParseMetaItem for $ty <$kp, $vp>
716 where
717 $kp: ParseMetaItem + ToKeyString $(+ $kbound $(+ $kbounds)*)?,
718 $vp: ParseMetaItem,
719 {
720 #[inline]
721 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
722 Brace::parse_delimited_meta_item(input, _mode)
723 }
724 #[inline]
725 fn parse_meta_item_inline<'s, S: Borrow<ParseBuffer<'s>>>(inputs: &[S], mode: ParseMode) -> Result<Self> {
726 <Self as ParseMetaFlatUnnamed>::parse_meta_flat_unnamed(inputs, mode, 0)
727 }
728 }
729
730 impl<$kp, $vp> ParseMetaFlatUnnamed for $ty <$kp, $vp>
731 where
732 $kp: ParseMetaItem + ToKeyString $(+ $kbound $(+ $kbounds)*)?,
733 $vp: ParseMetaItem,
734 {
735 #[inline]
736 fn field_count() -> Option<usize> {
737 None
738 }
739 fn parse_meta_flat_unnamed<'s, S: Borrow<ParseBuffer<'s>>>(
740 inputs: &[S],
741 _mode: ParseMode,
742 _index: usize
743 ) -> Result<Self> {
744 let mut $ident = Self::new();
745 let errors = Errors::new();
746 for input in inputs {
747 let input = input.borrow();
748 loop {
749 if input.is_empty() {
750 break;
751 }
752 let start = input.span();
753 let $key = $kp::parse_meta_item(input, ParseMode::Unnamed)?;
754 let span = input.span().join(start).unwrap_or(start);
755 let $value = errors.push_result($key.with_key_string(|ks| {
756 <_>::parse_meta_item_named(input, &ks, start)
757 }));
758 match $value {
759 Some($value) => if !$push {
760 errors.push(span, "Duplicate key");
761 }
762 None => skip_meta_item(input),
763 }
764 if !input.is_empty() {
765 input.parse::<Token![,]>()?;
766 }
767 }
768 }
769 errors.check()?;
770 Ok($ident)
771 }
772 }
773
774 impl<$kp, $vp> ParseMetaRest for $ty <$kp, $vp>
775 where
776 $kp: ParseMetaItem + ToKeyString $(+ $kbound $(+ $kbounds)*)?,
777 $vp: ParseMetaItem,
778 {
779 fn parse_meta_rest<'s, S: Borrow<ParseBuffer<'s>>>(
780 inputs: &[S],
781 exclude: &[&str],
782 ) -> Result<Self> {
783 let mut $ident = Self::new();
784 let errors = Errors::new();
785 for input in inputs {
786 let input = input.borrow();
787 loop {
788 if input.is_empty() {
789 break;
790 }
791 let start = input.span();
792 let $key = $kp::parse_meta_item(input, ParseMode::Unnamed)?;
793 let span = input.span().join(start).unwrap_or(start);
794 let $value = errors.push_result($key.with_key_string(|ks| {
795 if exclude.contains(&ks) {
796 skip_meta_item(input);
797 Ok::<_, crate::Error>(None)
798 } else {
799 Ok(Some(<_>::parse_meta_item_named(input, &ks, start)?))
800 }
801 })).flatten();
802 if let Some($value) = $value {
803 if !$push {
804 errors.push(span, "Duplicate key");
805 }
806 }
807 if !input.is_empty() {
808 input.parse::<Token![,]>()?;
809 }
810 }
811 }
812 errors.check()?;
813 Ok($ident)
814 }
815 }
816
817 impl<$kp, $vp> ToKeyString for $ty <$kp, $vp>
818 where
819 $kp: ToKeyString $(+ $kbound $(+ $kbounds)*)?,
820 $vp: ToKeyString,
821 {
822 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
823 f.write_char('{')?;
824 for (i, (k, v)) in self.iter().enumerate() {
825 if i > 0 {
826 f.write_str(", ")?;
827 }
828 k.fmt_key_string(f)?;
829 f.write_str(" = ")?;
830 v.fmt_key_string(f)?;
831 }
832 f.write_char('}')
833 }
834 }
835 };
836}
837
838impl_parse_meta_item_collection!(Vec<T>, v, item, v.push(item));
839impl_parse_meta_item_set!(BTreeSet<T: Ord>, set, item, set.insert(item));
840impl_parse_meta_item_map!(BTreeMap<K: Ord, V>, map, key, value, map.insert(key, value).is_none());
841impl_parse_meta_item_collection!(BinaryHeap<T: Ord>, heap, item, heap.push(item));
842impl_parse_meta_item_set!(HashSet<T: Hash + Eq>, set, item, set.insert(item));
843impl_parse_meta_item_map!(HashMap<K: Hash + Eq, V>, map, key, value, map.insert(key, value).is_none());
844impl_parse_meta_item_collection!(LinkedList<T>, list, item, list.push_back(item));
845impl_parse_meta_item_collection!(VecDeque<T>, v, item, v.push_back(item));
846
847macro_rules! impl_parse_meta_item_wrapper {
848 ($i:ident $(::$ip:ident)* <$param:ident>) => {
849 impl<$param: ParseMetaItem> ParseMetaItem for $i $(::$ip)* <$param> {
850 #[inline]
851 fn parse_meta_item(input: ParseStream, mode: ParseMode) -> Result<Self> {
852 Ok(Self::new($param::parse_meta_item(input, mode)?))
853 }
854 #[inline]
855 fn parse_meta_item_flag(span: Span) -> Result<Self> {
856 $param::parse_meta_item_flag(span).map(Self::new)
857 }
858 }
859 };
860}
861
862impl_parse_meta_item_wrapper!(Box<T>);
863
864impl<T: ToKeyString> ToKeyString for Box<T> {
865 #[inline]
866 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
867 (**self).fmt_key_string(f)
868 }
869 #[inline]
870 fn with_key_string<R>(&self, f: impl FnOnce(&str) -> R) -> R {
871 (**self).with_key_string(f)
872 }
873}
874
875impl_parse_meta_item_wrapper!(std::rc::Rc<T>);
876
877impl<T: ToKeyString> ToKeyString for std::rc::Rc<T> {
878 #[inline]
879 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
880 (**self).fmt_key_string(f)
881 }
882 #[inline]
883 fn with_key_string<R>(&self, f: impl FnOnce(&str) -> R) -> R {
884 (**self).with_key_string(f)
885 }
886}
887impl_parse_meta_item_wrapper!(std::cell::Cell<T>);
888
889impl<T: ToKeyString + Copy> ToKeyString for std::cell::Cell<T> {
890 #[inline]
891 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
892 self.get().fmt_key_string(f)
893 }
894 #[inline]
895 fn with_key_string<R>(&self, f: impl FnOnce(&str) -> R) -> R {
896 self.get().with_key_string(f)
897 }
898}
899
900impl_parse_meta_item_wrapper!(std::cell::RefCell<T>);
901
902impl<T: ToKeyString> ToKeyString for std::cell::RefCell<T> {
903 #[inline]
904 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
905 self.borrow().fmt_key_string(f)
906 }
907 #[inline]
908 fn with_key_string<R>(&self, f: impl FnOnce(&str) -> R) -> R {
909 self.borrow().with_key_string(f)
910 }
911}
912
913impl<'t, T: ParseMetaItem + Clone> ParseMetaItem for std::borrow::Cow<'t, T> {
914 #[inline]
915 fn parse_meta_item(input: ParseStream, mode: ParseMode) -> Result<Self> {
916 Ok(Self::Owned(T::parse_meta_item(input, mode)?))
917 }
918 #[inline]
919 fn parse_meta_item_flag(span: Span) -> Result<Self> {
920 T::parse_meta_item_flag(span).map(Self::Owned)
921 }
922}
923
924impl<'t, T: ToKeyString + Clone> ToKeyString for std::borrow::Cow<'t, T> {
925 #[inline]
926 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
927 (**self).fmt_key_string(f)
928 }
929 #[inline]
930 fn with_key_string<R>(&self, f: impl FnOnce(&str) -> R) -> R {
931 (**self).with_key_string(f)
932 }
933}
934
935impl ParseMetaItem for proc_macro2::TokenTree {
936 #[inline]
937 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
938 input.step(|cursor| {
939 cursor
940 .token_tree()
941 .ok_or_else(|| crate::Error::new(cursor.span(), "unexpected end of tokens"))
942 })
943 }
944}
945
946macro_rules! impl_fmt_key_string_display {
947 ($(#[$attr:meta])* $ty:ty) => {
948 $(#[$attr])*
949 impl ToKeyString for $ty {
950 #[inline]
951 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
952 fmt::Display::fmt(self, f)
953 }
954 }
955 };
956 ($ty:ty, #proc_macro) => {
957 impl_fmt_key_string_display!(
958 #[cfg(feature = "proc-macro")]
959 #[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))]
960 $ty
961 );
962 };
963}
964
965impl_fmt_key_string_display!(proc_macro2::TokenTree);
966
967impl ParseMetaItem for proc_macro2::TokenStream {
970 #[inline]
971 fn parse_meta_item(input: ParseStream, mode: ParseMode) -> Result<Self> {
972 if input.peek(Token![,]) {
973 return Err(syn::Error::new(input.span(), "unexpected comma"));
974 }
975 input.step(|cursor| {
976 let mut cursor = *cursor;
977 let mut tts = Vec::new();
978 while let Some((tt, rest)) = cursor.token_tree() {
979 match tt {
980 proc_macro2::TokenTree::Punct(p) if p.as_char() == ',' => break,
981 tt => tts.push(tt),
982 }
983 cursor = rest;
984 }
985 if tts.is_empty() {
986 return Err(syn::Error::new(mode.to_span(input), "expected token"));
987 }
988 Ok((tts.into_iter().collect(), cursor))
989 })
990 }
991 #[inline]
992 fn parse_meta_item_flag(_: Span) -> Result<Self> {
993 Ok(Default::default())
994 }
995 #[inline]
996 fn missing_meta_item(_name: &str, _span: Span) -> Result<Self> {
997 Ok(Default::default())
998 }
999}
1000
1001impl ParseMetaFlatUnnamed for proc_macro2::TokenStream {
1002 #[inline]
1003 fn field_count() -> Option<usize> {
1004 None
1005 }
1006 fn parse_meta_flat_unnamed<'s, S: Borrow<ParseBuffer<'s>>>(
1007 inputs: &[S],
1008 _mode: ParseMode,
1009 _index: usize,
1010 ) -> Result<Self> {
1011 let mut tts = Self::new();
1012 for input in inputs {
1013 let input = input.borrow();
1014 loop {
1015 if input.is_empty() {
1016 break;
1017 }
1018 tts.extend(Self::parse_meta_item(input, ParseMode::Unnamed)?);
1019 }
1020 }
1021 Ok(tts)
1022 }
1023}
1024
1025impl_fmt_key_string_display!(proc_macro2::TokenStream);
1026
1027impl ParseMetaItem for proc_macro2::Literal {
1028 #[inline]
1029 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1030 input.step(|cursor| {
1031 cursor
1032 .literal()
1033 .ok_or_else(|| crate::Error::new(cursor.span(), "expected literal"))
1034 })
1035 }
1036}
1037
1038impl_fmt_key_string_display!(proc_macro2::Literal);
1039
1040impl ParseMetaItem for proc_macro2::Punct {
1041 #[inline]
1042 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1043 input.step(|cursor| {
1044 cursor
1045 .punct()
1046 .ok_or_else(|| crate::Error::new(cursor.span(), "expected punctuation"))
1047 })
1048 }
1049}
1050
1051impl_fmt_key_string_display!(proc_macro2::Punct);
1052
1053impl ParseMetaItem for proc_macro2::Group {
1054 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1055 input.step(|cursor| {
1056 for delim in {
1057 use proc_macro2::Delimiter::*;
1058 [Parenthesis, Brace, Bracket, None]
1059 } {
1060 if let Some((group, _, cursor)) = cursor.group(delim) {
1061 return Ok((proc_macro2::Group::new(delim, group.token_stream()), cursor));
1062 }
1063 }
1064 Err(crate::Error::new(
1065 cursor.span(),
1066 "expected parenthesis or brace or bracket",
1067 ))
1068 })
1069 }
1070}
1071
1072#[cfg(feature = "proc-macro")]
1073#[inline]
1074fn convert_token_tree(tt: proc_macro2::TokenTree) -> syn::Result<proc_macro::TokenTree> {
1075 #[inline]
1076 fn convert_delimiter(d: proc_macro2::Delimiter) -> proc_macro::Delimiter {
1077 match d {
1078 proc_macro2::Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis,
1079 proc_macro2::Delimiter::Brace => proc_macro::Delimiter::Brace,
1080 proc_macro2::Delimiter::Bracket => proc_macro::Delimiter::Bracket,
1081 proc_macro2::Delimiter::None => proc_macro::Delimiter::None,
1082 }
1083 }
1084 #[inline]
1085 fn convert_spacing(s: proc_macro2::Spacing) -> proc_macro::Spacing {
1086 match s {
1087 proc_macro2::Spacing::Alone => proc_macro::Spacing::Alone,
1088 proc_macro2::Spacing::Joint => proc_macro::Spacing::Joint,
1089 }
1090 }
1091 Ok(match tt {
1092 proc_macro2::TokenTree::Group(g) => {
1093 proc_macro::Group::new(convert_delimiter(g.delimiter()), g.stream().into()).into()
1094 }
1095 proc_macro2::TokenTree::Ident(i) => {
1096 proc_macro::Ident::new(&i.to_string(), i.span().unwrap()).into()
1097 }
1098 proc_macro2::TokenTree::Punct(p) => {
1099 proc_macro::Punct::new(p.as_char(), convert_spacing(p.spacing())).into()
1100 }
1101 proc_macro2::TokenTree::Literal(l) => l
1102 .to_string()
1103 .parse::<proc_macro::Literal>()
1104 .map(|mut pl| {
1105 pl.set_span(l.span().unwrap());
1106 pl
1107 })
1108 .map_err(|e| syn::Error::new(l.span(), e))?
1109 .into(),
1110 })
1111}
1112
1113#[cfg(feature = "proc-macro")]
1114#[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))]
1115impl ParseMetaItem for proc_macro::TokenTree {
1116 #[inline]
1117 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1118 convert_token_tree(input.parse::<proc_macro2::TokenTree>()?)
1119 }
1120}
1121
1122impl_fmt_key_string_display!(proc_macro::TokenTree, #proc_macro);
1123
1124#[cfg(feature = "proc-macro")]
1125#[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))]
1126impl ParseMetaItem for proc_macro::TokenStream {
1127 #[inline]
1128 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1129 Ok(input.parse::<proc_macro2::TokenStream>()?.into())
1130 }
1131}
1132
1133impl_fmt_key_string_display!(proc_macro::TokenStream, #proc_macro);
1134
1135#[cfg(feature = "proc-macro")]
1136#[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))]
1137impl ParseMetaItem for proc_macro::Literal {
1138 #[inline]
1139 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1140 match convert_token_tree(proc_macro2::TokenTree::Literal(input.parse()?))? {
1141 proc_macro::TokenTree::Literal(l) => Ok(l),
1142 _ => unreachable!(),
1143 }
1144 }
1145}
1146
1147impl_fmt_key_string_display!(proc_macro::Literal, #proc_macro);
1148
1149#[cfg(feature = "proc-macro")]
1150#[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))]
1151impl ParseMetaItem for proc_macro::Punct {
1152 #[inline]
1153 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1154 match convert_token_tree(proc_macro2::TokenTree::Punct(input.parse()?))? {
1155 proc_macro::TokenTree::Punct(p) => Ok(p),
1156 _ => unreachable!(),
1157 }
1158 }
1159}
1160
1161impl_fmt_key_string_display!(proc_macro::Punct, #proc_macro);
1162
1163#[cfg(feature = "proc-macro")]
1164#[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))]
1165impl ParseMetaItem for proc_macro::Group {
1166 #[inline]
1167 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1168 match convert_token_tree(proc_macro2::TokenTree::Group(input.parse()?))? {
1169 proc_macro::TokenTree::Group(g) => Ok(g),
1170 _ => unreachable!(),
1171 }
1172 }
1173}
1174
1175impl_fmt_key_string_display!(proc_macro::Group, #proc_macro);
1176
1177#[cfg(feature = "proc-macro")]
1178#[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))]
1179impl ParseMetaItem for proc_macro::Ident {
1180 #[inline]
1181 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1182 match convert_token_tree(proc_macro2::TokenTree::Ident(input.parse()?))? {
1183 proc_macro::TokenTree::Ident(i) => Ok(i),
1184 _ => unreachable!(),
1185 }
1186 }
1187}
1188
1189impl_fmt_key_string_display!(proc_macro::Ident, #proc_macro);
1190
1191impl<T: ParseMetaItem, P: Parse + Peek + Default> ParseMetaItem for Punctuated<T, P> {
1192 #[inline]
1193 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1194 Bracket::parse_delimited_meta_item(input, ParseMode::Unnamed)
1195 }
1196 #[inline]
1197 fn parse_meta_item_inline<'s, S: Borrow<ParseBuffer<'s>>>(
1198 inputs: &[S],
1199 _mode: ParseMode,
1200 ) -> Result<Self> {
1201 Self::parse_meta_flat_unnamed(inputs, _mode, 0)
1202 }
1203}
1204
1205impl<T: ParseMetaItem, P: Parse + Peek + Default> ParseMetaFlatUnnamed for Punctuated<T, P> {
1206 #[inline]
1207 fn field_count() -> Option<usize> {
1208 None
1209 }
1210 fn parse_meta_flat_unnamed<'s, S: Borrow<ParseBuffer<'s>>>(
1211 inputs: &[S],
1212 _mode: ParseMode,
1213 _index: usize,
1214 ) -> Result<Self> {
1215 let mut p = Punctuated::new();
1216 let errors = Errors::new();
1217 for input in inputs {
1218 let input = input.borrow();
1219 loop {
1220 if input.is_empty() {
1221 break;
1222 }
1223 match errors.push_result(T::parse_meta_item(input, ParseMode::Unnamed)) {
1224 Some(v) => {
1225 p.push(v);
1226 if !input.is_empty() && errors.push_result(input.parse::<P>()).is_some() {
1227 break;
1228 }
1229 }
1230 None => {
1231 while !input.is_empty() {
1233 if input.peek(P::default()) {
1234 input.parse::<P>()?;
1235 break;
1236 }
1237 input.step(|c| Ok(((), c.token_tree().map(|(_, c)| c).unwrap())))?;
1238 }
1239 }
1240 }
1241 }
1242 }
1243 errors.check()?;
1244 Ok(p)
1245 }
1246}
1247
1248impl<T: ToKeyString, P: ToTokens> ToKeyString for Punctuated<T, P> {
1249 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
1250 f.write_char('[')?;
1251 for p in self.pairs() {
1252 match p {
1253 syn::punctuated::Pair::Punctuated(t, p) => {
1254 t.fmt_key_string(f)?;
1255 p.to_token_stream().fmt_key_string(f)?;
1256 f.write_char(' ')?;
1257 }
1258 syn::punctuated::Pair::End(t) => t.fmt_key_string(f)?,
1259 }
1260 }
1261 f.write_char(']')
1262 }
1263}
1264
1265macro_rules! impl_parse_meta_item_syn {
1266 ($(#[$attr:meta])* $ty:ty) => {
1267 $(#[$attr])*
1268 impl ParseMetaItem for $ty {
1269 #[inline]
1270 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1271 input.parse()
1272 }
1273 }
1274 $(#[$attr])*
1275 impl ToKeyString for $ty {
1276 #[inline]
1277 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
1278 self.to_token_stream().fmt_key_string(f)
1279 }
1280 }
1281 };
1282 ($ty:ty, #full) => {
1283 impl_parse_meta_item_syn!(
1284 #[cfg(feature = "full")]
1285 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
1286 $ty
1287 );
1288 };
1289}
1290
1291macro_rules! impl_parse_meta_paren_item_syn {
1292 ($(#[$attr:meta])* $ty:ty) => {
1293 $(#[$attr])*
1294 impl ParseMetaItem for $ty {
1295 #[inline]
1296 fn parse_meta_item(input: ParseStream, mode: ParseMode) -> Result<Self> {
1297 match mode {
1298 ParseMode::Named(_) => {
1299 let content = Paren::parse_delimited(input)?;
1300 let ret = content.parse()?;
1301 content.parse::<Nothing>()?;
1302 Ok(ret)
1303 }
1304 ParseMode::Unnamed => Ok(input.parse()?),
1305 }
1306 }
1307 }
1308 $(#[$attr])*
1309 impl ToKeyString for $ty {
1310 #[inline]
1311 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
1312 self.to_token_stream().fmt_key_string(f)
1313 }
1314 }
1315 };
1316 ($ty:ty, #full) => {
1317 impl_parse_meta_paren_item_syn!(
1318 #[cfg(feature = "full")]
1319 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
1320 $ty
1321 );
1322 };
1323}
1324
1325impl_parse_meta_item_syn!(syn::AngleBracketedGenericArguments);
1326impl_parse_meta_item_syn!(syn::BareFnArg);
1327impl_parse_meta_item_syn!(syn::BoundLifetimes);
1328impl_parse_meta_item_syn!(syn::BinOp);
1329impl_parse_meta_item_syn!(syn::Expr, #full);
1330impl_parse_meta_item_syn!(syn::ExprArray, #full);
1331impl_parse_meta_paren_item_syn!(syn::ExprAssign, #full);
1332impl_parse_meta_item_syn!(syn::ExprCall, #full);
1333impl_parse_meta_item_syn!(syn::ExprCast, #full);
1334impl_parse_meta_item_syn!(syn::ExprField, #full);
1335impl_parse_meta_item_syn!(syn::ExprIndex, #full);
1336impl_parse_meta_item_syn!(syn::ExprLit, #full);
1337impl_parse_meta_item_syn!(syn::ExprMethodCall, #full);
1338impl_parse_meta_item_syn!(syn::ExprParen, #full);
1339impl_parse_meta_item_syn!(syn::ExprPath, #full);
1340impl_parse_meta_item_syn!(syn::ExprRange, #full);
1341impl_parse_meta_item_syn!(syn::ExprRepeat, #full);
1342impl_parse_meta_item_syn!(syn::ExprTuple, #full);
1343impl_parse_meta_item_syn!(syn::FnArg, #full);
1344impl_parse_meta_item_syn!(syn::GenericParam);
1345impl ParseMetaItem for syn::Ident {
1346 #[inline]
1347 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1348 syn::ext::IdentExt::parse_any(input)
1349 }
1350}
1351impl ToKeyString for syn::Ident {
1352 #[inline]
1353 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
1354 fmt::Display::fmt(self, f)
1355 }
1356}
1357impl_parse_meta_item_syn!(syn::Lifetime);
1358impl_parse_meta_item_syn!(syn::LifetimeParam);
1359impl_parse_meta_item_syn!(syn::Lit);
1360impl_parse_meta_item_syn!(syn::LitStr);
1361impl_parse_meta_item_syn!(syn::LitByteStr);
1362impl_parse_meta_item_syn!(syn::LitByte);
1363impl_parse_meta_item_syn!(syn::LitChar);
1364impl_parse_meta_item_syn!(syn::LitInt);
1365impl_parse_meta_item_syn!(syn::LitFloat);
1366impl_parse_meta_item_syn!(syn::LitBool);
1367impl_parse_meta_item_syn!(syn::MetaList);
1368impl_parse_meta_paren_item_syn!(syn::Meta);
1369impl_parse_meta_paren_item_syn!(syn::MetaNameValue);
1370#[cfg(feature = "full")]
1371#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
1372impl ParseMetaItem for syn::Pat {
1373 #[inline]
1374 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1375 syn::Pat::parse_single(input)
1376 }
1377}
1378#[cfg(feature = "full")]
1379#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
1380impl ToKeyString for syn::Pat {
1381 #[inline]
1382 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
1383 self.to_token_stream().fmt_key_string(f)
1384 }
1385}
1386impl ParseMetaItem for syn::Path {
1387 #[inline]
1388 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1389 input.parse()
1390 }
1391}
1392impl ToKeyString for syn::Path {
1393 #[inline]
1394 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
1395 for (i, seg) in self.segments.iter().enumerate() {
1396 if i > 0 {
1397 f.write_str("::")?;
1398 }
1399 seg.ident.fmt_key_string(f)?;
1400 if !seg.arguments.is_empty() {
1401 seg.arguments.to_token_stream().fmt_key_string(f)?;
1402 }
1403 }
1404 Ok(())
1405 }
1406}
1407impl_parse_meta_item_syn!(syn::PathSegment);
1408impl_parse_meta_item_syn!(syn::ParenthesizedGenericArguments);
1409impl_parse_meta_item_syn!(syn::Receiver, #full);
1410impl_parse_meta_item_syn!(syn::Signature, #full);
1411impl_parse_meta_item_syn!(syn::TraitBound);
1412impl_parse_meta_item_syn!(syn::Type);
1413impl_parse_meta_item_syn!(syn::TypeArray);
1414impl_parse_meta_item_syn!(syn::TypeBareFn);
1415impl_parse_meta_item_syn!(syn::TypeImplTrait);
1416impl_parse_meta_item_syn!(syn::TypePath);
1417impl_parse_meta_item_syn!(syn::TypePtr);
1418impl_parse_meta_item_syn!(syn::TypeReference);
1419impl_parse_meta_item_syn!(syn::TypeSlice);
1420impl_parse_meta_item_syn!(syn::TypeTraitObject);
1421impl_parse_meta_item_syn!(syn::TypeTuple);
1422impl_parse_meta_item_syn!(syn::TypeParamBound);
1423impl_parse_meta_item_syn!(syn::UseTree, #full);
1424impl_parse_meta_item_syn!(syn::UnOp);
1425impl_parse_meta_item_syn!(syn::Visibility);
1426impl_parse_meta_item_syn!(syn::WherePredicate);
1427
1428impl ParseMetaItem for () {
1429 #[inline]
1430 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1431 let content = Paren::parse_delimited(input)?;
1432 content.parse::<Nothing>()?;
1433 Ok(())
1434 }
1435 #[inline]
1436 fn parse_meta_item_inline<'s, S: Borrow<ParseBuffer<'s>>>(
1437 inputs: &[S],
1438 _mode: ParseMode,
1439 ) -> Result<Self> {
1440 for input in inputs {
1441 input.borrow().parse::<Nothing>()?;
1442 }
1443 Ok(())
1444 }
1445 #[inline]
1446 fn parse_meta_item_flag(_: Span) -> Result<Self> {
1447 Ok(())
1448 }
1449}
1450
1451impl ToKeyString for () {
1452 #[inline]
1453 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
1454 f.write_str("()")
1455 }
1456 #[inline]
1457 fn with_key_string<R>(&self, f: impl FnOnce(&str) -> R) -> R {
1458 f("()")
1459 }
1460}
1461
1462macro_rules! impl_parse_meta_item_tuple {
1463 ($len:literal: $($index:tt $param:tt $item:ident)+) => {
1464 impl<$($param: ParseMetaItem,)+> ParseMetaItem for ($($param,)+) {
1465 #[inline]
1466 fn parse_meta_item(input: ParseStream, _mode: ParseMode) -> Result<Self> {
1467 Paren::parse_delimited_meta_item(input, ParseMode::Unnamed)
1468 }
1469 #[inline]
1470 fn parse_meta_item_inline<'s, S: Borrow<ParseBuffer<'s>>>(inputs: &[S], _mode: ParseMode) -> Result<Self> {
1471 Self::parse_meta_flat_unnamed(inputs, _mode, 0)
1472 }
1473 }
1474
1475 impl<$($param: ParseMetaItem,)+> ParseMetaFlatUnnamed for ($($param,)+) {
1476 #[inline]
1477 fn field_count() -> Option<usize> {
1478 Some($len)
1479 }
1480 fn parse_meta_flat_unnamed<'s, S: Borrow<ParseBuffer<'s>>>(
1481 inputs: &[S],
1482 _mode: ParseMode,
1483 _index: usize
1484 ) -> Result<Self> {
1485 $(let mut $item = FieldStatus::None;)+
1486 let errors = Errors::new();
1487 errors.push_result(parse_tuple_struct(inputs, $len, |stream, _, index| {
1488 match index {
1489 $($index => $item.parse_unnamed_item(stream, &errors),)+
1490 _ => unreachable!(),
1491 }
1492 Ok(())
1493 }));
1494 $(if $item.is_none() {
1495 errors.push(
1496 inputs_span(inputs),
1497 format!("Expected tuple of length {}, got {}", $len, $index),
1498 );
1499 return errors.bail();
1500 };)+
1501 errors.check()?;
1502 $(let $item = $item.unwrap_or_else(|| unreachable!());)+
1503 Ok(($($item,)+))
1504 }
1505 }
1506
1507 impl<$($param: ToKeyString,)+> ToKeyString for ($($param,)+) {
1508 #[inline]
1509 fn fmt_key_string(&self, f: &mut fmt::Formatter) -> fmt::Result {
1510 f.write_char('(')?;
1511
1512 $(
1513 impl_parse_meta_item_tuple!(@push_comma f, $index);
1514 self.$index.fmt_key_string(f)?;
1515 )+
1516 f.write_char(')')
1517 }
1518 }
1519 };
1520 (@push_comma $f:ident, 0) => { };
1521 (@push_comma $f:ident, $index:literal) => { $f.write_str(", ")?; };
1522}
1523
1524impl_parse_meta_item_tuple!(1: 0 T0 t0);
1525impl_parse_meta_item_tuple!(2: 0 T0 t0 1 T1 t1);
1526impl_parse_meta_item_tuple!(3: 0 T0 t0 1 T1 t1 2 T2 t2);
1527impl_parse_meta_item_tuple!(4: 0 T0 t0 1 T1 t1 2 T2 t2 3 T3 t3);
1528impl_parse_meta_item_tuple!(5: 0 T0 t0 1 T1 t1 2 T2 t2 3 T3 t3 4 T4 t4);
1529impl_parse_meta_item_tuple!(6: 0 T0 t0 1 T1 t1 2 T2 t2 3 T3 t3 4 T4 t4 5 T5 t5);
1530impl_parse_meta_item_tuple!(7: 0 T0 t0 1 T1 t1 2 T2 t2 3 T3 t3 4 T4 t4 5 T5 t5 6 T6 t6);
1531impl_parse_meta_item_tuple!(8: 0 T0 t0 1 T1 t1 2 T2 t2 3 T3 t3 4 T4 t4 5 T5 t5 6 T6 t6 7 T7 t7);
1532impl_parse_meta_item_tuple!(9: 0 T0 t0 1 T1 t1 2 T2 t2 3 T3 t3 4 T4 t4 5 T5 t5 6 T6 t6 7 T7 t7 8 T8 t8);
1533impl_parse_meta_item_tuple!(10: 0 T0 t0 1 T1 t1 2 T2 t2 3 T3 t3 4 T4 t4 5 T5 t5 6 T6 t6 7 T7 t7 8 T8 t8 9 T9 t9);
1534impl_parse_meta_item_tuple!(11: 0 T0 t0 1 T1 t1 2 T2 t2 3 T3 t3 4 T4 t4 5 T5 t5 6 T6 t6 7 T7 t7 8 T8 t8 9 T9 t9 10 T10 t10);
1535impl_parse_meta_item_tuple!(12: 0 T0 t0 1 T1 t1 2 T2 t2 3 T3 t3 4 T4 t4 5 T5 t5 6 T6 t6 7 T7 t7 8 T8 t8 9 T9 t9 10 T10 t10 11 T11 t11);
1536impl_parse_meta_item_tuple!(13: 0 T0 t0 1 T1 t1 2 T2 t2 3 T3 t3 4 T4 t4 5 T5 t5 6 T6 t6 7 T7 t7 8 T8 t8 9 T9 t9 10 T10 t10 11 T11 t11 12 T12 t12);
1537impl_parse_meta_item_tuple!(14: 0 T0 t0 1 T1 t1 2 T2 t2 3 T3 t3 4 T4 t4 5 T5 t5 6 T6 t6 7 T7 t7 8 T8 t8 9 T9 t9 10 T10 t10 11 T11 t11 12 T12 t12 13 T13 t13);
1538impl_parse_meta_item_tuple!(15: 0 T0 t0 1 T1 t1 2 T2 t2 3 T3 t3 4 T4 t4 5 T5 t5 6 T6 t6 7 T7 t7 8 T8 t8 9 T9 t9 10 T10 t10 11 T11 t11 12 T12 t12 13 T13 t13 14 T14 t14);
1539impl_parse_meta_item_tuple!(16: 0 T0 t0 1 T1 t1 2 T2 t2 3 T3 t3 4 T4 t4 5 T5 t5 6 T6 t6 7 T7 t7 8 T8 t8 9 T9 t9 10 T10 t10 11 T11 t11 12 T12 t12 13 T13 t13 14 T14 t14 15 T15 t15);