Skip to main content

example_communication_common/
communication.rs

1use std::cmp::PartialEq;
2use std::fmt;
3use std::fmt::{Display, Formatter};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub enum ConnectionType {
8    Client,
9    Controller
10}
11
12impl PartialEq<ConnectionType> for &ConnectionType {
13    fn eq(&self, other: &ConnectionType) -> bool {
14        match (self,other) {
15            (&ConnectionType::Client, &ConnectionType::Client) => true,
16            (&ConnectionType::Controller, &ConnectionType::Controller) => true,
17            _ => false
18        }
19    }
20}
21
22impl ConnectionType {
23    pub fn as_str(&self) -> &str {
24        match self {
25            ConnectionType::Client => {"Client"}
26            ConnectionType::Controller => {"Controller"}
27        }
28    }
29}
30impl Display for ConnectionType {
31    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
32        write!(f, "{}", self.as_str())
33    }
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct ConnectionInfo {
38    pub uuid: String,
39    pub name: String,
40    pub connection_type: ConnectionType,
41}
42
43impl Display for ConnectionInfo {
44    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
45        write!(f, "(uuid: {} name: {} connection type: {})", self.uuid, self.name, self.connection_type)
46    }
47}
48
49#[derive(Serialize, Deserialize, Clone)]
50pub enum ControlTypes {
51    Message,
52    TransferFile,
53}
54
55pub struct ControlOption {
56    pub display_name: String,
57    pub name: String,
58    pub ui_type: UITypes,
59    pub default_value: String,
60}
61
62pub enum UITypes {
63    Text,
64    Checkbox
65}
66
67pub struct ControlDefinition {
68    pub display_name: String,
69    pub name: String,
70    pub options: Vec<ControlOption>
71}
72
73impl ControlTypes {
74    pub fn as_str(&self) -> String {
75        match self {
76            ControlTypes::Message => {"Message".to_string()}
77            ControlTypes::TransferFile => {"TransferFile".to_string()}
78        }
79    }
80    pub fn to_definition(&self) -> ControlDefinition {
81        match self {
82            ControlTypes::Message => {
83                ControlDefinition {
84                    display_name: "Send Message".to_string(),
85                    name: self.as_str(),
86                    options: vec![ControlOption {
87                        display_name: "Text".to_string(),
88                        name: "Text".to_string(),
89                        ui_type: UITypes::Text,
90                        default_value: "".to_string(),
91                    }],
92                }
93            },
94            ControlTypes::TransferFile => {
95                ControlDefinition {
96                    display_name: "Transfer File".to_string(),
97                    name: self.as_str(),
98                    options: vec![ControlOption {
99                       display_name: "File Location".to_string(),
100                        name: "File".to_string(),
101                        ui_type: UITypes::Text,
102                        default_value: "".to_string(),
103                    }],
104                }
105            }
106        }
107    }
108}
109
110#[derive(Serialize, Deserialize, Clone)]
111pub enum ControlMessage {
112    Message {
113        text: String
114    },
115    TransferFile,
116}
117
118#[derive(Serialize, Deserialize, Clone)]
119pub struct FileDefinition {
120    pub path: String,
121    pub file_type: String
122}
123
124#[derive(Serialize, Deserialize, Clone)]
125pub enum CommandType {
126    // Server -> Client
127    Welcome {uuid: String},
128    ActiveConnections { users: Vec<ConnectionInfo> },
129    UpdateConnection { connection_info: ConnectionInfo },
130    NotifyDisconnect { uuid: String },
131    // Client -> Server
132    GetConnections {reply_uuid: String},
133    SetConnectionInfo { info: ConnectionInfo },
134    Disconnect,
135    // Client -> Client
136    Control {
137        message_type: ControlMessage,
138    },
139    RequestCapabilities {
140        reply_uuid: String
141    },
142    ProvideCapabilities {
143        sender_uuid: String,
144        list: Vec<ControlTypes>
145    },
146    Ack,
147    // File Transfer
148    StartFileTransfer {
149        name: String,
150        chunk_count: u64,
151        blob_size: usize,
152        checksum: String,
153        return_uuid: String
154    },
155    FileTransferBlob {
156        name: String,
157        chunk_num: i32,
158        blob: Vec<u8>,
159        return_uuid: String
160    },
161    FileTransferAck {
162        name: String,
163        start: bool,
164        chunk_num: i32,
165        whole: bool,
166    },
167    FileTransferNack {
168        name: String,
169        start: bool,
170        chunk_num: i32,
171        whole: bool
172    },
173    // Files
174    AddFileWatch {
175        return_uuid: String
176    },
177    ProvideFiles {
178        uuid: String,
179        files: Vec<FileDefinition>
180    },
181    UpdateFile {
182        uuid: String,
183        file: FileDefinition,
184        add: bool,
185    }
186}
187
188#[derive(Serialize, Deserialize, Clone)]
189pub enum Destination {
190    Single { destination_uuid: String},
191    Multi { destination_uuids: Vec<String>},
192    Type { destination_type: ConnectionType },
193    All,
194    None
195}
196
197
198impl Destination {
199    pub fn matches_destination(&self, connection_info: &ConnectionInfo) -> bool {
200        match self {
201            Destination::Single { destination_uuid } => { *destination_uuid == connection_info.uuid }
202            Destination::Multi { destination_uuids } => { destination_uuids.contains(&connection_info.uuid) }
203            Destination::Type { destination_type } => { destination_type == connection_info.connection_type }
204            Destination::All => { true }
205            Destination::None => { false }
206        }
207    }
208
209    pub fn matches_uuid(&self, uuid: &String) -> bool {
210        match self {
211            Destination::Single { destination_uuid } => { *destination_uuid == *uuid }
212            Destination::Multi { destination_uuids } => { destination_uuids.contains(uuid) }
213            Destination::Type { .. } => { false }
214            Destination::All => { true }
215            Destination::None => { false }
216        }
217
218    }
219}
220
221#[derive(Serialize, Deserialize, Clone)]
222pub struct WebSocketMessage {
223    pub command: CommandType,
224    pub destination: Destination
225}