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
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! This module is a beta feature that only works with
//! RoleA, RoleB and RoleC. It also has various
//! prerequisites that are shown in tests 06.

mod aux_checker;
mod aux_dot;

use self::aux_checker::{checker_aux, parse_type_of};

use crate::binary::struct_trait::Session;
use crate::meshedchannels::MeshedChannels;
use crate::role::Role;

use std::collections::HashMap;
use std::error::Error;

/// Displays the local endpoints of each roles.
/// It is required that the `MeshedChannels` are the root ones,
/// and not a partial part included in a bigger one. It is
/// useful for checking whether the implemented local
/// endpoints are the expected ones.
///
/// Returns the 3 strings if everything went right.
/// TODO: Adapt checker for RoleBroadcast
/// Useful???
pub fn checker<
    S0,
    S1,
    S2,
    R1,
    R2,
    R3,
    N1,
    N2,
    N3,
    BH1: ::std::hash::BuildHasher,
    BH2: ::std::hash::BuildHasher,
>(
    s1: MeshedChannels<S0, <S2 as Session>::Dual, R1, N1>,
    s2: MeshedChannels<<S0 as Session>::Dual, S1, R2, N2>,
    s3: MeshedChannels<S2, <S1 as Session>::Dual, R3, N3>,
    branches_receivers: &HashMap<String, &Vec<String>, BH1>,
    branches_sender: &HashMap<String, &Vec<String>, BH2>,
) -> Result<(String, String, String), Box<dyn Error>>
where
    S0: Session + 'static,
    S1: Session + 'static,
    S2: Session + 'static,
    R1: Role + 'static,
    R2: Role + 'static,
    R3: Role + 'static,
    N1: Role + 'static,
    N2: Role + 'static,
    N3: Role + 'static,
{
    let result_1 = checker_aux(
        [
            &parse_type_of(&s1.session1),
            &parse_type_of(&s1.session2),
            &parse_type_of(&s1.stack),
            &parse_type_of(&s1.name),
        ],
        "A",
        (branches_receivers, branches_sender),
        &mut vec![],
    )?;
    // println!("result A: {}", &result_1);
    let result_2 = checker_aux(
        [
            &parse_type_of(&s2.session1),
            &parse_type_of(&s2.session2),
            &parse_type_of(&s2.stack),
            &parse_type_of(&s2.name),
        ],
        "B",
        (branches_receivers, branches_sender),
        &mut vec![],
    )?;
    // println!("result B: {}", &result_2);
    let result_3 = checker_aux(
        [
            &parse_type_of(&s3.session1),
            &parse_type_of(&s3.session2),
            &parse_type_of(&s3.stack),
            &parse_type_of(&s3.name),
        ],
        "C",
        (branches_receivers, branches_sender),
        &mut vec![],
    )?;
    // println!("result C: {}", &result_3);

    Ok((
        format!("A: {}", &result_1),
        format!("B: {}", &result_2),
        format!("C: {}", &result_3),
    ))
}

/// macro to create hashmap function, necessary for
/// recursion. Need to sort out the path
#[macro_export]
#[doc(hidden)]
macro_rules! checker_hashmaps {
    // ($( $branch: ty, $func: ident, $branch_type: expr, { $( $pat: path, $branch_name: expr, $label: path, )* }, )*) => {
        ({ $( $branch: path, $func: ident, { $( $pat: path, )* }, )* }) => {

        let mut hm: HashMap<String, &Vec<String>> = HashMap::new();

        fn type_of<T>(_: T) -> &'static str {
            type_name::<T>()
        }

        $(
            impl<N: marker::Send> fmt::Display for $branch<N> {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    match self {
                        $(
                            $pat(s) => write!(f, stringify!($pat), type_of(&s)),
                        )*
                    }
                }
            }

            fn $func() -> Vec<String> {
                let vec = Vec::new();

                $(
                    let (s, _) = <_ as Session>::new();

                    vec.push((&$pat::<i32>(s).to_string()));
                )*

                vec
            }

            hm.insert(String::from(stringify!($branch)), &$func());
        )*

        hm
    };
}