]>
Commit | Line | Data |
---|---|---|
ea8adc8c XL |
1 | /*!\r |
2 | This module provides convenience macros to help with implementing the conversion traits.\r | |
3 | \r | |
4 | # `TryFrom!`\r | |
5 | \r | |
6 | ```ignore\r | |
7 | macro_rules! TryFrom {\r | |
8 | (($target:ty) $enum:item) => { ... };\r | |
9 | }\r | |
10 | ```\r | |
11 | \r | |
12 | This macro attempts to derive an implementation of the [`TryFrom`](../trait.TryFrom.html) trait. Specifically, it supports `enum`s consisting entirely of unitary variants, with or without explicit values. The source type can be any integer type which the variants of the enumeration can be explicitly cast to (*i.e.* using `as`).\r | |
13 | \r | |
14 | If a conversion fails (due to there being no matching variant for the specified integer value `src`), then the conversion returns `Err(Unrepresentable(src))` (see [`Unrepresentable`](../errors/struct.Unrepresentable.html)).\r | |
15 | \r | |
16 | It is compatible with the [`custom_derive!`](https://crates.io/crates/custom_derive) macro.\r | |
17 | \r | |
18 | ## Example\r | |
19 | \r | |
20 | Using `custom_derive!`:\r | |
21 | \r | |
22 | ```\r | |
23 | #[macro_use] extern crate conv;\r | |
24 | #[macro_use] extern crate custom_derive;\r | |
25 | \r | |
26 | custom_derive! {\r | |
27 | #[derive(Debug, PartialEq, TryFrom(i32))]\r | |
28 | enum Colours {\r | |
29 | Red = 0,\r | |
30 | Green = 5,\r | |
31 | Blue\r | |
32 | }\r | |
33 | }\r | |
34 | \r | |
35 | fn main() {\r | |
36 | use conv::{TryFrom, Unrepresentable};\r | |
37 | \r | |
38 | assert_eq!(Colours::try_from(0), Ok(Colours::Red));\r | |
39 | assert_eq!(Colours::try_from(1), Err(Unrepresentable(1)));\r | |
40 | assert_eq!(Colours::try_from(5), Ok(Colours::Green));\r | |
41 | assert_eq!(Colours::try_from(6), Ok(Colours::Blue));\r | |
42 | assert_eq!(Colours::try_from(7), Err(Unrepresentable(7)));\r | |
43 | }\r | |
44 | ```\r | |
45 | \r | |
46 | The above is equivalent to the following:\r | |
47 | \r | |
48 | ```\r | |
49 | #[macro_use] extern crate conv;\r | |
50 | \r | |
51 | #[derive(Debug, PartialEq)]\r | |
52 | enum Colours {\r | |
53 | Red = 0,\r | |
54 | Green = 5,\r | |
55 | Blue\r | |
56 | }\r | |
57 | \r | |
58 | TryFrom! { (i32) enum Colours {\r | |
59 | Red = 0,\r | |
60 | Green = 5,\r | |
61 | Blue\r | |
62 | } }\r | |
63 | # fn main() {}\r | |
64 | ```\r | |
65 | */\r | |
66 | \r | |
67 | /**\r | |
68 | See the documentation for the [`macros`](./macros/index.html#tryfrom!) module for details.\r | |
69 | */\r | |
70 | #[macro_export]\r | |
71 | macro_rules! TryFrom {\r | |
72 | (($prim:ty) $(pub)* enum $name:ident { $($body:tt)* }) => {\r | |
73 | TryFrom! {\r | |
74 | @collect_variants ($name, $prim),\r | |
75 | ($($body)*,) -> ()\r | |
76 | }\r | |
77 | };\r | |
78 | \r | |
79 | (\r | |
80 | @collect_variants ($name:ident, $prim:ty),\r | |
81 | ($(,)*) -> ($($var_names:ident,)*)\r | |
82 | ) => {\r | |
83 | impl $crate::TryFrom<$prim> for $name {\r | |
84 | type Err = $crate::errors::Unrepresentable<$prim>;\r | |
85 | fn try_from(src: $prim) -> Result<$name, Self::Err> {\r | |
86 | $(\r | |
87 | if src == $name::$var_names as $prim {\r | |
88 | return Ok($name::$var_names);\r | |
89 | }\r | |
90 | )*\r | |
91 | Err($crate::errors::Unrepresentable(src))\r | |
92 | }\r | |
93 | }\r | |
94 | };\r | |
95 | \r | |
96 | (\r | |
97 | @collect_variants $fixed:tt,\r | |
98 | (#[$_attr:meta] $($tail:tt)*) -> $var_names:tt\r | |
99 | ) => {\r | |
100 | TryFrom! {\r | |
101 | @skip_meta $fixed,\r | |
102 | ($($tail)*) -> $var_names\r | |
103 | }\r | |
104 | };\r | |
105 | \r | |
106 | (\r | |
107 | @collect_variants $fixed:tt,\r | |
108 | ($var:ident $(= $_val:expr)*, $($tail:tt)*) -> ($($var_names:tt)*)\r | |
109 | ) => {\r | |
110 | TryFrom! {\r | |
111 | @collect_variants $fixed,\r | |
112 | ($($tail)*) -> ($($var_names)* $var,)\r | |
113 | }\r | |
114 | };\r | |
115 | \r | |
116 | (\r | |
117 | @collect_variants ($name:ident),\r | |
118 | ($var:ident $_struct:tt, $($tail:tt)*) -> ($($var_names:tt)*)\r | |
119 | ) => {\r | |
120 | const _error: () = concat!(\r | |
121 | "cannot derive TryFrom for ",\r | |
122 | stringify!($name),\r | |
123 | ", due to non-unitary variant ",\r | |
124 | stringify!($var),\r | |
125 | "."\r | |
126 | );\r | |
127 | };\r | |
128 | \r | |
129 | (\r | |
130 | @skip_meta $fixed:tt,\r | |
131 | (#[$_attr:meta] $($tail:tt)*) -> $var_names:tt\r | |
132 | ) => {\r | |
133 | TryFrom! {\r | |
134 | @skip_meta $fixed,\r | |
135 | ($($tail)*) -> $var_names\r | |
136 | }\r | |
137 | };\r | |
138 | \r | |
139 | (\r | |
140 | @skip_meta $fixed:tt,\r | |
141 | ($var:ident $($tail:tt)*) -> $var_names:tt\r | |
142 | ) => {\r | |
143 | TryFrom! {\r | |
144 | @collect_variants $fixed,\r | |
145 | ($var $($tail)*) -> $var_names\r | |
146 | }\r | |
147 | };\r | |
148 | }\r |