ronantakizawa/codereview-bench huggingface dataset:
Repository: DiceDB/dice
File: core/store.go (Go)

Code before:
// List all keys in the store by given pattern
func Keys(p string) ([]string, error) {
	var keys []string
	var err error

	withLocks(func() {
		keys = make([]string, 0, len(keypool))
		for k := range keypool {
			if found, e := path.Match(p, k); e != nil {
				err = e
				return
			} else if found {
				keys = append(keys, k)
			}
		}
	}, WithStoreRLock(), WithKeypoolRLock())

	return keys, err
}

// GetDbSize returns all the keys present in the db
func GetDBSize() uint64 {
	var noOfKeys uint64
	withLocks(func() {
		noOfKeys = uint64(len(keypool))
	}, WithStoreRLock(), WithKeypoolLock())
	return noOfKeys
}

// Function to add a new watcher to a query.
func AddWatcher(query DSQLQuery, clientFd int) { //nolint:gocritic
	clients, _ := WatchList.LoadOrStore(query, &sync.Map{})
	clients.(*sync.Map).Store(clientFd, struct{}{})
}

// Function to remove a watcher from a query.
func RemoveWatcher(query DSQLQuery, clientFd int) { //nolint:gocritic
	if clients, ok := WatchList.Load(query); ok {
		clients.(*sync.Map).Delete(clientFd)
		// If no more clients for this query, remove the query from WatchList
		if countClients(clients.(*sync.Map)) == 0 {
			WatchList.Delete(query)
		}
	}
}

// Rename function to implement RENAME functionality using existing helpers
func Rename(sourceKey, destKey string) bool {
	return withLocksReturn(func() bool {
		// If source and destination are the same, do nothing and return true
		if sourceKey == destKey {

Review comment (suggestion):
No need to take a lock on the store since we don't access it. Also, use `WithKeypoolRLock()` (read-lock for keypool instead of write lock)

Code after:
// List all keys in the store by given pattern
func Keys(p string) ([]string, error) {
	var keys []string
	var err error

	withLocks(func() {
		keys = make([]string, 0, len(keypool))
		for k := range keypool {
			if found, e := path.Match(p, k); e != nil {
				err = e
				return
			} else if found {
				keys = append(keys, k)
			}
		}
	}, WithStoreRLock(), WithKeypoolRLock())

	return keys, err
}

// GetDbSize returns number of keys present in the database
func GetDBSize() uint64 {
	var noOfKeys uint64
	withLocks(func() {
		noOfKeys = uint64(len(keypool))
	}, WithKeypoolRLock())
	return noOfKeys
}

// Function to add a new watcher to a query.
func AddWatcher(query DSQLQuery, clientFd int) { //nolint:gocritic
	clients, _ := WatchList.LoadOrStore(query, &sync.Map{})
	clients.(*sync.Map).Store(clientFd, struct{}{})
}

// Function to remove a watcher from a query.
func RemoveWatcher(query DSQLQuery, clientFd int) { //nolint:gocritic
	if clients, ok := WatchList.Load(query); ok {
		clients.(*sync.Map).Delete(clientFd)
		// If no more clients for this query, remove the query from WatchList
		if countClients(clients.(*sync.Map)) == 0 {
			WatchList.Delete(query)
		}
	}
}

// Rename function to implement RENAME functionality using existing helpers
func Rename(sourceKey, destKey string) bool {
	return withLocksReturn(func() bool {
		// If source and destination are the same, do nothing and return true
		if sourceKey == destKey {
Repository: DiceDB/dice
File: core/eval.go (Go)

Code before:

	// return the RESP encoded value
	return Encode(obj.Value, false)
}

// evalJSONTYPE retrieves a JSON value type stored at the specified key
// args must contain at least the key;  (path unused in this implementation)
// Returns RespNIL if key is expired or it does not exist
// Returns encoded error response if incorrect number of arguments
// The RESP value of the key's value type is encoded and then returned
func evalJSONTYPE(args []string) []byte {
	if len(args) < 1 {
		return Encode(errors.New("ERR wrong number of arguments for 'JSON.TYPE' command"), false)
	}
	key := args[0]

	// Default path is root if not specified
	path := defaultRootPath
	if len(args) > 1 {
		path = args[1]
	}
	// Retrieve the object from the database
	obj := Get(key)
	if obj == nil {
		return RespNIL
	}

	jsonData := obj.Value

	// If path is root, return "object" instantly
	if path == defaultRootPath {
		_, err := sonic.Marshal(jsonData)
		if err != nil {
			return Encode(errors.New("ERR could not serialize result"), false)
		}
		return Encode(utils.ObjectType, false)
	}

	// Parse the JSONPath expression
	expr, err := jp.ParseString(path)
	if err != nil {
		return Encode(errors.New("ERR invalid JSONPath"), false)
	}

	results := expr.Get(jsonData)
	if len(results) == 0 {
		return RespNIL
	}
	if len(results) == 1 {
		jsonType := utils.GetJSONFieldType(results[0])
		return Encode(jsonType, false)

Review comment (suggestion):
Please use `assertType` and `assertEncoding` methods to validate the retrieved object's type and encoding.
Return error if the object doesn't have JSON type and encoding.

Code after:

	// return the RESP encoded value
	return Encode(obj.Value, false)
}

// evalJSONTYPE retrieves a JSON value type stored at the specified key
// args must contain at least the key;  (path unused in this implementation)
// Returns RespNIL if key is expired or it does not exist
// Returns encoded error response if incorrect number of arguments
// The RESP value of the key's value type is encoded and then returned
func evalJSONTYPE(args []string) []byte {
	if len(args) < 1 {
		return Encode(errors.New("ERR wrong number of arguments for 'JSON.TYPE' command"), false)
	}
	key := args[0]

	// Default path is root if not specified
	path := defaultRootPath
	if len(args) > 1 {
		path = args[1]
	}
	// Retrieve the object from the database
	obj := Get(key)
	if obj == nil {
		return RespNIL
	}

	err := assertType(obj.TypeEncoding, ObjTypeJSON)
	if err != nil {
		return Encode(err, false)
	}
	err = assertEncoding(obj.TypeEncoding, ObjEncodingJSON)
	if err != nil {
		return Encode(err, false)
	}

	jsonData := obj.Value

	// If path is root, return "object" instantly
	if path == defaultRootPath {
		_, err := sonic.Marshal(jsonData)
		if err != nil {
			return Encode(errors.New("ERR could not serialize result"), false)
		}
		return Encode(constants.ObjectType, false)
	}

	// Parse the JSONPath expression
	expr, err := jp.ParseString(path)
	if err != nil {
		return Encode(errors.New("ERR invalid JSONPath"), false)
Repository: DiceDB/dice
File: core/hmap.go (Go)

Code before:
package core

import (
	"errors"

	orderedmap "github.com/wk8/go-ordered-map/v2"
)

type HMap = *orderedmap.OrderedMap[string, string]

func hashMapBuilder(args []string, currentHashMap HMap) (HMap, int64, error) {
	var hmap HMap
	var numKeysNewlySet int64

	if currentHashMap == nil {
		hmap = orderedmap.New[string, string]()
	} else {
		hmap = currentHashMap
	}

	iter := 1 // NOTE: to move past args[0] (aka key) within args

	for iter <= len(args)-1 {
		if iter < len(args)-1 && iter+1 <= len(args)-1 {
			k := args[iter]
			v := args[iter+1]

			_, present := hmap.Set(k, v)
			if !present {
				numKeysNewlySet++
			}
			iter += 2
		} else {
			return hmap, -1, errors.New("ERR mismatch in number of fields and values provided to HSET")

Review comment (bug):
Any specific reasons for using `orderedMap`? Asking as Redis doesn't [preserve order](https://stackoverflow.com/questions/40643482/redis-inserting-out-of-order-or-sorting-oddly) in case of `HSET`

Code after:
package core

import (
	"fmt"

	"github.com/dicedb/dice/core/diceerrors"
)

type HashMap map[string]string

func (h HashMap) Get(k string) (*string, bool) {
	value, ok := h[k]
	if !ok {
		return nil, false
	}
	return &value, true
}

func (h HashMap) Set(k, v string) (*string, bool) {
	value, ok := h[k]
	if ok {
		oldValue := value
		h[k] = v
		return &oldValue, true
	}

	h[k] = v
	return nil, false
}

func hashMapBuilder(keyValuePairs []string, currentHashMap HashMap) (HashMap, int64, error) {
	var hmap HashMap
	var numKeysNewlySet int64
Repository: DiceDB/dice
File: core/eval.go (Go)

Code before:
// respective values in an hashmap stored at key
//
// This command overwrites the values of specified
// fields that exist in the hash.
//
// If key doesn't exist, a new key holding a hash is created.
//
// Usage: HSET key field value [field value ...]
func evalHSET(args []string, store *Store) []byte {
	if len(args) < 3 {
		return Encode(errors.New("ERR wrong number of arguments for command"), false)
	}

	key := args[0]

	obj := store.Get(key)

	var hashMap HMap
	var numKeys int64

	if obj != nil { // NOTE: add the new keys to the hash map here
		// NOTE: we need to perform a check whether the information
		// stored with the following key is indeed an hashmap
		switch currentVal := obj.Value.(type) {
		case HMap:
			updatedHashMap, lengthKeys, err := hashMapBuilder(args, currentVal)
			if err != nil {
				return Encode(err, false)
			} else {
				hashMap = updatedHashMap
				numKeys = lengthKeys
			}
		default:
			return Encode(errors.New("ERR key provided does not store a hashmap"), false)
		}
	} else {
		newMap, keysInMap, err := hashMapBuilder(args, nil)
		if err != nil {
			return Encode(err, false)
		}
		hashMap = newMap
		numKeys = keysInMap
	}

	hValue := string(Encode(hashMap, false))
	oType, oEnc := deduceTypeEncoding(hValue)

	obj = store.NewObj(hashMap, -1, oType, oEnc)
	store.Put(key, obj)

	return Encode(numKeys, false)

Review comment (refactor):
Can we simplify L2165-L2170 as?
```
hashMap, numKeys, err := hashMapBuilder(args, currentVal)
if err != nil {
    return Encode(err, false)
}

```

Code after:
	_, isExpirySet := getExpiry(obj, store)
	if !isExpirySet {
		return RespMinusOne
	}

	// If the object exists, remove the expiration time
	delExpiry(obj, store)

	return RespOne
}

func evalCOPY(args []string, store *Store) []byte {
	if len(args) < 2 {
		return diceerrors.NewErrArity("COPY")
	}

	isReplace := false

	sourceKey := args[0]
	destinationKey := args[1]
	sourceObj := store.Get(sourceKey)
	if sourceObj == nil {
		return RespZero
	}

	for i := 2; i < len(args); i++ {
		arg := strings.ToUpper(args[i])
		if arg == "REPLACE" {
			isReplace = true
		}
	}

	if isReplace {
		store.Del(destinationKey)
	}

	destinationObj := store.Get(destinationKey)
	if destinationObj != nil {
		return RespZero
	}

	copyObj := sourceObj.DeepCopy()
	if copyObj == nil {
		return RespZero
	}

	exp, ok := getExpiry(sourceObj, store)
	var exDurationMs int64 = -1
	if ok {
		exDurationMs = int64(exp - uint64(utils.GetCurrentTime().UnixMilli()))
	}
Repository: DiceDB/dice
File: core/hmap.go (Go)

Code before:
package core

import (
	"errors"

	orderedmap "github.com/wk8/go-ordered-map/v2"
)

type HMap = *orderedmap.OrderedMap[string, string]

func hashMapBuilder(args []string, currentHashMap HMap) (HMap, int64, error) {
	var hmap HMap
	var numKeysNewlySet int64

	if currentHashMap == nil {
		hmap = orderedmap.New[string, string]()
	} else {
		hmap = currentHashMap
	}

	iter := 1 // NOTE: to move past args[0] (aka key) within args

	for iter <= len(args)-1 {
		if iter < len(args)-1 && iter+1 <= len(args)-1 {
			k := args[iter]
			v := args[iter+1]

			_, present := hmap.Set(k, v)
			if !present {
				numKeysNewlySet++
			}
			iter += 2
		} else {
			return hmap, -1, errors.New("ERR mismatch in number of fields and values provided to HSET")
		}
	}

Review comment (suggestion):
Is passing `args[]` required here? Asking as we're any ways doing `iter := 1`
Instead of passing the entire args slice, shall we pass only pass key-value pairs?
With call as `keyValuePairs := args[1:]`.

Code after:
package core

import (
	"fmt"

	"github.com/dicedb/dice/core/diceerrors"
)

type HashMap map[string]string

func (h HashMap) Get(k string) (*string, bool) {
	value, ok := h[k]
	if !ok {
		return nil, false
	}
	return &value, true
}

func (h HashMap) Set(k, v string) (*string, bool) {
	value, ok := h[k]
	if ok {
		oldValue := value
		h[k] = v
		return &oldValue, true
	}

	h[k] = v
	return nil, false
}

func hashMapBuilder(keyValuePairs []string, currentHashMap HashMap) (HashMap, int64, error) {
	var hmap HashMap
	var numKeysNewlySet int64

	if currentHashMap == nil {
		hmap = make(HashMap)
Repository: DiceDB/dice
File: core/eval.go (Go)

Code before:
				numKeys = lengthKeys
			}
		default:
			return Encode(errors.New("ERR key provided does not store a hashmap"), false)
		}
	} else {
		newMap, keysInMap, err := hashMapBuilder(args, nil)
		if err != nil {
			return Encode(err, false)
		}
		hashMap = newMap
		numKeys = keysInMap
	}

	hValue := string(Encode(hashMap, false))
	oType, oEnc := deduceTypeEncoding(hValue)

	obj = store.NewObj(hashMap, -1, oType, oEnc)
	store.Put(key, obj)

	return Encode(numKeys, false)
}

func evalHGET(args []string, store *Store) []byte {
	if len(args) != 2 {
		return Encode(errors.New("ERR wrong number of arguments for command"), false)
	}

	key := args[0]
	field := args[1]
	var value string

	obj := store.Get(key)

	if obj == nil {
		return RespNIL
	}

	switch currentVal := obj.Value.(type) {
	case HMap:
		val, present := currentVal.Get(field)
		if !present {
			return RespNIL
		}
		value = val
	default:
		return Encode(errors.New("WRONGTYPE Operation against a key holding the wrong kind of value"), false)
	}

	return Encode(value, false)
}

Review comment (suggestion):
We shall use `diceerrors` package for standardization.

Code after:
	}

	if isReplace {
		store.Del(destinationKey)
	}

	destinationObj := store.Get(destinationKey)
	if destinationObj != nil {
		return RespZero
	}

	copyObj := sourceObj.DeepCopy()
	if copyObj == nil {
		return RespZero
	}

	exp, ok := getExpiry(sourceObj, store)
	var exDurationMs int64 = -1
	if ok {
		exDurationMs = int64(exp - uint64(utils.GetCurrentTime().UnixMilli()))
	}

	store.Put(destinationKey, copyObj)

	if exDurationMs > 0 {
		store.setExpiry(copyObj, exDurationMs)
	}
	return RespOne
}

// GETEX key [EX seconds | PX milliseconds | EXAT unix-time-seconds |
// PXAT unix-time-milliseconds | PERSIST]
// Get the value of key and optionally set its expiration.
// GETEX is similar to GET, but is a write command with additional options.
// The GETEX command supports a set of options that modify its behavior:
// EX seconds -- Set the specified expire time, in seconds.
// PX milliseconds -- Set the specified expire time, in milliseconds.
// EXAT timestamp-seconds -- Set the specified Unix time at which the key will expire, in seconds.
// PXAT timestamp-milliseconds -- Set the specified Unix time at which the key will expire, in milliseconds.
// PERSIST -- Remove the time to live associated with the key.
// The RESP value of the key is encoded and then returned
// evalGET returns RespNIL if key is expired or it does not exist
func evalGETEX(args []string, store *Store) []byte {
	if len(args) < 1 {
		return diceerrors.NewErrArity("GETEX")
	}

	var key string = args[0]

	// Get the key from the hash table
	obj := store.Get(key)
Repository: DiceDB/dice
File: core/hmap.go (Go)

Code before:
package core

import (
	"errors"

	orderedmap "github.com/wk8/go-ordered-map/v2"
)

type HMap = *orderedmap.OrderedMap[string, string]

func hashMapBuilder(args []string, currentHashMap HMap) (HMap, int64, error) {
	var hmap HMap
	var numKeysNewlySet int64

	if currentHashMap == nil {
		hmap = orderedmap.New[string, string]()
	} else {
		hmap = currentHashMap
	}

	iter := 1 // NOTE: to move past args[0] (aka key) within args

	for iter <= len(args)-1 {
		if iter < len(args)-1 && iter+1 <= len(args)-1 {
			k := args[iter]
			v := args[iter+1]

			_, present := hmap.Set(k, v)
			if !present {
				numKeysNewlySet++
			}
			iter += 2
		} else {
			return hmap, -1, errors.New("ERR mismatch in number of fields and values provided to HSET")
		}
	}

	return hmap, numKeysNewlySet, nil
}


Review comment (suggestion):
Do not use NOTE annotation for this purpose.
```suggestion
	iter := 1 // to move past args[0] (aka key) within args
```

Code after:
package core

import (
	"fmt"

	"github.com/dicedb/dice/core/diceerrors"
)

type HashMap map[string]string

func (h HashMap) Get(k string) (*string, bool) {
	value, ok := h[k]
	if !ok {
		return nil, false
	}
	return &value, true
}

func (h HashMap) Set(k, v string) (*string, bool) {
	value, ok := h[k]
	if ok {
		oldValue := value
		h[k] = v
		return &oldValue, true
	}

	h[k] = v
	return nil, false
}

func hashMapBuilder(keyValuePairs []string, currentHashMap HashMap) (HashMap, int64, error) {
	var hmap HashMap
	var numKeysNewlySet int64

	if currentHashMap == nil {
		hmap = make(HashMap)
	} else {
		hmap = currentHashMap
	}

	iter := 0
	argLength := len(keyValuePairs)

	for iter <= argLength-1 {
		if iter >= argLength-1 || iter+1 > argLength-1 {
			return hmap, -1, diceerrors.NewErr(fmt.Sprintf(diceerrors.ArityErr, "HSET"))
Repository: DiceDB/dice
File: core/eval.go (Go)

Code before:
// respective values in an hashmap stored at key
//
// This command overwrites the values of specified
// fields that exist in the hash.
//
// If key doesn't exist, a new key holding a hash is created.
//
// Usage: HSET key field value [field value ...]
func evalHSET(args []string, store *Store) []byte {
	if len(args) < 3 {
		return diceerrors.NewErrWithMessage("wrong number of arguments for command")
	}

	key := args[0]

	obj := store.Get(key)

	var hashMap HashMap
	var numKeys int64

	if obj != nil {
		switch currentVal := obj.Value.(type) {
		case HashMap:
			hashMap = currentVal
		default:
			return diceerrors.NewErrWithMessage("key already exists")
		}
	}

	keyValuePairs := args[1:]
	hashMap, numKeys, err := hashMapBuilder(keyValuePairs, hashMap)
	if err != nil {
		return diceerrors.NewErrWithMessage(err.Error())
	}

	hValue := string(Encode(hashMap, false))
	oType, oEnc := deduceTypeEncoding(hValue)

	obj = store.NewObj(hashMap, -1, oType, oEnc)
	store.Put(key, obj)

	return Encode(numKeys, false)
}

func evalObjectIdleTime(key string, store *Store) []byte {
	obj := store.GetNoTouch(key)
	if obj == nil {
		return RespNIL
	}

	return Encode(int64(getIdleTime(obj.LastAccessedAt)), true)

Review comment (bug):
I believe if the key is already associated with another type, it should throw error as below
> (error) WRONGTYPE Operation against a key holding the wrong kind of value
We can do
 `return diceerrors.NewErrWithMessage(diceerrors.WrongTypeErr)`

Code after:
//	RESP encoded -1 in case no expiration is set on the key
func evalPTTL(args []string, store *Store) []byte {
	if len(args) != 1 {
		return diceerrors.NewErrArity("PTTL")
	}

	key := args[0]

	obj := store.Get(key)

	if obj == nil {
		return RespMinusTwo
	}

	exp, isExpirySet := getExpiry(obj, store)

	if !isExpirySet {
		return RespMinusOne
	}

	// compute the time remaining for the key to expire and
	// return the RESP encoded form of it
	durationMs := exp - uint64(utils.GetCurrentTime().UnixMilli())
	return Encode(int64(durationMs), false)
}

// evalHSET sets the specified fields to their
// respective values in an hashmap stored at key
//
// This command overwrites the values of specified
// fields that exist in the hash.
//
// If key doesn't exist, a new key holding a hash is created.
//
// Usage: HSET key field value [field value ...]
func evalHSET(args []string, store *Store) []byte {
	if len(args) < 3 {
		return diceerrors.NewErrArity("HSET")
	}

	key := args[0]

	obj := store.Get(key)

	var hashMap HashMap
	var numKeys int64

	if obj != nil {
		switch currentVal := obj.Value.(type) {
		case HashMap:
			hashMap = currentVal
Repository: DiceDB/dice
File: core/hmap.go (Go)

Code before:
	if ok {
		oldValue := value
		h[k] = v
		return &oldValue, true
	}

	h[k] = v
	return nil, false
}

func hashMapBuilder(keyValuePairs []string, currentHashMap HashMap) (HashMap, int64, error) {
	var hmap HashMap
	var numKeysNewlySet int64

	if currentHashMap == nil {
		hmap = make(HashMap)
	} else {
		hmap = currentHashMap
	}

	iter := 0
	argLength := len(keyValuePairs)

	for iter <= argLength-1 {
		if iter >= argLength-1 || iter+1 > argLength-1 {
			return hmap, -1, errors.New("mismatch in number of fields and values provided to HSET")
		}

		k := keyValuePairs[iter]
		v := keyValuePairs[iter+1]

		_, present := hmap.Set(k, v)
		if !present {
			numKeysNewlySet++
		}
		iter += 2
	}

	return hmap, numKeysNewlySet, nil
}

//nolint:unused
func getValueFromHashMap(key, field string, store *Store) ([]byte, error) {
	var value string

	obj := store.Get(key)

	if obj == nil {
		return RespNIL, nil
	}


Review comment (suggestion):
Error message shouldn't be associated with 1 command type ideally. If we're planning to allow this class to used by other command types like `HMSET, HPERSIST` etc.

Code after:
func (h HashMap) Set(k, v string) (*string, bool) {
	value, ok := h[k]
	if ok {
		oldValue := value
		h[k] = v
		return &oldValue, true
	}

	h[k] = v
	return nil, false
}

func hashMapBuilder(keyValuePairs []string, currentHashMap HashMap) (HashMap, int64, error) {
	var hmap HashMap
	var numKeysNewlySet int64

	if currentHashMap == nil {
		hmap = make(HashMap)
	} else {
		hmap = currentHashMap
	}

	iter := 0
	argLength := len(keyValuePairs)

	for iter <= argLength-1 {
		if iter >= argLength-1 || iter+1 > argLength-1 {
			return hmap, -1, diceerrors.NewErr(fmt.Sprintf(diceerrors.ArityErr, "HSET"))
		}

		k := keyValuePairs[iter]
		v := keyValuePairs[iter+1]

		_, present := hmap.Set(k, v)
		if !present {
			numKeysNewlySet++
		}
		iter += 2
	}

	return hmap, numKeysNewlySet, nil
}

//nolint:unused
func getValueFromHashMap(key, field string, store *Store) ([]byte, error) {
	var value string

	obj := store.Get(key)

	if obj == nil {
		return RespNIL, nil
Repository: DiceDB/dice
File: core/hmap.go (Go)

Code before:
		}
		iter += 2
	}

	return hmap, numKeysNewlySet, nil
}

//nolint:unused
func getValueFromHashMap(key, field string, store *Store) ([]byte, error) {
	var value string

	obj := store.Get(key)

	if obj == nil {
		return RespNIL, nil
	}

	switch currentVal := obj.Value.(type) {
	case HashMap:
		val, present := currentVal.Get(field)
		if !present {
			return RespNIL, nil
		}
		value = *val
	default:
		return nil, errors.New("WRONGTYPE Operation against a key holding the wrong kind of value")
	}

	return []byte(value), nil
}


Review comment (bug):
Instead of `errors.New` we can do `diceerrors.NewErr(diceerrors.WrongTypeErr)`

Code after:
		if !present {
			numKeysNewlySet++
		}
		iter += 2
	}

	return hmap, numKeysNewlySet, nil
}

//nolint:unused
func getValueFromHashMap(key, field string, store *Store) ([]byte, error) {
	var value string

	obj := store.Get(key)

	if obj == nil {
		return RespNIL, nil
	}

	switch currentVal := obj.Value.(type) {
	case HashMap:
		val, present := currentVal.Get(field)
		if !present {
			return RespNIL, nil
		}
		value = *val
	default:
		return nil, diceerrors.NewErr(diceerrors.WrongTypeErr)
	}

	return []byte(value), nil
}