aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
authoralex <[email protected]>2026-07-05 21:49:42 +0200
committeralex <[email protected]>2026-07-05 21:49:42 +0200
commit99436c327d5204779efe9149cebb0dfa1cec070b (patch)
tree59a4c8243afeb51f6ac2717b35528f5f3dae693e /main.go
parent981ff3f7ed3a5db91dc3d618b9a109379620bffe (diff)
downloadredis-clone-99436c327d5204779efe9149cebb0dfa1cec070b.tar.xz
redis-clone-99436c327d5204779efe9149cebb0dfa1cec070b.zip
added LRANGE keyword and serializeRESP function
Diffstat (limited to 'main.go')
-rw-r--r--main.go78
1 files changed, 78 insertions, 0 deletions
diff --git a/main.go b/main.go
index 96d4b8a..8aa1354 100644
--- a/main.go
+++ b/main.go
@@ -183,6 +183,76 @@ func handleRpush(conn net.Conn, args []string) {
conn.Write([]byte(":" + strconv.Itoa(len(list)) + "\r\n"))
}
+func handleLrange(conn net.Conn, key string, start, stop int) {
+ db.mu.Lock()
+ defer db.mu.Unlock()
+
+ value, exists := db.data[key]
+ if !exists {
+ conn.Write([]byte("*0\r\n"))
+ return
+ }
+
+ typedList, ok := value.([]string)
+ if !ok {
+ conn.Write([]byte("-WRONGTYPE Operation against a key holding the wrong kind of value\r\n"))
+ return
+ }
+
+ size := len(typedList)
+
+ if start < 0 {
+ start += size
+ if start < 0 {
+ start = 0
+ }
+ }
+
+ if stop < 0 {
+ stop += size
+ if stop < 0 {
+ stop = 0
+ }
+ }
+
+ if stop >= size {
+ stop = size - 1
+ }
+
+ if start > stop || start >= size {
+ conn.Write([]byte("*0\r\n"))
+ return
+ }
+
+ resultList := typedList[start : stop+1]
+ conn.Write(serializeRESP(resultList))
+}
+
+func serializeRESP(v any) []byte {
+ switch val := v.(type) {
+ case string:
+ bulkString := fmt.Sprintf("$%d\r\n%s\r\n", len(val), val)
+ return []byte(bulkString)
+ case int:
+ integerString := fmt.Sprintf(":%d\r\n",val)
+ return []byte(integerString)
+ case nil:
+ return []byte("$-1\r\n")
+ case error:
+ errorString := fmt.Sprintf("-ERR %s\r\n",val.Error())
+ return []byte(errorString)
+ case []string:
+ size := len(val)
+ result := []byte(fmt.Sprintf("*%d\r\n", size))
+ for i := 0; i < size; i++ {
+ result = append(result, serializeRESP(val[i])...)
+ }
+ return result
+ default:
+ return []byte("-ERR internal server error: unknown type\r\n")
+ }
+}
+
func parseRESP(reader *bufio.Reader) ([]string, error) {
line, err := reader.ReadString('\n')
if err != nil {
@@ -276,6 +346,14 @@ func handleConnection(conn net.Conn) {
handleFlushall(conn)
case command == "RPUSH" && len(args) >= 3:
handleRpush(conn, args)
+ case command == "LRANGE" && len(args) == 4:
+ start, err1 := strconv.Atoi(args[2])
+ stop, err2 := strconv.Atoi(args[3])
+ if err1 != nil || err2 != nil {
+ conn.Write([]byte("-ERR value is not an integer or out of range\r\n"))
+ break
+ }
+ handleLrange(conn, args[1], start, stop)
default:
conn.Write([]byte("-ERR unknown command or wrong arguments\r\n"))
}