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
pub mod prelude;
pub mod panic;

mod crash;
pub use crash::Crash;

mod device_id;
pub use device_id::DeviceID;

mod device;
pub use device::Device;

mod fault;
pub use fault::Fault;

mod line;
pub use line::Line;

mod watched;
pub use watched::Watched;

mod plugboard;
mod linemap;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
/// There was a problem Linking
pub enum LinkError {
    /// We can't because we already disconnected.
    DeviceDown,
    /// We can't because the other Device already disconnected.
    LinkDown,
}

#[derive(Clone, Copy)]
#[repr(u32)]
/// How deeply should we link?
pub enum LinkMode {
    /// Receive a notification when the other Device disconnects.
    Monitor = 0b01,
    /// Send a notification when we disconnect.
    Notify  = 0b10,
    /// Monitor + Notify.
    Peer    = 0b11,
}

impl LinkMode {
    /// true if we should be notified when the other Device disconnects.
    pub fn monitor(&self) -> bool {
        LinkMode::Monitor as u32 == ((*self) as u32 & LinkMode::Monitor as u32)
    }
    /// true if we should notify the other Device when we disconnect.
    pub fn notify(&self) -> bool {
        LinkMode::Notify as u32 == ((*self) as u32 & LinkMode::Notify as u32)
    }
    /// true if both sides will notify the other on disconnect.
    pub fn peer(&self) -> bool {
        LinkMode::Peer as u32 == ((*self) as u32 & LinkMode::Peer as u32)
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
/// A message exchanged between devices.
pub enum Message {
    /// A Device we are monitoring has disconnected.
    Disconnected(DeviceID, Option<Fault>),
    /// Request to stop running.
    Shutdown(DeviceID),
}

use Message::{Disconnected, Shutdown};

impl Message {

    /// Returns the DeviceID of the sender.
    pub fn sender(&self) -> DeviceID {
        match self {
            Disconnected(did, _) => *did,
            Shutdown(did) => *did,
        }
    }

    /// Unwraps the Disconnect notification or panics.
    pub fn unwrap_disconnected(&self) -> (DeviceID, Option<Fault>) {
        if let Disconnected(did, fault) = self { (*did, *fault) }
        else { panic!("Message was not Disconnected") }
    }

    /// Unwraps the Shutdown request or panics.
    pub fn unwrap_shutdown(&self) -> DeviceID {
        if let Shutdown(did) = self { *did }
        else { panic!("Message was not Shutdown") }
    }
}