1#![deny(warnings)]
11#![doc(test(attr(deny(warnings))))]
12#![doc(test(attr(allow(dead_code))))]
13#![doc(test(attr(allow(unused_variables))))]
14#![doc(test(attr(allow(unused_macros))))]
15
16#![doc=document_features::document_features!()]
21#![cfg_attr(not(feature="std"), no_std)]
47#[cfg(feature="std")]
48extern crate core;
49
50#[doc(hidden)]
51pub use core::compile_error as std_compile_error;
52#[doc(hidden)]
53pub use core::convert::From as std_convert_From;
54#[doc(hidden)]
55pub use core::fmt::Display as std_fmt_Display;
56#[doc(hidden)]
57pub use core::fmt::Formatter as std_fmt_Formatter;
58#[doc(hidden)]
59pub use core::fmt::Result as std_fmt_Result;
60#[doc(hidden)]
61pub use core::iter::ExactSizeIterator as std_iter_ExactSizeIterator;
62#[doc(hidden)]
63pub use core::iter::Iterator as std_iter_Iterator;
64#[doc(hidden)]
65pub use core::mem::replace as std_mem_replace;
66#[doc(hidden)]
67pub use core::option::Option as std_option_Option;
68#[doc(hidden)]
69pub use core::result::Result as std_result_Result;
70#[doc(hidden)]
71pub use core::str::FromStr as std_str_FromStr;
72
73#[doc(hidden)]
74#[macro_export]
75macro_rules! enum_derive_util {
76 (@as_expr $e:expr) => {$e};
77 (@as_item $($i:item)+) => {$($i)+};
78 (@first_expr $head:expr $(, $($($tail:expr),+ $(,)?)?)?) => {$head};
79
80 (
81 @collect_unitary_variants ($callback:path { $($args:tt)* }),
82 ($(,)*) -> ($($var_names:ident,)*)
83 ) => {
84 $crate::enum_derive_util! {
85 @as_item
86 $callback!{ $($args)* ($($var_names),*) }
87 }
88 };
89
90 (
91 @collect_unitary_variants $fixed:tt,
92 (#[$_attr:meta] $($tail:tt)*) -> ($($var_names:tt)*)
93 ) => {
94 $crate::enum_derive_util! {
95 @collect_unitary_variants $fixed,
96 ($($tail)*) -> ($($var_names)*)
97 }
98 };
99
100 (
101 @collect_unitary_variants $fixed:tt,
102 ($var:ident $(= $_val:expr)*, $($tail:tt)*) -> ($($var_names:tt)*)
103 ) => {
104 $crate::enum_derive_util! {
105 @collect_unitary_variants $fixed,
106 ($($tail)*) -> ($($var_names)* $var,)
107 }
108 };
109
110 (
111 @collect_unitary_variants ($name:ident),
112 ($var:ident $_struct:tt, $($tail:tt)*) -> ($($var_names:tt)*)
113 ) => {
114 $crate::std_compile_error!("cannot parse unitary variants from enum with non-unitary variants");
115 };
116
117 (
118 @collect_unary_variants ($callback:path { $($args:tt)* }),
119 ($(,)*) -> ($($out:tt)*)
120 ) => {
121 $crate::enum_derive_util! {
122 @as_item
123 $callback!{ $($args)* ($($out)*) }
124 }
125 };
126
127 (
128 @collect_unary_variants $fixed:tt,
129 (#[$_attr:meta] $($tail:tt)*) -> ($($out:tt)*)
130 ) => {
131 $crate::enum_derive_util! {
132 @collect_unary_variants $fixed,
133 ($($tail)*) -> ($($out)*)
134 }
135 };
136
137 (
138 @collect_unary_variants $fixed:tt,
139 ($var_name:ident($vis:vis $var_ty:ty), $($tail:tt)*) -> ($($out:tt)*)
140 ) => {
141 $crate::enum_derive_util! {
142 @collect_unary_variants $fixed,
143 ($($tail)*) -> ($($out)* $var_name($var_ty),)
144 }
145 };
146
147 (
148 @collect_unary_variants ($name:ident),
149 ($var:ident $_struct:tt, $($tail:tt)*) -> ($($_out:tt)*)
150 ) => {
151 $crate::std_compile_error!("cannot parse unary variants from enum with non-unary tuple variants");
152 };
153}
154
155#[macro_export]
172macro_rules! IterVariants {
173 (($itername:ident) $vis:vis enum $name:ident { $($body:tt)* }) => {
174 $crate::enum_derive_util! {
175 @collect_unitary_variants
176 ($crate::IterVariants_impl { @expand ($vis) $itername, $name }),
177 ($($body)*,) -> ()
178 }
179 };
180 (() $vis:vis enum $name:ident { $($body:tt)* }) => {
181 $crate::std_compile_error!("IterVariants! requires iterator name parameter");
182 };
183}
184
185#[doc(hidden)]
186#[macro_export]
187macro_rules! IterVariants_impl {
188 (
189 @expand ($vis:vis) $itername:ident, $name:ident ()
190 ) => {
191 $crate::enum_derive_util! { @as_item $vis struct $itername; }
192
193 impl $crate::std_iter_Iterator for $itername {
194 type Item = $name;
195 fn next(&mut self) -> $crate::std_option_Option<Self::Item> {
196 None
197 }
198
199 fn size_hint(&self) -> (usize, $crate::std_option_Option<usize>) {
200 (0, Some(0))
201 }
202 }
203
204 impl $crate::std_iter_ExactSizeIterator for $itername { }
205
206 $crate::enum_derive_util! {
207 @as_item
208 impl $name {
209 #[allow(dead_code)]
210 $vis fn iter_variants() -> $itername {
211 $itername
212 }
213 }
214 }
215 };
216
217 (
218 @expand ($vis:vis) $itername:ident, $name:ident ($($var_names:ident),*)
219 ) => {
220 $crate::enum_derive_util! { @as_item $vis struct $itername($crate::std_option_Option<$name>); }
221
222 $crate::IterVariants_impl! { @iter ($itername, $name), ($($var_names,)*) -> () () (0usize) }
223
224 $crate::enum_derive_util! {
225 @as_item
226 impl $name {
227 #[allow(dead_code)]
228 $vis fn iter_variants() -> $itername {
229 $itername($crate::std_option_Option::Some($crate::enum_derive_util!(@first_expr $($name::$var_names),+)))
230 }
231 }
232 }
233 };
234
235 (
236 @iter ($itername:ident, $name:ident), () -> ($($next_body:tt)*) ($($size_body:tt)*) ($($count:tt)*)
237 ) => {
238 $crate::enum_derive_util! {
239 @as_item
240 impl $crate::std_iter_Iterator for $itername {
241 type Item = $name;
242 fn next(&mut self) -> $crate::std_option_Option<Self::Item> {
243 let next_item = match self.0 {
244 $($next_body)*
245 $crate::std_option_Option::None => $crate::std_option_Option::None
246 };
247 $crate::std_mem_replace(&mut self.0, next_item)
248 }
249
250 fn size_hint(&self) -> (usize, $crate::std_option_Option<usize>) {
251 let variants = $($count)*;
252 let progress = match self.0 {
253 $($size_body)*
254 $crate::std_option_Option::None => variants
255 };
256 (variants - progress, $crate::std_option_Option::Some(variants - progress))
257 }
258 }
259
260 impl $crate::std_iter_ExactSizeIterator for $itername { }
261 }
262 };
263
264 (
265 @iter ($itername:ident, $name:ident), ($a:ident, $b:ident, $($rest:tt)*) -> ($($next_body:tt)*) ($($size_body:tt)*) ($($count:tt)*)
266 ) => {
267 $crate::IterVariants_impl! {
268 @iter ($itername, $name), ($b, $($rest)*)
269 -> (
270 $($next_body)*
271 $crate::std_option_Option::Some($name::$a) => $crate::std_option_Option::Some($name::$b),
272 )
273 (
274 $($size_body)*
275 $crate::std_option_Option::Some($name::$a) => $($count)*,
276 )
277 ($($count)* + 1usize)
278 }
279 };
280
281 (
282 @iter ($itername:ident, $name:ident), ($a:ident,) -> ($($next_body:tt)*) ($($size_body:tt)*) ($($count:tt)*)
283 ) => {
284 $crate::IterVariants_impl! {
285 @iter ($itername, $name), ()
286 -> (
287 $($next_body)*
288 $crate::std_option_Option::Some($name::$a) => $crate::std_option_Option::None,
289 )
290 (
291 $($size_body)*
292 $crate::std_option_Option::Some($name::$a) => $($count)*,
293 )
294 ($($count)* + 1usize)
295 }
296 };
297}
298
299#[macro_export]
316macro_rules! IterVariantNames {
317 (($itername:ident) $vis:vis enum $name:ident { $($body:tt)* }) => {
318 $crate::enum_derive_util! {
319 @collect_unitary_variants
320 ($crate::IterVariantNames_impl { @expand ($vis) $itername, $name }),
321 ($($body)*,) -> ()
322 }
323 };
324 (() $vis:vis enum $name:ident { $($body:tt)* }) => {
325 $crate::std_compile_error!("IterVariantNames! requires iterator name parameter");
326 };
327}
328
329#[doc(hidden)]
330#[macro_export]
331macro_rules! IterVariantNames_impl {
332 (
333 @expand ($vis:vis) $itername:ident, $name:ident ()
334 ) => {
335 $crate::enum_derive_util! { @as_item $vis struct $itername; }
336
337 impl $crate::std_iter_Iterator for $itername {
338 type Item = &'static str;
339 fn next(&mut self) -> $crate::std_option_Option<Self::Item> {
340 $crate::std_option_Option::None
341 }
342
343 fn size_hint(&self) -> (usize, $crate::std_option_Option<usize>) {
344 (0, $crate::std_option_Option::Some(0))
345 }
346 }
347
348 impl $crate::std_iter_ExactSizeIterator for $itername { }
349
350 $crate::enum_derive_util! {
351 @as_item
352 impl $name {
353 #[allow(dead_code)]
354 $vis fn iter_variant_names() -> $itername {
355 $itername
356 }
357 }
358 }
359 };
360
361 (
362 @expand ($vis:vis) $itername:ident, $name:ident ($($var_names:ident),*)
363 ) => {
364 $crate::enum_derive_util! { @as_item $vis struct $itername($crate::std_option_Option<$name>); }
365
366 $crate::IterVariantNames_impl! { @iter ($itername, $name), ($($var_names,)*) -> () () (0usize) }
367
368 $crate::enum_derive_util! {
369 @as_item
370 impl $name {
371 #[allow(dead_code)]
372 $vis fn iter_variant_names() -> $itername {
373 $itername($crate::std_option_Option::Some($crate::enum_derive_util!(@first_expr $($name::$var_names),+)))
374 }
375 }
376 }
377 };
378
379 (
380 @iter ($itername:ident, $name:ident), () -> ($($next_body:tt)*) ($($size_body:tt)*) ($($count:tt)*)
381 ) => {
382 $crate::enum_derive_util! {
383 @as_item
384 impl $crate::std_iter_Iterator for $itername {
385 type Item = &'static str;
386 fn next(&mut self) -> $crate::std_option_Option<Self::Item> {
387 let (next_state, result) = match self.0 {
388 $($next_body)*
389 $crate::std_option_Option::None => ($crate::std_option_Option::None, $crate::std_option_Option::None)
390 };
391 self.0 = next_state;
392 result
393 }
394
395 fn size_hint(&self) -> (usize, $crate::std_option_Option<usize>) {
396 let variants = $($count)*;
397 let progress = match self.0 {
398 $($size_body)*
399 None => variants
400 };
401 (variants - progress, $crate::std_option_Option::Some(variants - progress))
402 }
403 }
404
405 impl $crate::std_iter_ExactSizeIterator for $itername { }
406 }
407 };
408
409 (
410 @iter ($itername:ident, $name:ident), ($a:ident, $b:ident, $($rest:tt)*) -> ($($next_body:tt)*) ($($size_body:tt)*) ($($count:tt)*)
411 ) => {
412 $crate::IterVariantNames_impl! {
413 @iter ($itername, $name), ($b, $($rest)*)
414 -> (
415 $($next_body)*
416 $crate::std_option_Option::Some($name::$a)
417 => ($crate::std_option_Option::Some($name::$b), $crate::std_option_Option::Some(stringify!($a))),
418 )
419 (
420 $($size_body)*
421 $crate::std_option_Option::Some($name::$a) => $($count)*,
422 )
423 ($($count)* + 1usize)
424 }
425 };
426
427 (
428 @iter ($itername:ident, $name:ident), ($a:ident,) -> ($($next_body:tt)*) ($($size_body:tt)*) ($($count:tt)*)
429 ) => {
430 $crate::IterVariantNames_impl! {
431 @iter ($itername, $name), ()
432 -> (
433 $($next_body)*
434 $crate::std_option_Option::Some($name::$a)
435 => ($crate::std_option_Option::None, $crate::std_option_Option::Some(stringify!($a))),
436 )
437 (
438 $($size_body)*
439 $crate::std_option_Option::Some($name::$a) => $($count)*,
440 )
441 ($($count)* + 1usize)
442 }
443 };
444}
445
446#[macro_export]
449macro_rules! NextVariant {
450 (() $vis:vis enum $name:ident { $($body:tt)* }) => {
451 $crate::enum_derive_util! {
452 @collect_unitary_variants
453 ($crate::NextVariant_impl { @expand ($vis) $name }),
454 ($($body)*,) -> ()
455 }
456 };
457}
458
459#[doc(hidden)]
460#[macro_export]
461macro_rules! NextVariant_impl {
462 (
463 @expand ($vis:vis) $name:ident ()
464 ) => {
465 $crate::enum_derive_util! {
466 @as_item
467 impl $name {
468 #[allow(dead_code)]
469 $vis fn next_variant(&self) -> $crate::std_option_Option<$name> {
470 loop {} }
472 }
473 }
474 };
475
476 (
477 @expand ($vis:vis) $name:ident ($($var_names:ident),*)
478 ) => {
479 $crate::enum_derive_util! {
480 @as_item
481 impl $name {
482 #[allow(dead_code)]
483 $vis fn next_variant(&self) -> $crate::std_option_Option<$name> {
484 $crate::NextVariant_impl!(@arms ($name, self), ($($var_names)*) -> ())
485 }
486 }
487 }
488 };
489
490 (
491 @arms ($name:ident, $self_:expr), ($a:ident) -> ($($body:tt)*)
492 ) => {
493 $crate::enum_derive_util! {
494 @as_expr
495 match *$self_ {
496 $($body)*
497 $name::$a => $crate::std_option_Option::None
498 }
499 }
500 };
501
502 (
503 @arms ($name:ident, $self_:expr), ($a:ident $b:ident $($rest:tt)*) -> ($($body:tt)*)
504 ) => {
505 $crate::NextVariant_impl! {
506 @arms ($name, $self_), ($b $($rest)*)
507 -> (
508 $($body)*
509 $name::$a => $crate::std_option_Option::Some($name::$b),
510 )
511 }
512 };
513}
514
515#[macro_export]
517macro_rules! PrevVariant {
518 (() $vis:vis enum $name:ident { $($body:tt)* }) => {
519 $crate::enum_derive_util! {
520 @collect_unitary_variants
521 ($crate::PrevVariant_impl { @expand ($vis) $name }),
522 ($($body)*,) -> ()
523 }
524 };
525}
526
527#[doc(hidden)]
528#[macro_export]
529macro_rules! PrevVariant_impl {
530 (
531 @expand ($vis:vis) $name:ident ()
532 ) => {
533 $crate::enum_derive_util! {
534 @as_item
535 impl $name {
536 #[allow(dead_code)]
537 $vis fn prev_variant(&self) -> $crate::std_option_Option<$name> {
538 loop {} }
540 }
541 }
542 };
543
544 (
545 @expand ($vis:vis) $name:ident ($($var_names:ident),*)
546 ) => {
547 $crate::enum_derive_util! {
548 @as_item
549 impl $name {
550 #[allow(dead_code)]
551 $vis fn prev_variant(&self) -> $crate::std_option_Option<$name> {
552 $crate::PrevVariant_impl!(@arms ($name, self), ($crate::std_option_Option::None, $($var_names)*) -> ())
553 }
554 }
555 }
556 };
557
558 (
559 @arms ($name:ident, $self_:expr), ($prev:expr, $a:ident) -> ($($body:tt)*)
560 ) => {
561 $crate::enum_derive_util! {
562 @as_expr
563 match *$self_ {
564 $($body)*
565 $name::$a => $prev
566 }
567 }
568 };
569
570 (
571 @arms ($name:ident, $self_:expr), ($prev:expr, $a:ident $($rest:tt)*) -> ($($body:tt)*)
572 ) => {
573 $crate::PrevVariant_impl! {
574 @arms ($name, $self_), ($crate::std_option_Option::Some($name::$a), $($rest)*)
575 -> (
576 $($body)*
577 $name::$a => $prev,
578 )
579 }
580 };
581}
582
583#[macro_export]
587macro_rules! EnumDisplay {
588 (() $vis:vis enum $name:ident { $($body:tt)* }) => {
589 $crate::enum_derive_util! {
590 @collect_unitary_variants
591 ($crate::EnumDisplay_impl { @expand $name }),
592 ($($body)*,) -> ()
593 }
594 };
595}
596
597#[doc(hidden)]
598#[macro_export]
599macro_rules! EnumDisplay_impl {
600 (
601 @expand $name:ident ()
602 ) => {
603 $crate::enum_derive_util! {
604 @as_item
605 impl $crate::std_fmt_Display for $name {
606 fn fmt(&self, _: &mut $crate::std_fmt_Formatter) -> $crate::std_fmt_Result {
607 loop {} }
609 }
610 }
611 };
612
613 (
614 @expand $name:ident ($($var_names:ident),*)
615 ) => {
616 $crate::enum_derive_util! {
617 @as_item
618 impl $crate::std_fmt_Display for $name {
619 fn fmt(&self, f: &mut $crate::std_fmt_Formatter) -> $crate::std_fmt_Result {
620 $crate::EnumDisplay_impl!(@arms ($name, self, f), ($($var_names)*) -> ())
621 }
622 }
623 }
624 };
625
626 (
627 @arms ($name:ident, $self_:expr, $f:ident), ($a:ident) -> ($($body:tt)*)
628 ) => {
629 $crate::enum_derive_util! {
630 @as_expr
631 match *$self_ {
632 $($body)*
633 $name::$a => write!($f, stringify!($a)),
634 }
635 }
636 };
637
638 (
639 @arms ($name:ident, $self_:expr, $f:ident), ($a:ident $b:ident $($rest:tt)*) -> ($($body:tt)*)
640 ) => {
641 $crate::EnumDisplay_impl! {
642 @arms ($name, $self_, $f), ($b $($rest)*)
643 -> (
644 $($body)*
645 $name::$a => write!($f, stringify!($a)),
646 )
647 }
648 };
649}
650
651#[macro_export]
653macro_rules! EnumFromStr {
654 (() $vis:vis enum $name:ident { $($body:tt)* }) => {
655 $crate::enum_derive_util! {
656 @collect_unitary_variants
657 ($crate::EnumFromStr_impl { @expand ($vis) $name }),
658 ($($body)*,) -> ()
659 }
660 };
661}
662
663#[doc(hidden)]
664#[macro_export]
665macro_rules! EnumFromStr_impl {
666 (
667 @expand ($vis:vis) $name:ident ()
668 ) => {
669 $crate::enum_derive_util! {
670 @as_item
671 impl $crate::std_str_FromStr for $name {
672 type Err = $crate::ParseEnumError;
673
674 fn from_str(_: &str) -> $crate::std_result_Result<Self, Self::Err> {
675 $crate::std_result_Result::Err($crate::ParseEnumError)
676 }
677 }
678 }
679 };
680
681 (
682 @expand ($vis:vis) $name:ident ($($var_names:ident),*)
683 ) => {
684 $crate::enum_derive_util! {
685 @as_item
686 impl $crate::std_str_FromStr for $name {
687 type Err = $crate::ParseEnumError;
688
689 fn from_str(s: &str) -> Result<Self, Self::Err> {
690 $crate::EnumFromStr_impl!(@arms ($name, s), ($($var_names)*) -> ())
691 }
692 }
693 }
694 };
695
696 (
697 @arms ($name:ident, $s:ident), ($a:ident) -> ($($body:tt)*)
698 ) => {
699 $crate::enum_derive_util! {
700 @as_expr
701 match $s {
702 $($body)*
703 stringify!($a) => $crate::std_result_Result::Ok($name::$a),
704 _ => $crate::std_result_Result::Err($crate::ParseEnumError)
705 }
706 }
707 };
708
709 (
710 @arms ($name:ident, $s:ident), ($a:ident $b:ident $($rest:tt)*) -> ($($body:tt)*)
711 ) => {
712 $crate::EnumFromStr_impl! {
713 @arms ($name, $s), ($b $($rest)*)
714 -> (
715 $($body)*
716 stringify!($a) => $crate::std_result_Result::Ok($name::$a),
717 )
718 }
719 };
720}
721
722#[derive(Clone, Debug, Eq, PartialEq)]
724pub struct ParseEnumError;
725
726impl core::fmt::Display for ParseEnumError {
727 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
728 write!(fmt, "provided string did not match any enum variant")
729 }
730}
731
732#[cfg(feature="std")]
733impl std::error::Error for ParseEnumError { }
734
735#[macro_export]
738macro_rules! EnumFromInner {
739 (() $vis:vis enum $name:ident { $($body:tt)* }) => {
740 $crate::enum_derive_util! {
741 @collect_unary_variants
742 ($crate::EnumFromInner_impl { @expand $name }),
743 ($($body)*,) -> ()
744 }
745 };
746}
747
748#[doc(hidden)]
749#[macro_export]
750macro_rules! EnumFromInner_impl {
751 (
752 @expand $name:ident ($($var_names:ident($var_tys:ty),)*)
753 ) => {
754 $(
755 impl $crate::std_convert_From<$var_tys> for $name {
756 fn from(v: $var_tys) -> $name {
757 $name::$var_names(v)
758 }
759 }
760 )*
761 };
762}
763
764#[macro_export]
786macro_rules! EnumInnerAsTrait {
787 ($arg:tt $vis:vis enum $name:ident { $($body:tt)* }) => {
788 $crate::enum_derive_util! {
789 @collect_unary_variants
790 ($crate::EnumInnerAsTrait_impl { @expand $arg, $name, }),
791 ($($body)*,) -> ()
792 }
793 };
794}
795
796#[doc(hidden)]
797#[macro_export]
798macro_rules! EnumInnerAsTrait_impl {
799 (
800 @expand ($vis:vis $fn_name:ident -> &mut $tr:ty), $($tail:tt)*
801 ) => {
802 $crate::EnumInnerAsTrait_impl! { @expand_inner ($vis), $fn_name, (mut), $tr, $($tail)* }
803 };
804
805 (
806 @expand ($vis:vis $fn_name:ident -> &$tr:ty), $($tail:tt)*
807 ) => {
808 $crate::EnumInnerAsTrait_impl! { @expand_inner ($vis), $fn_name, (), $tr, $($tail)* }
809 };
810
811 (
812 @expand ($($t:tt)*), $($tail:tt)*
813 ) => {
814 $crate::std_compile_error!(
815 "invalid EnumInnerAsTrait! parameter, the allowed form is '$vis:vis $fn_name:ident -> & $(mut)? $tr:ty'"
816 );
817 };
818
819 (
820 @expand_inner
821 ($vis:vis), $fn_name:ident, (mut), $tr:ty,
822 $ty_name:ident,
823 ($($var_names:ident($_var_tys:ty),)*)
824 ) => {
825 $crate::enum_derive_util! {
826 @as_item
827 impl $ty_name {
828 $vis fn $fn_name(&mut self) -> &mut $tr {
829 match *self {
830 $(
831 $ty_name::$var_names(ref mut v) => v as &mut $tr,
832 )*
833 }
834 }
835 }
836 }
837 };
838
839 (
840 @expand_inner
841 ($vis:vis), $fn_name:ident, (), $tr:ty,
842 $ty_name:ident,
843 ($($var_names:ident($_var_tys:ty),)*)
844 ) => {
845 $crate::enum_derive_util! {
846 @as_item
847 impl $ty_name {
848 $vis fn $fn_name(&self) -> &$tr {
849 match *self {
850 $(
851 $ty_name::$var_names(ref v) => v as &$tr,
852 )*
853 }
854 }
855 }
856 }
857 };
858}