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
use {
	glib::{
		types::StaticType,
		value::{FromValue, ValueTypeChecker, ValueTypeMismatchError, ValueTypeMismatchOrNoneError},
		Type, Value,
	},
	std::error::Error,
};

pub trait FromValues<'a> {
	type Error: Error;
	type Types: IntoIterator<Item = Type>;

	fn from_values(args: &'a [Value]) -> Result<Self, Self::Error>
	where
		Self: Sized;
	fn static_types() -> Self::Types;
}

macro_rules! impl_signal_arguments {
	($count:literal; ($($tx:ident),*)) => {
		#[allow(non_snake_case)]
		impl<'a, $($tx,)*> FromValues<'a> for ($($tx, )*) where
			$($tx: FromValue<'a> + StaticType,)*
			$(ValueTypeMismatchOrNoneError<ValueTypeMismatchError>: From<<$tx::Checker as ValueTypeChecker>::Error>,)*
		{
			type Error = ValueTypeMismatchOrNoneError<ValueTypeMismatchError>;
			type Types = [Type; $count];

			fn from_values(args: &'a [Value]) -> Result<Self, Self::Error> {
				match args {
					[$($tx,)*] => Ok(($($tx.get()?,)*)),
					_ => Err(ValueTypeMismatchOrNoneError::UnexpectedNone),
				}
			}

			fn static_types() -> Self::Types {
				[$($tx::static_type(),)*]
			}
		}
	};
}

impl_signal_arguments! { 0; () }
impl_signal_arguments! { 1; (T0) }
impl_signal_arguments! { 2; (T0, T1) }
impl_signal_arguments! { 3; (T0, T1, T2) }
impl_signal_arguments! { 4; (T0, T1, T2, T3) }
impl_signal_arguments! { 5; (T0, T1, T2, T3, T4) }
impl_signal_arguments! { 6; (T0, T1, T2, T3, T4, T5) }
impl_signal_arguments! { 7; (T0, T1, T2, T3, T4, T5, T6) }
impl_signal_arguments! { 8; (T0, T1, T2, T3, T4, T5, T6, T7) }
impl_signal_arguments! { 9; (T0, T1, T2, T3, T4, T5, T6, T7, T8) }
impl_signal_arguments! { 10; (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) }
impl_signal_arguments! { 11; (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) }
impl_signal_arguments! { 12; (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) }