1use crate::connection::{Connection, ConnectionError};
2use crate::frame::Frame;
3use bytes::Bytes;
4use std::any::type_name;
5use std::collections::HashMap;
6use std::hash::Hash;
7use std::str::{self, Utf8Error};
8use thiserror::Error;
9
10pub trait ToSegmentFrame {
12 fn to_segment_frame(&self) -> Frame;
14}
15
16pub trait FromSegmentFrame: Sized {
18 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError>;
20}
21
22#[derive(Debug)]
24pub struct Command {
25 args: Vec<Frame>,
26}
27
28#[derive(Debug, Error)]
30pub enum CommandError {
31 #[error("incompatible response type: failed to convert from {0} to {1}")]
33 IncompatibleType(&'static str, &'static str),
34
35 #[error(transparent)]
37 Utf8Error(#[from] Utf8Error),
38
39 #[error("{0}")]
41 QueryError(String),
42
43 #[error(transparent)]
45 ConnectionError(#[from] ConnectionError),
46
47 #[error("failed to decode the frame")]
49 Decode,
50}
51
52impl Command {
53 pub fn new() -> Self {
55 Command { args: Vec::new() }
56 }
57
58 pub fn arg<T: ToSegmentFrame>(&mut self, arg: T) -> &mut Self {
60 self.args.push(arg.to_segment_frame());
61 self
62 }
63
64 pub async fn query<T: FromSegmentFrame>(
66 self,
67 connection: &mut Connection,
68 ) -> Result<T, CommandError> {
69 let cmd = Frame::Array(self.args);
70 connection.write_frame(&cmd).await?;
71 let response = connection.read_frame().await?;
72
73 match response {
74 Frame::Error(val) => Err(CommandError::QueryError(
75 str::from_utf8(&val[..])?.to_string(),
76 )),
77 _ => T::from_segment_frame(&response),
78 }
79 }
80}
81
82impl Default for Command {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
88impl ToSegmentFrame for u8 {
89 fn to_segment_frame(&self) -> Frame {
90 Frame::Integer(*self as i64)
91 }
92}
93
94impl ToSegmentFrame for i8 {
95 fn to_segment_frame(&self) -> Frame {
96 Frame::Integer(*self as i64)
97 }
98}
99
100impl ToSegmentFrame for u16 {
101 fn to_segment_frame(&self) -> Frame {
102 Frame::Integer(*self as i64)
103 }
104}
105
106impl ToSegmentFrame for i16 {
107 fn to_segment_frame(&self) -> Frame {
108 Frame::Integer(*self as i64)
109 }
110}
111
112impl ToSegmentFrame for u32 {
113 fn to_segment_frame(&self) -> Frame {
114 Frame::Integer(*self as i64)
115 }
116}
117
118impl ToSegmentFrame for i32 {
119 fn to_segment_frame(&self) -> Frame {
120 Frame::Integer(*self as i64)
121 }
122}
123
124impl ToSegmentFrame for u64 {
125 fn to_segment_frame(&self) -> Frame {
126 Frame::Integer(*self as i64)
127 }
128}
129
130impl ToSegmentFrame for i64 {
131 fn to_segment_frame(&self) -> Frame {
132 Frame::Integer(*self as i64)
133 }
134}
135
136impl ToSegmentFrame for usize {
137 fn to_segment_frame(&self) -> Frame {
138 Frame::Integer(*self as i64)
139 }
140}
141
142impl ToSegmentFrame for isize {
143 fn to_segment_frame(&self) -> Frame {
144 Frame::Integer(*self as i64)
145 }
146}
147
148impl ToSegmentFrame for f32 {
149 fn to_segment_frame(&self) -> Frame {
150 Frame::Double(*self as f64)
151 }
152}
153
154impl ToSegmentFrame for f64 {
155 fn to_segment_frame(&self) -> Frame {
156 Frame::Double(*self as f64)
157 }
158}
159
160impl ToSegmentFrame for bool {
161 fn to_segment_frame(&self) -> Frame {
162 Frame::Boolean(*self)
163 }
164}
165
166impl ToSegmentFrame for String {
167 fn to_segment_frame(&self) -> Frame {
168 Frame::String(Bytes::from(self.clone()))
169 }
170}
171
172impl ToSegmentFrame for &str {
173 fn to_segment_frame(&self) -> Frame {
174 Frame::String(Bytes::from(self.to_string()))
175 }
176}
177
178impl ToSegmentFrame for Bytes {
179 fn to_segment_frame(&self) -> Frame {
180 Frame::String(self.clone())
181 }
182}
183
184impl<T: ToSegmentFrame> ToSegmentFrame for Option<T> {
185 fn to_segment_frame(&self) -> Frame {
186 if let Some(val) = self {
187 return T::to_segment_frame(val);
188 }
189 Frame::Null
190 }
191}
192
193impl<K: ToSegmentFrame, V: ToSegmentFrame> ToSegmentFrame for HashMap<K, V> {
194 fn to_segment_frame(&self) -> Frame {
195 let mut map = Vec::with_capacity(2 * self.len());
196 for (key, value) in self.iter() {
197 map.push(key.to_segment_frame());
198 map.push(value.to_segment_frame());
199 }
200
201 Frame::Map(map)
202 }
203}
204
205impl FromSegmentFrame for u8 {
206 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
207 match frame {
208 Frame::Integer(val) => Ok(*val as u8),
209 Frame::Double(val) => Ok(*val as u8),
210 other => Err(CommandError::IncompatibleType(
211 other.as_str(),
212 type_name::<Self>(),
213 )),
214 }
215 }
216}
217
218impl FromSegmentFrame for i8 {
219 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
220 match frame {
221 Frame::Integer(val) => Ok(*val as i8),
222 Frame::Double(val) => Ok(*val as i8),
223 other => Err(CommandError::IncompatibleType(
224 other.as_str(),
225 type_name::<Self>(),
226 )),
227 }
228 }
229}
230
231impl FromSegmentFrame for u16 {
232 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
233 match frame {
234 Frame::Integer(val) => Ok(*val as u16),
235 Frame::Double(val) => Ok(*val as u16),
236 other => Err(CommandError::IncompatibleType(
237 other.as_str(),
238 type_name::<Self>(),
239 )),
240 }
241 }
242}
243
244impl FromSegmentFrame for i16 {
245 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
246 match frame {
247 Frame::Integer(val) => Ok(*val as i16),
248 Frame::Double(val) => Ok(*val as i16),
249 other => Err(CommandError::IncompatibleType(
250 other.as_str(),
251 type_name::<Self>(),
252 )),
253 }
254 }
255}
256
257impl FromSegmentFrame for u32 {
258 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
259 match frame {
260 Frame::Integer(val) => Ok(*val as u32),
261 Frame::Double(val) => Ok(*val as u32),
262 other => Err(CommandError::IncompatibleType(
263 other.as_str(),
264 type_name::<Self>(),
265 )),
266 }
267 }
268}
269
270impl FromSegmentFrame for i32 {
271 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
272 match frame {
273 Frame::Integer(val) => Ok(*val as i32),
274 Frame::Double(val) => Ok(*val as i32),
275 other => Err(CommandError::IncompatibleType(
276 other.as_str(),
277 type_name::<Self>(),
278 )),
279 }
280 }
281}
282
283impl FromSegmentFrame for u64 {
284 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
285 match frame {
286 Frame::Integer(val) => Ok(*val as u64),
287 Frame::Double(val) => Ok(*val as u64),
288 other => Err(CommandError::IncompatibleType(
289 other.as_str(),
290 type_name::<Self>(),
291 )),
292 }
293 }
294}
295
296impl FromSegmentFrame for i64 {
297 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
298 match frame {
299 Frame::Integer(val) => Ok(*val),
300 Frame::Double(val) => Ok(*val as i64),
301 other => Err(CommandError::IncompatibleType(
302 other.as_str(),
303 type_name::<Self>(),
304 )),
305 }
306 }
307}
308
309impl FromSegmentFrame for f32 {
310 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
311 match frame {
312 Frame::Integer(val) => Ok(*val as f32),
313 Frame::Double(val) => Ok(*val as f32),
314 other => Err(CommandError::IncompatibleType(
315 other.as_str(),
316 type_name::<Self>(),
317 )),
318 }
319 }
320}
321
322impl FromSegmentFrame for f64 {
323 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
324 match frame {
325 Frame::Integer(val) => Ok(*val as f64),
326 Frame::Double(val) => Ok(*val),
327 other => Err(CommandError::IncompatibleType(
328 other.as_str(),
329 type_name::<Self>(),
330 )),
331 }
332 }
333}
334
335impl FromSegmentFrame for bool {
336 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
337 match frame {
338 Frame::Boolean(val) => Ok(*val),
339 other => Err(CommandError::IncompatibleType(
340 other.as_str(),
341 type_name::<Self>(),
342 )),
343 }
344 }
345}
346
347impl FromSegmentFrame for String {
348 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
349 match frame {
350 Frame::String(val) => Ok(str::from_utf8(&val[..])?.to_string()),
351 other => Err(CommandError::IncompatibleType(
352 other.as_str(),
353 type_name::<Self>(),
354 )),
355 }
356 }
357}
358
359impl FromSegmentFrame for Bytes {
360 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
361 match frame {
362 Frame::String(val) => Ok(val.clone()),
363 other => Err(CommandError::IncompatibleType(
364 other.as_str(),
365 type_name::<Self>(),
366 )),
367 }
368 }
369}
370
371impl<T: FromSegmentFrame> FromSegmentFrame for Option<T> {
372 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
373 match frame {
374 Frame::Null => Ok(None),
375 _ => Ok(Some(T::from_segment_frame(frame)?)),
376 }
377 }
378}
379
380impl<T: FromSegmentFrame> FromSegmentFrame for Vec<T> {
381 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
382 let mut vec = Vec::new();
383 match frame {
384 Frame::Array(array) => {
385 for v in array {
386 vec.push(T::from_segment_frame(v)?);
387 }
388 Ok(vec)
389 }
390 other => Err(CommandError::IncompatibleType(
391 other.as_str(),
392 type_name::<Self>(),
393 )),
394 }
395 }
396}
397
398impl<K, V> FromSegmentFrame for HashMap<K, V>
399where
400 K: FromSegmentFrame + Eq + Hash,
401 V: FromSegmentFrame,
402{
403 fn from_segment_frame(frame: &Frame) -> Result<Self, CommandError> {
404 match frame {
405 Frame::Map(map) => {
406 let len = map.len();
407 if len == 0 {
408 return Ok(HashMap::new());
409 }
410 if len % 2 != 0 {
411 return Err(CommandError::Decode);
412 }
413 let mut result = HashMap::with_capacity(len / 2);
414 let mut idx = 0;
415
416 while idx < len - 1 {
417 let key = K::from_segment_frame(&map[idx])?;
418 idx += 1;
419 let value = V::from_segment_frame(&map[idx])?;
420 idx += 1;
421
422 result.insert(key, value);
423 }
424
425 Ok(result)
426 }
427 other => Err(CommandError::IncompatibleType(
428 other.as_str(),
429 type_name::<Self>(),
430 )),
431 }
432 }
433}