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
use super::{Reference, TreatmentInstanciation};
use std::sync::{Arc, RwLock, Weak};

#[derive(Debug)]
pub enum IO {
    Sequence(),
    Treatment(Weak<RwLock<TreatmentInstanciation>>),
}

impl PartialEq for IO {
    fn eq(&self, other: &Self) -> bool {
        match self {
            IO::Sequence() => false,
            IO::Treatment(s_t) => match other {
                IO::Sequence() => false,
                IO::Treatment(o_t) => s_t.ptr_eq(o_t),
            },
        }
    }
}

/**
 * Describes designed connection.
 *
 * Main point of attention is about connection logic:
 * - a connection entry point is an _output_;
 * - a connection exit point is an _input_.
 * But:
 * - when a connection starts from `self`, its entry point is the `self` treatment **input**;
 * - when a connection ends to `self`, its exit point is the `self` treatment **output**.
 *
 * In functions, all is always ordered in the connection direction, starting from entry point and finishing to exit point.
 */
#[derive(Debug)]
pub struct Connection {
    pub output_treatment: IO,
    pub output_name: String,

    pub input_treatment: IO,
    pub input_name: String,

    pub design_reference: Option<Arc<dyn Reference>>,
}

impl Connection {
    pub fn new_internal(
        output_name: &str,
        output_treatment: &Arc<RwLock<TreatmentInstanciation>>,
        input_name: &str,
        input_treatment: &Arc<RwLock<TreatmentInstanciation>>,
        design_reference: Option<Arc<dyn Reference>>,
    ) -> Self {
        Self {
            output_name: output_name.to_string(),
            output_treatment: IO::Treatment(Arc::downgrade(output_treatment)),
            input_name: input_name.to_string(),
            input_treatment: IO::Treatment(Arc::downgrade(input_treatment)),
            design_reference,
        }
    }

    pub fn new_self(
        self_input_name: &str,
        self_output_name: &str,
        design_reference: Option<Arc<dyn Reference>>,
    ) -> Self {
        Self {
            output_name: self_input_name.to_string(),
            output_treatment: IO::Sequence(),
            input_name: self_output_name.to_string(),
            input_treatment: IO::Sequence(),
            design_reference,
        }
    }

    pub fn new_self_to_internal(
        self_input_name: &str,
        input_name: &str,
        input_treatment: &Arc<RwLock<TreatmentInstanciation>>,
        design_reference: Option<Arc<dyn Reference>>,
    ) -> Self {
        Self {
            output_name: self_input_name.to_string(),
            output_treatment: IO::Sequence(),
            input_name: input_name.to_string(),
            input_treatment: IO::Treatment(Arc::downgrade(input_treatment)),
            design_reference,
        }
    }

    pub fn new_internal_to_self(
        output_name: &str,
        output_treatment: &Arc<RwLock<TreatmentInstanciation>>,
        self_output_name: &str,
        design_reference: Option<Arc<dyn Reference>>,
    ) -> Self {
        Self {
            output_name: output_name.to_string(),
            output_treatment: IO::Treatment(Arc::downgrade(output_treatment)),
            input_name: self_output_name.to_string(),
            input_treatment: IO::Sequence(),
            design_reference,
        }
    }
}