From f00398f4be24b5c3cce52c36dc71a42d1d0ccfbe Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 6 Jul 2026 13:35:07 +0200 Subject: split the code into multiple files for better readability --- main.go | 353 ---------------------------------------------------------------- 1 file changed, 353 deletions(-) (limited to 'main.go') diff --git a/main.go b/main.go index 2fd1bd3..81ff1fc 100644 --- a/main.go +++ b/main.go @@ -3,21 +3,12 @@ package main import ( "bufio" "fmt" - "io" "net" "os" "strconv" "strings" - "sync" - "errors" ) -type RedisDB struct { - mu sync.Mutex - data map[string]any -} - -type SimpleString string var db RedisDB @@ -42,350 +33,6 @@ func main() { } } -func handleGet(conn net.Conn, key string) { - db.mu.Lock() - defer db.mu.Unlock() - - value, exists := db.data[key] - if !exists { - conn.Write(serializeRESP(nil)) - return - } - - strValue, ok := value.(string) - if !ok { - err := errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - conn.Write(serializeRESP(err)) - return - } - - conn.Write(serializeRESP(strValue)) -} - -func handleExists(conn net.Conn, key string) { - db.mu.Lock() - defer db.mu.Unlock() - - _, exists := db.data[key] - if exists { - conn.Write(serializeRESP(1)) - } else { - conn.Write(serializeRESP(0)) - } -} - -func handleSet(conn net.Conn, key, value string) { - db.mu.Lock() - defer db.mu.Unlock() - - db.data[key] = value - conn.Write(serializeRESP(SimpleString("OK"))) -} - -func handleDel(conn net.Conn, key string) { - db.mu.Lock() - defer db.mu.Unlock() - - _, exists := db.data[key] - if exists { - delete(db.data, key) - conn.Write(serializeRESP(1)) - } else { - conn.Write(serializeRESP(0)) - } -} - -func handleIncr(conn net.Conn, key string) { - db.mu.Lock() - defer db.mu.Unlock() - - value, exists := db.data[key] - if exists { - strValue, ok := value.(string) - if !ok { - err := errors.New("value is not an integer or out of range") - conn.Write(serializeRESP(err)) - return - } - - currentInt, err := strconv.Atoi(strValue) - if err != nil { - err := errors.New("value is not an integer or out of range") - conn.Write(serializeRESP(err)) - return - } - - newValueStr := strconv.Itoa(currentInt + 1) - db.data[key] = newValueStr - conn.Write(serializeRESP(currentInt + 1)) - } else { - db.data[key] = "1" - conn.Write(serializeRESP(1)) - } -} - -func handleDecr(conn net.Conn, key string) { - db.mu.Lock() - defer db.mu.Unlock() - - value, exists := db.data[key] - if exists { - strValue, ok := value.(string) - if !ok { - err := errors.New("value is not an integer or out of range") - conn.Write(serializeRESP(err)) - return - } - - currentInt, err := strconv.Atoi(strValue) - if err != nil { - err := errors.New("value is not an integer or out of range") - conn.Write(serializeRESP(err)) - return - } - - newValueStr := strconv.Itoa(currentInt - 1) - db.data[key] = newValueStr - conn.Write(serializeRESP(currentInt - 1)) - } else { - db.data[key] = "-1" - conn.Write(serializeRESP(-1)) - } -} - -func handlePing(conn net.Conn) { - conn.Write(serializeRESP(SimpleString("PONG"))) -} - -func handleFlushall(conn net.Conn) { - db.mu.Lock() - defer db.mu.Unlock() - - db.data = make(map[string]any) - conn.Write(serializeRESP(SimpleString("OK"))) -} - -func handleRpush(conn net.Conn, args []string) { - key := args[1] - newItems := args[2:] - - db.mu.Lock() - defer db.mu.Unlock() - - var list []string - existingValue, exists := db.data[key] - - if exists { - var ok bool - list, ok = existingValue.([]string) - if !ok { - err := errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - conn.Write(serializeRESP(err)) - return - } - } else { - list = []string{} - } - list = append(list, newItems...) - db.data[key] = list - conn.Write(serializeRESP(len(list))) -} - -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(serializeRESP([]string{})) - - return - } - - typedList, ok := value.([]string) - if !ok { - err := errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - conn.Write(serializeRESP(err)) - 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(serializeRESP([]string{})) - return - } - - resultList := typedList[start : stop+1] - conn.Write(serializeRESP(resultList)) -} - -func handleLpop(conn net.Conn, key string){ - db.mu.Lock() - defer db.mu.Unlock() - - value, exists := db.data[key] - if !exists { - conn.Write(serializeRESP(nil)) - return - } - - typedList, ok := value.([]string) - if !ok { - err := errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - conn.Write(serializeRESP(err)) - return - } - - if len(typedList) == 0 { - conn.Write(serializeRESP(nil)) - return - } - - item := typedList[0] - newList := typedList[1:] - if len(newList) <= 0 { - delete(db.data, key) - }else{ - db.data[key] = newList - } - conn.Write(serializeRESP(item)) - -} - -func handleRpop(conn net.Conn, key string){ - db.mu.Lock() - defer db.mu.Unlock() - - value, exists := db.data[key] - if !exists { - conn.Write(serializeRESP(nil)) - return - } - - typedList, ok := value.([]string) - if !ok { - err := errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") - conn.Write(serializeRESP(err)) - return - } - - if len(typedList) == 0 { - conn.Write(serializeRESP(nil)) - return - } - - item := typedList[len(typedList)-1] - newList := typedList[:len(typedList)-1] - if len(newList) <= 0 { - delete(db.data, key) - }else{ - db.data[key] = newList - } - conn.Write(serializeRESP(item)) - -} - -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 - case SimpleString: - simpleStr := fmt.Sprintf("+%s\r\n", val) - return []byte(simpleStr) - 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 { - return nil, err - } - - if len(line) == 0 { - return nil, fmt.Errorf("empty line") - } - - switch line[0] { - case '*': - var args []string - argC, _ := strconv.Atoi(strings.TrimSpace(line[1:])) - - for i := 0; i < argC; i++ { - nestedArgs, err := parseRESP(reader) - if err != nil { - return nil, err - } - - args = append(args, nestedArgs...) - } - return args, nil - case '$': - strLen, _ := strconv.Atoi(strings.TrimSpace(line[1:])) - - if strLen == -1 { - return []string{""}, nil - } - - buf := make([]byte, strLen) - - _, err = io.ReadFull(reader, buf) - if err != nil { - return nil, err - } - - _, err = reader.Discard(2) - if err != nil { - return nil, err - } - - return []string{string(buf)}, nil - case '+': - cleanStr := strings.TrimSpace(line[1:]) - return []string{cleanStr}, nil - case ':': - return []string{strings.TrimSpace(line[1:])}, nil - default: - return nil, fmt.Errorf("unknown command type: %c", line[0]) - } -} - func handleConnection(conn net.Conn) { defer conn.Close() fmt.Println("Client connected:", conn.RemoteAddr()) -- cgit v1.2.3