1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use std::pin::Pin;
use std::future::Future;
use std::task::{Poll, Context};

pub struct PinnedFuture<'a, O> {
	inner: Pin<Box<dyn Future<Output=O> + Send + 'a>>
}

impl<'a, O> PinnedFuture<'a, O> {
	pub fn new<F>(future: F) -> Self
	where F: Future<Output=O> + Send + 'a {
		Self {
			inner: Box::pin(future)
		}
	}
}

impl<O> Future for PinnedFuture<'_, O> {
	type Output = O;
	fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
		self.get_mut().inner.as_mut().poll(cx)
	}
}

/// Creates a enum with the action type
/// 
/// ## Example
/// ```
/// # use fire_stream_api as stream_api;
/// use stream_api::action;
/// 
/// action! {
/// 	#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
/// 	pub enum Action {
/// 		SomeAction = 1
/// 	}
/// }
/// 
/// // The type `Action::Unkown` will be added, unknown should never be used.
/// ```
#[macro_export]
macro_rules! action {
	(
		IMPL,
		$(#[$attr:meta])*
		($($vis:tt)*) $name:ident {
			$(
				$(#[$variant_attr:meta])*
				$variant:ident = $variant_val:expr
			),*
		}
	) => (
		$(#[$attr])*
		$($vis)* enum $name {
			$(
				$(#[$variant_attr])*
				$variant
			),*,
			Unknown
		}

		impl $crate::message::Action for $name {
			fn empty() -> Self {
				Self::Unknown
			}

			fn from_u16(num: u16) -> Option<Self> {
				match num {
					// use this so nobody uses 0 by accident
					0 => Some(Self::Unknown),
					$(
						$variant_val => Some(Self::$variant)
					),*,
					_ => None
				}
			}

			fn as_u16(&self) -> u16 {
				match self {
					$(
						Self::$variant => $variant_val
					),*,
					Self::Unknown => 0
				}
			}
		}
	);
	($(#[$attr:meta])* pub enum $($toks:tt)*) => (
		$crate::action!(IMPL, $(#[$attr])* (pub) $($toks)*);
	);
	($(#[$attr:meta])* pub ($($vis:tt)+) enum $($toks:tt)*) => (
		$crate::action!(IMPL, $(#[$attr])* (pub ($($vis)+)) $($toks)*);
	);
	($(#[$attr:meta])* enum $($toks:tt)*) => (
		$crate::action!(IMPL, $(#[$attr])* () $($toks)*);
	)
}