1use std::{
2 fmt::Display,
3 io::{Read, Write},
4};
5
6#[derive(Debug)]
7pub enum Argument {
8 Str(String),
9 Int(i64),
10}
11
12impl Display for Argument {
13 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
14 match self {
15 Argument::Str(s) => write!(f, "{}", s),
16 Argument::Int(i) => write!(f, "{}", i),
17 }
18 }
19}
20
21pub fn read_line<T: Read>(conn: &mut T) -> Result<String, String> {
23 let mut buf = vec![];
25
26 let mut tmp_buf = [0u8; 4096];
28
29 loop {
30 let sz = conn.read(&mut tmp_buf).map_err(|err| err.to_string())?;
32
33 if sz == 0 {
35 return Err("connection closed".to_string());
36 }
37
38 buf.extend_from_slice(&tmp_buf[0..sz]);
40
41 if buf.ends_with(&[b'\n']) {
43 break;
44 }
45 }
46
47 Ok(String::from_utf8(buf)
49 .map_err(|err| err.to_string())?
50 .trim()
51 .to_owned())
52}
53
54pub fn write_line<T: Write>(conn: &mut T, line: &String) -> Result<(), String> {
56 let data_to_write = line.to_owned() + "\n";
58
59 conn.write_all(data_to_write.as_bytes())
61 .map_err(|err| err.to_string())
62}
63
64pub fn parse_arguments(input: &str) -> Vec<Argument> {
66 let mut result = Vec::new();
68
69 let mut current_arg = String::new();
71
72 let mut in_quotes = false;
74
75 let mut escape = false;
77
78 for c in input.chars() {
80 if escape {
82 current_arg.push(c);
83 escape = false;
84 } else {
85 match c {
86 '"' => in_quotes = !in_quotes,
88
89 '\\' => escape = true,
91
92 ',' if !in_quotes => {
94 if current_arg.starts_with('"') && current_arg.ends_with('"') {
96 current_arg.remove(current_arg.len() - 1);
97 current_arg.remove(0);
98 result.push(Argument::Str(current_arg.clone()));
99 } else {
100 if let Ok(num) = current_arg.trim().parse::<i64>() {
102 result.push(Argument::Int(num));
103 } else {
104 result.push(Argument::Str(current_arg.clone()));
106 }
107 }
108 current_arg.clear();
110 }
111 _ => current_arg.push(c),
113 }
114 }
115 }
116
117 if !current_arg.is_empty() {
119 if current_arg.starts_with('"') && current_arg.ends_with('"') {
120 current_arg.remove(current_arg.len() - 1);
121 current_arg.remove(0);
122 result.push(Argument::Str(current_arg));
123 } else if let Ok(num) = current_arg.parse::<i64>() {
124 result.push(Argument::Int(num));
125 } else {
126 result.push(Argument::Str(current_arg));
127 }
128 }
129
130 result
132}
133
134pub fn split_command(command_line: &str) -> Option<(String, String)> {
136 let sp = command_line.splitn(2, " ").collect::<Vec<&str>>();
138
139 match sp.len() {
140 0 => None,
142
143 1 => Some((sp[0].to_string(), String::new())),
145
146 2 => Some((sp[0].to_string(), sp[1].to_string())),
148
149 _ => None,
151 }
152}