terminal-chat
288 строк · 6.9 Кб
1use std::{
2str::FromStr,
3fmt,
4error::Error
5};
6
7/*
8Сигнал может содержать следующие хедеры
9USER: USERNAME
10SERVER: AUTH_STATUS
11USER+SERVER: WITH_MESSAGE
12USER+SERVER: SIGNAL_TYPE
13SERVER: SERVER_MESSAGE
14*/
15
16#[derive(Debug)]
17pub struct ParseSignalDataError;
18impl Error for ParseSignalDataError {}
19impl fmt::Display for ParseSignalDataError {
20fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21write!(f, "invalid signal data")
22}
23}
24
25#[derive(Debug)]
26pub struct AuthConnectionError;
27impl Error for AuthConnectionError {}
28impl fmt::Display for AuthConnectionError {
29fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
30write!(f, "auth connection error")
31}
32}
33
34#[derive(Debug)]
35pub struct IncomingMessageError;
36impl Error for IncomingMessageError {}
37impl fmt::Display for IncomingMessageError {
38fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39write!(f, "incoming message error")
40}
41}
42
43
44#[derive(Debug, Clone, Copy)]
45pub enum SignalType {
46Connection,
47NewMessage,
48}
49
50impl FromStr for SignalType {
51type Err = ParseSignalDataError;
52
53fn from_str(s: &str) -> Result<Self, Self::Err> {
54match s {
55"CONNECTION" => Ok(SignalType::Connection),
56"NEW_MESSAGE" => Ok(SignalType::NewMessage),
57_ => Err(ParseSignalDataError)
58}
59}
60}
61
62impl ToString for SignalType {
63fn to_string(&self) -> String {
64match self {
65SignalType::Connection => "CONNECTION".to_owned(),
66SignalType::NewMessage => "NEW_MESSAGE".to_owned(),
67}
68}
69}
70
71
72#[derive(Debug, Clone, Copy)]
73pub enum AuthStatus {
74ACCEPTED,
75DENIED
76}
77
78impl FromStr for AuthStatus {
79type Err = ParseSignalDataError;
80
81fn from_str(s: &str) -> Result<Self, Self::Err> {
82match s {
83"ACCEPTED" => Ok(AuthStatus::ACCEPTED),
84"DENIED" => Ok(AuthStatus::DENIED),
85_ => Err(ParseSignalDataError)
86}
87}
88}
89
90impl ToString for AuthStatus {
91fn to_string(&self) -> String {
92match self {
93AuthStatus::ACCEPTED => "ACCEPTED".to_owned(),
94AuthStatus::DENIED => "DENIED".to_owned()
95}
96}
97}
98
99
100pub enum SignalHeader {
101Username(String),
102AuthStatus(AuthStatus),
103SignalType(SignalType),
104WithMessage,
105ServerMessage
106}
107
108impl FromStr for SignalHeader {
109type Err = ParseSignalDataError;
110
111fn from_str(s: &str) -> Result<Self, Self::Err> {
112let (header, value) = s.split_once(':').unwrap_or((s, s));
113
114match header {
115"USERNAME" => Ok(SignalHeader::Username(value.trim().to_owned())),
116"AUTH_STATUS" => {
117match AuthStatus::from_str(value.trim()) {
118Ok(v) => return Ok(SignalHeader::AuthStatus(v)),
119Err(_) => Err(ParseSignalDataError)
120}
121},
122"SIGNAL_TYPE" => {
123match SignalType::from_str(value.trim()) {
124Ok(v) => return Ok(SignalHeader::SignalType(v)),
125Err(_) => Err(ParseSignalDataError)
126}
127}
128"WITH_MESSAGE" => Ok(SignalHeader::WithMessage),
129"SERVER_MESSAGE" => Ok(SignalHeader::ServerMessage),
130_ => Err(ParseSignalDataError)
131}
132}
133}
134
135impl ToString for SignalHeader {
136fn to_string(&self) -> String {
137match self {
138SignalHeader::Username(v) => format!("USERNAME: {v}\r\n"),
139SignalHeader::AuthStatus(v) => format!("AUTH_STATUS: {}\r\n", v.to_string()),
140SignalHeader::SignalType(v) => format!("SIGNAL_TYPE: {}\r\n", v.to_string()),
141SignalHeader::WithMessage => "WITH_MESSAGE\r\n".to_owned(),
142SignalHeader::ServerMessage => "SERVER_MESSAGE\r\n".to_owned()
143}
144}
145}
146
147#[derive(Debug, Clone)]
148pub struct SignalData {
149pub username: Option<String>,
150pub password: Option<String>,
151pub key: Option<String>,
152pub auth_status: Option<AuthStatus>,
153pub signal_type: Option<SignalType>,
154pub with_message: bool,
155pub message: Option<String>,
156pub server_message: bool
157}
158
159impl SignalData {
160pub fn new(headers: Vec<SignalHeader>, message: Option<&str>) -> SignalData {
161let mut data = SignalData {
162username: None,
163password: None,
164key: None,
165auth_status: None,
166signal_type: None,
167with_message: false,
168message: None,
169server_message: false
170};
171
172for header in headers {
173match header {
174SignalHeader::Username(v) => {
175data.username = Some(v);
176},
177SignalHeader::AuthStatus(v) => {
178data.auth_status = Some(v);
179},
180SignalHeader::SignalType(v) => {
181data.signal_type = Some(v);
182},
183SignalHeader::WithMessage => {
184data.with_message = true;
185data.message = Some(message.unwrap_or("").to_owned());
186},
187SignalHeader::ServerMessage => {
188data.server_message = true;
189}
190}
191}
192
193data
194}
195}
196
197impl FromStr for SignalData {
198type Err = ParseSignalDataError;
199
200fn from_str(s: &str) -> Result<Self, Self::Err> {
201let mut data = SignalData {
202username: None,
203password: None,
204key: None,
205auth_status: None,
206signal_type: None,
207with_message: false,
208message: None,
209server_message: false,
210};
211let splitted = s.split("\r\n");
212for string in splitted {
213let header = match SignalHeader::from_str(string) {
214Ok(v) => v,
215Err(_) => continue
216};
217
218match header {
219SignalHeader::Username(v) => {
220data.username = Some(v);
221},
222SignalHeader::AuthStatus(v) => {
223data.auth_status = Some(v);
224},
225SignalHeader::SignalType(v) => {
226data.signal_type = Some(v);
227}
228SignalHeader::WithMessage => {
229data.with_message = true;
230},
231SignalHeader::ServerMessage => {
232data.server_message = true;
233}
234}
235}
236
237if data.with_message {
238let splitted = s.split_once("\r\n\r\n");
239if let Some(v) = splitted {
240if v.1.ends_with("\r\n\r\n") {
241let string = v.1.to_owned();
242data.message = Some(string[..string.len() - 4].to_owned());
243}
244else {
245data.message = Some(v.1.to_owned());
246}
247}
248else {
249return Err(ParseSignalDataError);
250}
251}
252
253if let None = data.signal_type {
254return Err(ParseSignalDataError)
255}
256
257Ok(data)
258}
259}
260
261impl ToString for SignalData {
262fn to_string(&self) -> String {
263let mut res_str = String::new();
264
265if let Some(v) = &self.username {
266res_str.push_str(&SignalHeader::Username(v.to_owned()).to_string());
267}
268if let Some(v) = &self.auth_status {
269res_str.push_str(&SignalHeader::AuthStatus(v.clone()).to_string());
270}
271if let Some(v) = &self.signal_type {
272res_str.push_str(&SignalHeader::SignalType(v.clone()).to_string());
273}
274if self.server_message {
275res_str.push_str(&SignalHeader::ServerMessage.to_string());
276}
277if self.with_message {
278if let Some(v) = &self.message {
279res_str.push_str(&SignalHeader::WithMessage.to_string());
280res_str.push_str("\r\n");
281res_str.push_str(&v);
282}
283}
284res_str.push_str("\r\n\r\n");
285
286res_str
287}
288}