Skip to main content

example_communication_common/
communication.rs

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