aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go353
1 files changed, 0 insertions, 353 deletions
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())