sider/
parser.rs

1use std::collections::HashSet;
2
3use crate::{Command, Request};
4
5pub fn parse_resp(s: &String) -> Request {
6    let mut splitted: Vec<&str> = s.split("\r\n").collect();
7    splitted.remove(splitted.len() - 1);
8    let size = splitted[0][1..].parse::<usize>().unwrap();
9    let mut command: Option<Command> = None;
10    let mut key = String::new();
11    let mut value: Vec<String> = vec![];
12    for i in 1..=size * 2 {
13        if i % 2 == 1 {
14            continue;
15        }
16        if i == 2 {
17            match splitted[i].to_uppercase().as_str() {
18                "SET" => command = Some(Command::SET),
19                "GET" => command = Some(Command::GET),
20                "DEL" => command = Some(Command::DEL),
21                "RPUSH" => command = Some(Command::RPUSH),
22                "LRANGE" => command = Some(Command::LRANGE),
23                "INCR" => command = Some(Command::INCR),
24                "INCRBY" => command = Some(Command::INCRBY),
25                "DECR" => command = Some(Command::DECR),
26                "DECRBY" => command = Some(Command::DECRBY),
27                "EXPIRE" => command = Some(Command::EXPIRE),
28                "CONFIG" => command = Some(Command::CONFIG),
29                "COMMAND" => command = Some(Command::COMMAND),
30                "PUBLISH" => command = Some(Command::PUBLISH),
31                "SUBSCRIBE" => command = Some(Command::SUBSCRIBE),
32                other => {
33                    panic!("{other} command not implemented!");
34                }
35            }
36        } else if i == 4 {
37            key = splitted[i].into();
38        } else {
39            value.push(splitted[i].into())
40        }
41    }
42    match command {
43        Some(command) => {
44            if let Command::SUBSCRIBE = command {
45                value.insert(0, key);
46                // Remove duplicates as it's the official Redis behavior
47                let set: HashSet<_> = value.drain(..).collect();
48                value.extend(set);
49                key = String::new();
50            }
51            let req = Request {
52                command,
53                key,
54                value,
55            };
56            return req;
57        }
58        None => panic!("Something went wrong with parsing RESP"),
59    }
60}