sum/
lib.rs

1//! General-purpose sum types.
2//!
3//! <p style="font-family: 'Fira Sans',sans-serif;padding:0.3em 0"><strong>
4//! <a href="https://crates.io/crates/sum">📦&nbsp;&nbsp;Crates.io</a>&nbsp;&nbsp;│&nbsp;&nbsp;<a href="https://github.com/alecmocatta/sum">📑&nbsp;&nbsp;GitHub</a>&nbsp;&nbsp;│&nbsp;&nbsp;<a href="https://constellation.zulipchat.com/#narrow/stream/213236-subprojects">💬&nbsp;&nbsp;Chat</a>
5//! </strong></p>
6//!
7//! Arbitrarily-sized product types exist in Rust in the form of [tuples](https://doc.rust-lang.org/std/primitive.tuple.html). This is a generalisation of bluss's [Either](https://docs.rs/either/1.5.0/either/enum.Either.html) type to provide **arbitrarily-sized sum types**\*.
8//!
9//! \* Over up to 32 types.
10
11#![doc(html_root_url = "https://docs.rs/sum/0.1.7")]
12#![warn(
13	missing_copy_implementations,
14	missing_debug_implementations,
15	// missing_docs,
16	trivial_casts,
17	trivial_numeric_casts,
18	unused_import_braces,
19	unused_qualifications,
20	unused_results,
21	clippy::pedantic
22)] // from https://github.com/rust-unofficial/patterns/blob/master/anti_patterns/deny-warnings.md
23#![allow(unused_variables, unreachable_patterns)]
24#![allow(
25	clippy::empty_enum,
26	clippy::type_complexity,
27	clippy::wrong_self_convention,
28	clippy::must_use_candidate,
29	clippy::unsafe_derive_deserialize,
30	clippy::match_wildcard_for_single_variants
31)]
32
33#[cfg(feature = "futures")]
34use futures_core::stream::Stream;
35#[cfg(feature = "serde")]
36use serde::{Deserialize, Serialize};
37use std::{
38	error::Error, fmt::{Display, Formatter, Result}, future::Future, hint::unreachable_unchecked, ops::{Deref, DerefMut}, pin::Pin, task::{Context, Poll}
39};
40
41macro_rules! impl_sum {
42	(@into_inner $name:ident : $($t:ident)* : !) => (
43		impl $name {
44			pub fn into_inner(self) -> ! {
45				match self { }
46			}
47		}
48	);
49	(@into_inner $name:ident : $($t:ident)* : $first_a:ident $($a:ident)*) => (
50		impl<$first_a> $name<$first_a, $($a,)*> {
51			pub fn into_inner(self) -> $first_a {
52				match self {
53					$($name::$t(inner) => inner,)*
54				}
55			}
56		}
57	);
58	($name:ident : $($t:ident $is:ident $map:ident $get:ident)* : $first_a:tt $($a:ident)* ) => (
59		#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
60		#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
61		pub enum $name<$($t,)*> {
62			$($t($t),)*
63		}
64		impl<$($t,)*> $name<$($t,)*> {
65			$(
66			pub fn $is(&self) -> bool {
67				match *self {
68					$name::$t(_) => true,
69					_ => false
70				}
71			}
72			// TODO
73			// pub fn $map<F,O>(self, f: F) -> $name<$(&$t,)*> where F: FnOnce($t)->O {
74			// 	match self {
75			// 		$name::$t(a) => $name::$t(f(a)),
76			// 		$($name::$t(inner) => inner,)*
77			// 	}
78			// }
79			pub fn $get(self) -> Option<$t> {
80				match self {
81					$name::$t(a) => Some(a),
82					_ => None
83				}
84			}
85			)*
86			pub fn as_ref(&self) -> $name<$(&$t,)*> {
87				match *self {
88					$($name::$t(ref a) => $name::$t(a),)*
89				}
90			}
91			pub fn as_mut(&mut self) -> $name<$(&mut $t,)*> {
92				match *self {
93					$($name::$t(ref mut a) => $name::$t(a),)*
94				}
95			}
96			pub fn as_pin_ref<'a>(self: Pin<&'a Self>) -> $name<$(Pin<&'a $t>,)*> {
97				unsafe {
98					match self.get_ref() {
99						$($name::$t(a) => $name::$t(Pin::new_unchecked(a)),)*
100						_ => unreachable_unchecked(),
101					}
102				}
103			}
104			pub fn as_pin_mut<'a>(self: Pin<&'a mut Self>) -> $name<$(Pin<&'a mut $t>,)*> {
105				unsafe {
106					match self.get_unchecked_mut() {
107						$($name::$t(a) => $name::$t(Pin::new_unchecked(a)),)*
108						_ => unreachable_unchecked(),
109					}
110				}
111			}
112		}
113		impl_sum!(@into_inner $name : $($t)* : $first_a $($a)*);
114		impl<$($t,)* Target> AsRef<Target> for $name<$($t,)*>
115		where
116			$($t: AsRef<Target>,)*
117		{
118			fn as_ref(&self) -> &Target {
119				match *self {
120					$($name::$t(ref inner) => inner.as_ref(),)*
121				}
122			}
123		}
124		impl<$($t,)* Target> AsMut<Target> for $name<$($t,)*>
125		where
126			$($t: AsMut<Target>,)*
127		{
128			fn as_mut(&mut self) -> &mut Target {
129				match *self {
130					$($name::$t(ref mut inner) => inner.as_mut(),)*
131				}
132			}
133		}
134		impl<$($t,)*> Error for $name<$($t,)*>
135		where
136			$($t: Error,)*
137		{
138			#[allow(deprecated)]
139			fn description(&self) -> &str {
140				match *self {
141					$($name::$t(ref inner) => inner.description(),)*
142				}
143			}
144			#[allow(deprecated)]
145			fn cause(&self) -> Option<&dyn Error> {
146				match *self {
147					$($name::$t(ref inner) => inner.cause(),)*
148				}
149			}
150			fn source(&self) -> Option<&(dyn Error + 'static)> {
151				match *self {
152					$($name::$t(ref inner) => inner.source(),)*
153				}
154			}
155		}
156		impl<$($t,)*> Display for $name<$($t,)*>
157		where
158			$($t: Display,)*
159		{
160			fn fmt(&self, f: &mut Formatter) -> Result {
161				match *self {
162					$($name::$t(ref inner) => inner.fmt(f),)*
163				}
164			}
165		}
166		impl_sum!(@multi $name : $($t $is $map $get)* : $first_a $($a)*);
167	);
168	(@multi $name:ident : : $first_a:tt $($a:ident)* ) => ();
169	(@multi $name:ident : $first_t:ident $first_is:ident $first_map:ident $first_get:ident $($t:ident $is:ident $map:ident $get:ident)* : $first_a:tt $($a:ident)* ) => (
170		impl<$first_t, $($t,)*> Deref for $name<$first_t, $($t,)*>
171		where
172			$first_t: Deref,
173			$($t: Deref<Target = $first_t::Target>,)*
174		{
175			type Target = $first_t::Target;
176			fn deref(&self) -> &Self::Target {
177				match *self {
178					$name::$first_t(ref inner) => &*inner,
179					$($name::$t(ref inner) => &*inner,)*
180				}
181			}
182		}
183		impl<$first_t, $($t,)*> DerefMut for $name<$first_t, $($t,)*>
184		where
185			$first_t: DerefMut,
186			$($t: DerefMut<Target = $first_t::Target>,)*
187		{
188			fn deref_mut(&mut self) -> &mut Self::Target {
189				match *self {
190					$name::$first_t(ref mut inner) => &mut *inner,
191					$($name::$t(ref mut inner) => &mut *inner,)*
192				}
193			}
194		}
195
196		impl<$first_t, $($t,)*> Iterator for $name<$first_t, $($t,)*>
197		where
198			$first_t: Iterator,
199			$($t: Iterator<Item = $first_t::Item>,)*
200		{
201			type Item = <$first_t>::Item;
202
203			fn next(&mut self) -> Option<Self::Item> {
204				match *self {
205					$name::$first_t(ref mut inner) => inner.next(),
206					$($name::$t(ref mut inner) => inner.next(),)*
207				}
208			}
209			fn size_hint(&self) -> (usize, Option<usize>) {
210				match *self {
211					$name::$first_t(ref inner) => inner.size_hint(),
212					$($name::$t(ref inner) => inner.size_hint(),)*
213				}
214			}
215		}
216		impl<$first_t, $($t,)*> DoubleEndedIterator for $name<$first_t, $($t,)*>
217		where
218			$first_t: DoubleEndedIterator,
219			$($t: DoubleEndedIterator<Item = $first_t::Item>,)*
220		{
221			fn next_back(&mut self) -> Option<Self::Item> {
222				match *self {
223					$name::$first_t(ref mut inner) => inner.next_back(),
224					$($name::$t(ref mut inner) => inner.next_back(),)*
225				}
226			}
227		}
228		impl<$first_t, $($t,)*> ExactSizeIterator for $name<$first_t, $($t,)*>
229		where
230			$first_t: ExactSizeIterator,
231			$($t: ExactSizeIterator<Item = $first_t::Item>,)*
232		{
233			fn len(&self) -> usize {
234				match *self {
235					$name::$first_t(ref inner) => inner.len(),
236					$($name::$t(ref inner) => inner.len(),)*
237				}
238			}
239		}
240
241		impl<$first_t, $($t,)*> Future for $name<$first_t, $($t,)*>
242		where
243			$first_t: Future,
244			$($t: Future<Output = $first_t::Output>,)*
245		{
246			type Output = <$first_t>::Output;
247
248			fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
249				match self.as_pin_mut() {
250					$name::$first_t(inner) => inner.poll(cx),
251					$($name::$t(inner) => inner.poll(cx),)*
252				}
253			}
254		}
255		#[cfg(feature = "futures")]
256		impl<$first_t, $($t,)*> Stream for $name<$first_t, $($t,)*>
257		where
258			$first_t: Stream,
259			$($t: Stream<Item = $first_t::Item>,)*
260		{
261			type Item = <$first_t>::Item;
262
263			fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
264				match self.as_pin_mut() {
265					$name::$first_t(inner) => inner.poll_next(cx),
266					$($name::$t(inner) => inner.poll_next(cx),)*
267				}
268			}
269		}
270	);
271}
272
273// TODO: impl_sum!(A Sum1 B Sum2 C Sum3 D Sum4 E Sum5 F Sum6);
274#[cfg(feature = "0")]
275impl_sum!(Sum0: : !);
276#[cfg(feature = "1")]
277impl_sum!(Sum1: A is_a map_a a: A);
278#[cfg(feature = "2")]
279impl_sum!(Sum2: A is_a map_a a B is_b map_b b: A A);
280#[cfg(feature = "3")]
281impl_sum!(Sum3: A is_a map_a a B is_b map_b b C is_c map_c c: A A A);
282#[cfg(feature = "4")]
283impl_sum!(Sum4: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d: A A A A);
284#[cfg(feature = "5")]
285impl_sum!(Sum5: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e: A A A A A);
286#[cfg(feature = "6")]
287impl_sum!(Sum6: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f: A A A A A A);
288#[cfg(feature = "7")]
289impl_sum!(Sum7: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g: A A A A A A A);
290#[cfg(feature = "8")]
291impl_sum!(Sum8: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h: A A A A A A A A);
292#[cfg(feature = "9")]
293impl_sum!(Sum9: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i: A A A A A A A A A);
294#[cfg(feature = "10")]
295impl_sum!(Sum10: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j: A A A A A A A A A A);
296#[cfg(feature = "11")]
297impl_sum!(Sum11: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k: A A A A A A A A A A A);
298#[cfg(feature = "12")]
299impl_sum!(Sum12: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l: A A A A A A A A A A A A);
300#[cfg(feature = "13")]
301impl_sum!(Sum13: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m: A A A A A A A A A A A A A);
302#[cfg(feature = "14")]
303impl_sum!(Sum14: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n: A A A A A A A A A A A A A A);
304#[cfg(feature = "15")]
305impl_sum!(Sum15: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o: A A A A A A A A A A A A A A A);
306#[cfg(feature = "16")]
307impl_sum!(Sum16: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p: A A A A A A A A A A A A A A A A);
308#[cfg(feature = "17")]
309impl_sum!(Sum17: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q: A A A A A A A A A A A A A A A A A);
310#[cfg(feature = "18")]
311impl_sum!(Sum18: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r: A A A A A A A A A A A A A A A A A A);
312#[cfg(feature = "19")]
313impl_sum!(Sum19: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s: A A A A A A A A A A A A A A A A A A A);
314#[cfg(feature = "20")]
315impl_sum!(Sum20: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s T is_t map_t t: A A A A A A A A A A A A A A A A A A A A);
316#[cfg(feature = "21")]
317impl_sum!(Sum21: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s T is_t map_t t U is_u map_u u: A A A A A A A A A A A A A A A A A A A A A);
318#[cfg(feature = "22")]
319impl_sum!(Sum22: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s T is_t map_t t U is_u map_u u V is_v map_v v: A A A A A A A A A A A A A A A A A A A A A A);
320#[cfg(feature = "23")]
321impl_sum!(Sum23: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s T is_t map_t t U is_u map_u u V is_v map_v v W is_w map_w w: A A A A A A A A A A A A A A A A A A A A A A A);
322#[cfg(feature = "24")]
323impl_sum!(Sum24: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s T is_t map_t t U is_u map_u u V is_v map_v v W is_w map_w w X is_x map_x x: A A A A A A A A A A A A A A A A A A A A A A A A);
324#[cfg(feature = "25")]
325impl_sum!(Sum25: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s T is_t map_t t U is_u map_u u V is_v map_v v W is_w map_w w X is_x map_x x Y is_y map_y y: A A A A A A A A A A A A A A A A A A A A A A A A A);
326#[cfg(feature = "26")]
327impl_sum!(Sum26: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s T is_t map_t t U is_u map_u u V is_v map_v v W is_w map_w w X is_x map_x x Y is_y map_y y Z is_z map_z z: A A A A A A A A A A A A A A A A A A A A A A A A A A);
328#[cfg(feature = "27")]
329impl_sum!(Sum27: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s T is_t map_t t U is_u map_u u V is_v map_v v W is_w map_w w X is_x map_x x Y is_y map_y y Z is_z map_z z Aa is_aa map_aa aa: A A A A A A A A A A A A A A A A A A A A A A A A A A A);
330#[cfg(feature = "28")]
331impl_sum!(Sum28: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s T is_t map_t t U is_u map_u u V is_v map_v v W is_w map_w w X is_x map_x x Y is_y map_y y Z is_z map_z z Aa is_aa map_aa aa Ab is_ab map_ab ab: A A A A A A A A A A A A A A A A A A A A A A A A A A A A);
332#[cfg(feature = "29")]
333impl_sum!(Sum29: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s T is_t map_t t U is_u map_u u V is_v map_v v W is_w map_w w X is_x map_x x Y is_y map_y y Z is_z map_z z Aa is_aa map_aa aa Ab is_ab map_ab ab Ac is_ac map_ac ac: A A A A A A A A A A A A A A A A A A A A A A A A A A A A A);
334#[cfg(feature = "30")]
335impl_sum!(Sum30: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s T is_t map_t t U is_u map_u u V is_v map_v v W is_w map_w w X is_x map_x x Y is_y map_y y Z is_z map_z z Aa is_aa map_aa aa Ab is_ab map_ab ab Ac is_ac map_ac ac Ad is_ad map_ad ad: A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A);
336#[cfg(feature = "31")]
337impl_sum!(Sum31: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s T is_t map_t t U is_u map_u u V is_v map_v v W is_w map_w w X is_x map_x x Y is_y map_y y Z is_z map_z z Aa is_aa map_aa aa Ab is_ab map_ab ab Ac is_ac map_ac ac Ad is_ad map_ad ad Ae is_ae map_ae ae: A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A);
338#[cfg(feature = "32")]
339impl_sum!(Sum32: A is_a map_a a B is_b map_b b C is_c map_c c D is_d map_d d E is_e map_e e F is_f map_f f G is_g map_g g H is_h map_h h I is_i map_i i J is_j map_j j K is_k map_k k L is_l map_l l M is_m map_m m N is_n map_n n O is_o map_o o P is_p map_p p Q is_q map_q q R is_r map_r r S is_s map_s s T is_t map_t t U is_u map_u u V is_v map_v v W is_w map_w w X is_x map_x x Y is_y map_y y Z is_z map_z z Aa is_aa map_aa aa Ab is_ab map_ab ab Ac is_ac map_ac ac Ad is_ad map_ad ad Ae is_ae map_ae ae Af is_af map_af af: A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A);
340
341#[doc(hidden)]
342#[macro_export]
343macro_rules! sum2 {
344    (impl<$($t:ident),*> $trait:ident <$($p:ty),*> for Sum where {
345        $(type $assoc:ident;)*
346        $(mut fn $mut_fn:ident(&mut self $(, $mut_arg:ident : $mut_arg_ty:ty)*) -> $mut_ret:ty;)*
347        $(fn $ref_fn:ident(&self $(, $ref_arg:ident : $ref_arg_ty:ty)*) -> $ref_ret:ty;)*
348    }) => (
349        impl<A, B, $($t,)*> $trait<$($t,)*> for $crate::Sum2<A, B>
350        where
351            A: $trait<$($t,)*>,
352            B: $trait<$($t,)* $($assoc = A::$assoc,)*>,
353        {
354            $(type $assoc = A::$assoc;)*
355
356            $(
357            #[inline]
358            fn $mut_fn(&mut self $(, $mut_arg : $mut_arg_ty)*) -> $mut_ret {
359                match self {
360                    $crate::Sum2::A(self_) => self_.$mut_fn($($mut_arg),*),
361                    $crate::Sum2::B(self_) => self_.$mut_fn($($mut_arg),*),
362                }
363            }
364            )*
365
366            $(
367            #[inline]
368            fn $ref_fn(&self $(, $ref_arg : $ref_arg_ty)*) -> $ref_ret {
369                match self {
370                    $crate::Sum2::A(self_) => self_.$ref_fn($($ref_arg),*),
371                    $crate::Sum2::B(self_) => self_.$ref_fn($($ref_arg),*),
372                }
373            }
374            )*
375        }
376    )
377}
378#[doc(hidden)]
379#[macro_export]
380macro_rules! sum3 {
381    (impl<$($t:ident),*> $trait:ident <$($p:ty),*> for Sum where {
382        $(type $assoc:ident;)*
383        $(mut fn $mut_fn:ident(&mut self $(, $mut_arg:ident : $mut_arg_ty:ty)*) -> $mut_ret:ty;)*
384        $(fn $ref_fn:ident(&self $(, $ref_arg:ident : $ref_arg_ty:ty)*) -> $ref_ret:ty;)*
385    }) => (
386        impl<A, B, C, $($t,)*> $trait<$($t,)*> for $crate::Sum3<A, B, C>
387        where
388            A: $trait<$($t,)*>,
389            B: $trait<$($t,)* $($assoc = A::$assoc,)*>,
390            C: $trait<$($t,)* $($assoc = A::$assoc,)*>,
391        {
392            $(type $assoc = A::$assoc;)*
393
394            $(
395            #[inline]
396            fn $mut_fn(&mut self $(, $mut_arg : $mut_arg_ty)*) -> $mut_ret {
397                match self {
398                    $crate::Sum3::A(self_) => self_.$mut_fn($($mut_arg),*),
399                    $crate::Sum3::B(self_) => self_.$mut_fn($($mut_arg),*),
400                    $crate::Sum3::C(self_) => self_.$mut_fn($($mut_arg),*),
401                }
402            }
403            )*
404
405            $(
406            #[inline]
407            fn $ref_fn(&self $(, $ref_arg : $ref_arg_ty)*) -> $ref_ret {
408                match self {
409                    $crate::Sum3::A(self_) => self_.$ref_fn($($ref_arg),*),
410                    $crate::Sum3::B(self_) => self_.$ref_fn($($ref_arg),*),
411                    $crate::Sum3::C(self_) => self_.$ref_fn($($ref_arg),*),
412                }
413            }
414            )*
415        }
416    )
417}
418
419#[doc(hidden)]
420#[macro_export(local_inner_macros)]
421macro_rules! derive_sum {
422    (impl<$($t:ident),*> $trait:ident <$($p:ty),*> for Sum where {
423        $(type $assoc:ident;)*
424        $(mut fn $mut_fn:ident(&mut self $(, $mut_arg:ident : $mut_arg_ty:ty)*) -> $mut_ret:ty;)*
425        $(fn $ref_fn:ident(&self $(, $ref_arg:ident : $ref_arg_ty:ty)*) -> $ref_ret:ty;)*
426    }) => (
427        sum2!(
428            impl<$($t),*> $trait <$($p),*> for Sum where {
429                $(type $assoc;)*
430                $(mut fn $mut_fn(&mut self $(, $mut_arg : $mut_arg_ty)*) -> $mut_ret;)*
431                $(fn $ref_fn(&self $(, $ref_arg : $ref_arg_ty)*) -> $ref_ret;)*
432            }
433        );
434        sum3!(
435            impl<$($t),*> $trait <$($p),*> for Sum where {
436                $(type $assoc;)*
437                $(mut fn $mut_fn(&mut self $(, $mut_arg : $mut_arg_ty)*) -> $mut_ret;)*
438                $(fn $ref_fn(&self $(, $ref_arg : $ref_arg_ty)*) -> $ref_ret;)*
439            }
440        );
441    );
442    (impl $trait:ident for Sum {
443        $(type $assoc:ident;)*
444        $(mut fn $mut_fn:ident(&mut self $(, $mut_arg:ident : $mut_arg_ty:ty)*) -> $mut_ret:ty;)*
445        $(fn $ref_fn:ident(&self $(, $ref_arg:ident : $ref_arg_ty:ty)*) -> $ref_ret:ty;)*
446    }) => (
447        sum2!(
448            impl<> $trait <> for Sum where {
449                $(type $assoc;)*
450                $(mut fn $mut_fn(&mut self $(, $mut_arg : $mut_arg_ty)*) -> $mut_ret;)*
451                $(fn $ref_fn(&self $(, $ref_arg : $ref_arg_ty)*) -> $ref_ret;)*
452            }
453        );
454        sum3!(
455            impl<> $trait <> for Sum where {
456                $(type $assoc;)*
457                $(mut fn $mut_fn(&mut self $(, $mut_arg : $mut_arg_ty)*) -> $mut_ret;)*
458                $(fn $ref_fn(&self $(, $ref_arg : $ref_arg_ty)*) -> $ref_ret;)*
459            }
460        );
461    );
462}
463
464#[test]
465fn basic() {
466	let mut e = Sum2::A(2);
467	let r = Sum2::B(2);
468	assert_eq!(e, Sum2::A(2));
469	e = r;
470	assert_eq!(e, Sum2::B(2));
471	assert_eq!(e.a(), None);
472	assert_eq!(e.b(), Some(2));
473	assert_eq!(e.as_ref().b(), Some(&2));
474	assert_eq!(e.as_mut().b(), Some(&mut 2));
475}
476
477#[test]
478fn derive() {
479	trait Abc {
480		fn abc(&self);
481		fn def(&mut self);
482	}
483	derive_sum!(impl Abc for Sum {
484		mut fn def(&mut self) -> ();
485		fn abc(&self) -> ();
486	});
487}