1use log::error;
12use std::cmp::Ordering;
13#[derive(Debug, Clone, PartialEq)]
14pub enum Cli {
15 SimpleString(String),
17 Errors(String),
19 Integers(i64),
21 BulkString(String),
25 NullBulkString,
27 NullArrays,
29 Arrays(Vec<Cli>),
40}
41impl Cli {
42 fn parse(org: &str) -> (Cli, &str) {
43 let mut str = org.splitn(2, "\r\n");
44 let first = str.next();
45 let second = str.next();
46 if let Some(first) = first {
47 match first.as_bytes()[0] {
48 b'+' => (Cli::SimpleString(first[1..].into()), second.unwrap_or("")),
49 b'-' => (Cli::Errors(first[1..].into()), second.unwrap_or("")),
50 b':' => {
51 let i = &first[1..];
52 (
53 Cli::Integers(i.parse::<i64>().unwrap_or(0)),
54 second.unwrap_or(""),
55 )
56 }
57 b'$' => {
58 let len = &first[1..];
59 let len: i64 = len.parse::<i64>().unwrap_or(-10);
60 match len.cmp(&-1) {
61 Ordering::Equal => (Cli::NullBulkString, second.unwrap_or("")),
62 Ordering::Less => {
63 error!("Cli parse Bulk String Invalid len = {}, str = {}", len, org);
64 (Cli::NullBulkString, "")
65 }
66 Ordering::Greater => {
67 let second = second.unwrap_or("");
68 let second_len = second.len();
69 let len = len as usize;
70 if len > second_len || len + 2 > second_len {
71 error!(
72 "Cli parse Bulk String Invalid len = {}, str = {}",
73 len, org
74 );
75 (Cli::NullBulkString, "")
76 } else {
77 (
78 Cli::BulkString(second[..len as usize].into()),
79 second[len as usize + 2..].into(),
80 )
81 }
82 }
83 }
84 }
85 b'*' => {
86 let len = &first[1..];
87 let len: i64 = len.parse::<i64>().unwrap_or(-10);
88 match len.cmp(&-1) {
89 Ordering::Equal => (Cli::NullArrays, second.unwrap_or("")),
90 Ordering::Less => {
91 error!("Cli parse Arrays Invalid len = {}, str = {}", len, org);
92 (Cli::NullArrays, "")
93 }
94 Ordering::Greater => {
95 let mut arrays = vec![];
96 let mut remain = second.unwrap_or("");
97 for _i in 0..len {
98 if !remain.is_empty() {
99 let (cli, other) = Cli::parse(remain);
100 remain = other;
101 arrays.push(cli);
102 }
103 }
104 (Cli::Arrays(arrays), remain)
105 }
106 }
107 }
108 _ => {
109 error!("Cli parse Invalid {}", org);
110 (Cli::NullArrays, "")
111 }
112 }
113 } else {
114 error!("Cli parse Invalid {}", org);
115 (Cli::NullArrays, "")
116 }
117 }
118}
119impl From<String> for Cli {
120 fn from(str: String) -> Self {
121 let (cli, _) = Cli::parse(&str);
122 cli
123 }
124}
125impl From<Cli> for String {
126 fn from(cli: Cli) -> Self {
127 match cli {
128 Cli::SimpleString(simple) => format!("+{}\r\n", simple),
129 Cli::Errors(errors) => format!("-{}\r\n", errors),
130 Cli::Integers(int) => format!(":{}\r\n", int),
131 Cli::BulkString(bulk) => format!("${}\r\n{}\r\n", bulk.len(), bulk),
132 Cli::NullBulkString => "$-1\r\n".into(),
133 Cli::NullArrays => "*-1\r\n".into(),
134 Cli::Arrays(arrays) if arrays.is_empty() => "*0\r\n".into(),
135 Cli::Arrays(arrays) => {
136 let mut rs = format!("*{}\r\n", arrays.len());
137 for row in arrays {
138 let str: String = row.into();
139 rs += &str;
140 }
141 rs
142 }
143 }
144 }
145}
146impl From<Vec<u8>> for Cli {
147 fn from(bytes: Vec<u8>) -> Self {
148 if let Ok(str) = String::from_utf8(bytes) {
149 str.into()
150 } else {
151 error!("Cli Bytes to String error invalid utf8");
152 Cli::NullArrays
153 }
154 }
155}
156impl From<Cli> for Vec<u8> {
157 fn from(cli: Cli) -> Self {
158 let str: String = cli.into();
159 str.into_bytes()
160 }
161}
162
163impl From<Cli> for Vec<String> {
164 fn from(msg: Cli) -> Self {
165 let mut rs: Vec<String> = vec![];
166 match msg {
167 Cli::Arrays(list) => {
168 for i in list {
169 match i {
170 Cli::SimpleString(ss) | Cli::BulkString(ss) | Cli::Errors(ss) => {
171 rs.push(ss);
172 }
173 Cli::Integers(int) => {
174 rs.push(int.to_string());
175 }
176 _ => {}
177 }
178 }
179 }
180 Cli::SimpleString(ss) | Cli::BulkString(ss) | Cli::Errors(ss) => {
181 rs.push(ss);
182 }
183 Cli::Integers(int) => {
184 rs.push(int.to_string());
185 }
186 _ => {}
187 }
188 rs
189 }
190}
191impl From<Vec<String>> for Cli {
192 fn from(msg: Vec<String>) -> Self {
193 let mut rs = vec![];
194 for str in msg {
195 rs.push(Cli::BulkString(str));
196 }
197 Cli::Arrays(rs)
198 }
199}