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    Message,
54    TransferFile,
55    DeleteFile,
56}
57
58pub struct ControlOption {
59    pub display_name: String,
60    pub name: String,
61    pub ui_type: UITypes,
62    pub default_value: String,
63    pub acceptable_option_types: Vec<String>
64}
65
66pub enum UITypes {
67    Text,
68    Checkbox,
69    ComboBox,
70}
71
72pub struct ControlDefinition {
73    pub display_name: String,
74    pub name: String,
75    pub options: Vec<ControlOption>
76}
77
78impl ControlTypes {
79    pub fn as_str(&self) -> String {
80        match self {
81            ControlTypes::Message => {"Message".to_string()}
82            ControlTypes::TransferFile => {"TransferFile".to_string()}
83            ControlTypes::DeleteFile => {"DeleteFile".to_string()}
84        }
85    }
86    pub fn to_definition(&self) -> ControlDefinition {
87        match self {
88            ControlTypes::Message => {
89                ControlDefinition {
90                    display_name: "Send Message".to_string(),
91                    name: self.as_str(),
92                    options: vec![ControlOption {
93                        display_name: "Text".to_string(),
94                        name: "Text".to_string(),
95                        ui_type: UITypes::Text,
96                        default_value: "".to_string(),
97                        acceptable_option_types: vec![],
98                    }],
99                }
100            },
101            ControlTypes::TransferFile => {
102                ControlDefinition {
103                    display_name: "Transfer File".to_string(),
104                    name: self.as_str(),
105                    options: vec![ControlOption {
106                       display_name: "File Location".to_string(),
107                        name: "File".to_string(),
108                        ui_type: UITypes::Text,
109                        default_value: "".to_string(),
110                        acceptable_option_types: vec![],
111                    }],
112                }
113            }
114            ControlTypes::DeleteFile => {
115                ControlDefinition {
116                    display_name: "Delete File".to_string(),
117                    name: self.as_str(),
118                    options: vec![ControlOption {
119                        display_name: "File To Delete".to_string(),
120                        name: "File".to_string(),
121                        ui_type: UITypes::ComboBox,
122                        default_value: "".to_string(),
123                        acceptable_option_types: vec!["ALL".to_string()],
124                    }],
125                }
126            }
127        }
128    }
129}
130
131#[derive(Serialize, Deserialize, Clone)]
132pub enum ControlMessage {
133    Default,
134    Message {
135        text: String
136    },
137    TransferFile,
138    DeleteFile {
139        path: String
140    }
141}
142
143impl Default for ControlMessage {
144    fn default() -> Self {ControlMessage::Default}
145}
146
147#[derive(Serialize, Deserialize, Clone)]
148pub struct FileDefinition {
149    pub path: String,
150    pub file_type: String
151}
152
153#[serde_as]
154#[derive(Serialize, Deserialize, Clone)]
155pub enum CommandType {
156    // Server -> Client
157    Welcome {uuid: String},
158    ActiveConnections { users: Vec<ConnectionInfo> },
159    UpdateConnection { connection_info: ConnectionInfo },
160    NotifyDisconnect { uuid: String },
161    // Client -> Server
162    GetConnections {reply_uuid: String},
163    SetConnectionInfo { info: ConnectionInfo },
164    Disconnect,
165    // Client -> Client
166    Control {
167        #[serde_as(deserialize_as = "DefaultOnError")]
168        message_type: ControlMessage,
169    },
170    RequestCapabilities {
171        reply_uuid: String
172    },
173    ProvideCapabilities {
174        sender_uuid: String,
175        list: Vec<ControlTypes>
176    },
177    Ack,
178    // File Transfer
179    StartFileTransfer {
180        name: String,
181        chunk_count: u64,
182        blob_size: usize,
183        checksum: String,
184        return_uuid: String
185    },
186    FileTransferBlob {
187        name: String,
188        chunk_num: i32,
189        blob: Vec<u8>,
190        return_uuid: String
191    },
192    FileTransferAck {
193        name: String,
194        start: bool,
195        chunk_num: i32,
196        whole: bool,
197    },
198    FileTransferNack {
199        name: String,
200        start: bool,
201        chunk_num: i32,
202        whole: bool
203    },
204    // Files
205    AddFileWatch {
206        return_uuid: String
207    },
208    ProvideFiles {
209        uuid: String,
210        files: Vec<FileDefinition>
211    },
212    UpdateFile {
213        uuid: String,
214        file: FileDefinition,
215        add: bool,
216    }
217}
218
219#[derive(Serialize, Deserialize, Clone)]
220pub enum Destination {
221    Single { destination_uuid: String},
222    Multi { destination_uuids: Vec<String>},
223    Type { destination_type: ConnectionType },
224    All,
225    None
226}
227
228
229impl Destination {
230    pub fn matches_destination(&self, connection_info: &ConnectionInfo) -> bool {
231        match self {
232            Destination::Single { destination_uuid } => { *destination_uuid == connection_info.uuid }
233            Destination::Multi { destination_uuids } => { destination_uuids.contains(&connection_info.uuid) }
234            Destination::Type { destination_type } => { destination_type == connection_info.connection_type }
235            Destination::All => { true }
236            Destination::None => { false }
237        }
238    }
239
240    pub fn matches_uuid(&self, uuid: &String) -> bool {
241        match self {
242            Destination::Single { destination_uuid } => { *destination_uuid == *uuid }
243            Destination::Multi { destination_uuids } => { destination_uuids.contains(uuid) }
244            Destination::Type { .. } => { false }
245            Destination::All => { true }
246            Destination::None => { false }
247        }
248
249    }
250}
251
252#[derive(Serialize, Deserialize, Clone)]
253pub struct WebSocketMessage {
254    pub command: CommandType,
255    pub destination: Destination
256}