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
use wrapper::nif_interface::NIF_TERM;
use wrapper::tuple;
use {Decoder, Encoder, Env, Error, NifResult, Term};
pub fn get_tuple<'a>(term: Term<'a>) -> Result<Vec<Term<'a>>, Error> {
let env = term.get_env();
unsafe {
match tuple::get_tuple(env.as_c_arg(), term.as_c_arg()) {
Ok(terms) => Ok(terms
.iter()
.map(|x| Term::new(env, *x))
.collect::<Vec<Term>>()),
Err(_error) => Err(Error::BadArg),
}
}
}
pub fn make_tuple<'a>(env: Env<'a>, terms: &[Term]) -> Term<'a> {
let c_terms: Vec<NIF_TERM> = terms.iter().map(|term| term.as_c_arg()).collect();
unsafe { Term::new(env, tuple::make_tuple(env.as_c_arg(), &c_terms)) }
}
macro_rules! tuple {
( ) => { () };
( $e0:tt ) => { ($e0,) };
( $( $e:tt ),* ) => { ( $( $e ),* ) };
}
macro_rules! count {
( ) => ( 0 );
( $blah:expr ) => ( 1 );
( $blah:expr, $( $others:expr ),* ) => ( 1 + count!( $( $others ),* ) )
}
macro_rules! impl_nifencoder_nifdecoder_for_tuple {
( $($index:tt : $tyvar:ident),* ) => {
impl<$( $tyvar: Encoder ),*>
Encoder for tuple!( $( $tyvar ),* )
{
fn encode<'a>(&self, env: Env<'a>) -> Term<'a> {
let arr = [ $( Encoder::encode(&self.$index, env).as_c_arg() ),* ];
unsafe {
Term::new(env, tuple::make_tuple(env.as_c_arg(), &arr))
}
}
}
impl<'a, $( $tyvar: Decoder<'a> ),*>
Decoder<'a> for tuple!( $( $tyvar ),* )
{
fn decode(term: Term<'a>) -> NifResult<tuple!( $( $tyvar ),* )>
{
match unsafe { tuple::get_tuple(term.get_env().as_c_arg(), term.as_c_arg()) } {
Ok(elements) if elements.len() == count!( $( $index ),* ) =>
Ok(tuple!( $(
(<$tyvar as Decoder>::decode(
unsafe { Term::new(term.get_env(), elements[$index]) })?)
),* )),
_ =>
Err(Error::BadArg),
}
}
}
}
}
impl_nifencoder_nifdecoder_for_tuple!();
impl_nifencoder_nifdecoder_for_tuple!(0: A);
impl_nifencoder_nifdecoder_for_tuple!(0: A, 1: B);
impl_nifencoder_nifdecoder_for_tuple!(0: A, 1: B, 2: C);
impl_nifencoder_nifdecoder_for_tuple!(0: A, 1: B, 2: C, 3: D);
impl_nifencoder_nifdecoder_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E);
impl_nifencoder_nifdecoder_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F);
impl_nifencoder_nifdecoder_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G);