Skip to content

Commit

Permalink
Implementing list commands (#2386)
Browse files Browse the repository at this point in the history
* Go: Implementing List commands

Signed-off-by: Janhavi Gupta <janhavigupta@google.com>
  • Loading branch information
janhavigupta007 authored Oct 11, 2024
1 parent d61ed73 commit 936b70a
Show file tree
Hide file tree
Showing 4 changed files with 571 additions and 1 deletion.
82 changes: 82 additions & 0 deletions go/api/base_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,88 @@ func (client *baseClient) RPush(key string, elements []string) (Result[int64], e
return handleLongResponse(result)
}

func (client *baseClient) LRange(key string, start int64, end int64) ([]Result[string], error) {
result, err := client.executeCommand(C.LRange, []string{key, utils.IntToString(start), utils.IntToString(end)})
if err != nil {
return nil, err
}

return handleStringArrayResponse(result)
}

func (client *baseClient) LIndex(key string, index int64) (Result[string], error) {
result, err := client.executeCommand(C.LIndex, []string{key, utils.IntToString(index)})
if err != nil {
return CreateNilStringResult(), err
}

return handleStringOrNullResponse(result)
}

func (client *baseClient) LTrim(key string, start int64, end int64) (Result[string], error) {
result, err := client.executeCommand(C.LTrim, []string{key, utils.IntToString(start), utils.IntToString(end)})
if err != nil {
return CreateNilStringResult(), err
}

return handleStringResponse(result)
}

func (client *baseClient) LLen(key string) (Result[int64], error) {
result, err := client.executeCommand(C.LLen, []string{key})
if err != nil {
return CreateNilInt64Result(), err
}

return handleLongResponse(result)
}

func (client *baseClient) LRem(key string, count int64, element string) (Result[int64], error) {
result, err := client.executeCommand(C.LRem, []string{key, utils.IntToString(count), element})
if err != nil {
return CreateNilInt64Result(), err
}

return handleLongResponse(result)
}

func (client *baseClient) RPop(key string) (Result[string], error) {
result, err := client.executeCommand(C.RPop, []string{key})
if err != nil {
return CreateNilStringResult(), err
}

return handleStringOrNullResponse(result)
}

func (client *baseClient) RPopCount(key string, count int64) ([]Result[string], error) {
result, err := client.executeCommand(C.RPop, []string{key, utils.IntToString(count)})
if err != nil {
return nil, err
}

return handleStringArrayOrNullResponse(result)
}

func (client *baseClient) LInsert(
key string,
insertPosition InsertPosition,
pivot string,
element string,
) (Result[int64], error) {
insertPositionStr, err := insertPosition.toString()
if err != nil {
return CreateNilInt64Result(), err
}

result, err := client.executeCommand(C.LInsert, []string{key, insertPositionStr, pivot, element})
if err != nil {
return CreateNilInt64Result(), err
}

return handleLongResponse(result)
}

func (client *baseClient) Ping() (string, error) {
result, err := client.executeCommand(C.Ping, []string{})
if err != nil {
Expand Down
25 changes: 25 additions & 0 deletions go/api/command_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,28 @@ const (
RankKeyword string = "RANK" // Valkey API keyword use to determine the rank of the match to return.
MaxLenKeyword string = "MAXLEN" // Valkey API keyword used to determine the maximum number of list items to compare.
)

// A InsertPosition defines where to insert new elements into a list.
//
// See [valkey.io]
//
// [valkey.io]: https://valkey.io/commands/linsert/
type InsertPosition string

const (
// Insert new element before the pivot.
Before InsertPosition = "BEFORE"
// Insert new element after the pivot.
After InsertPosition = "AFTER"
)

func (insertPosition InsertPosition) toString() (string, error) {
switch insertPosition {
case Before:
return string(Before), nil
case After:
return string(After), nil
default:
return "", &RequestError{"Invalid insert position"}
}
}
194 changes: 194 additions & 0 deletions go/api/list_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,198 @@ type ListCommands interface {
//
// [valkey.io]: https://valkey.io/commands/rpush/
RPush(key string, elements []string) (Result[int64], error)

// Returns the specified elements of the list stored at key.
// The offsets start and end are zero-based indexes, with 0 being the first element of the list, 1 being the next element
// and so on. These offsets can also be negative numbers indicating offsets starting at the end of the list, with -1 being
// the last element of the list, -2 being the penultimate, and so on.
//
// See [valkey.io] for details.
//
// Parameters:
// key - The key of the list.
// start - The starting point of the range.
// end - The end of the range.
//
// Return value:
// Array of elements as Result[string] in the specified range.
// If start exceeds the end of the list, or if start is greater than end, an empty array will be returned.
// If end exceeds the actual end of the list, the range will stop at the actual end of the list.
// If key does not exist an empty array will be returned.
//
// For example:
// 1. result, err := client.LRange("my_list", 0, 2)
// result: []api.Result[string]{api.CreateStringResult("value1"), api.CreateStringResult("value2"),
// api.CreateStringResult("value3")}
// 2. result, err := client.LRange("my_list", -2, -1)
// result: []api.Result[string]{api.CreateStringResult("value2"), api.CreateStringResult("value3")}
// 3. result, err := client.LRange("non_existent_key", 0, 2)
// result: []api.Result[string]{}
//
// [valkey.io]: https://valkey.io/commands/lrange/
LRange(key string, start int64, end int64) ([]Result[string], error)

// Returns the element at index from the list stored at key.
// The index is zero-based, so 0 means the first element, 1 the second element and so on. Negative indices can be used to
// designate elements starting at the tail of the list. Here, -1 means the last element, -2 means the penultimate and so
// forth.
//
// See [valkey.io] for details.
//
// Parameters:
// key - The key of the list.
// index - The index of the element in the list to retrieve.
//
// Return value:
// The Result[string] containing element at index in the list stored at key.
// If index is out of range or if key does not exist, [api.CreateNilStringResult()] is returned.
//
// For example:
// 1. result, err := client.LIndex("myList", 0)
// result.Value(): "value1" // Returns the first element in the list stored at 'myList'.
// result.IsNil(): false
// 2. result, err := client.LIndex("myList", -1)
// result.Value(): "value3" // Returns the last element in the list stored at 'myList'.
// result.IsNil(): false
//
// [valkey.io]: https://valkey.io/commands/lindex/
LIndex(key string, index int64) (Result[string], error)

// Trims an existing list so that it will contain only the specified range of elements specified.
// The offsets start and end are zero-based indexes, with 0 being the first element of the list, 1 being the next element
// and so on. These offsets can also be negative numbers indicating offsets starting at the end of the list, with -1 being
// the last element of the list, -2 being the penultimate, and so on.
//
// See [valkey.io] for details.
//
// Parameters:
// key - The key of the list.
// start - The starting point of the range.
// end - The end of the range.
//
// Return value:
// The Result[string] containing always "OK".
// If start exceeds the end of the list, or if start is greater than end, the result will be an empty list (which causes
// key to be removed).
// If end exceeds the actual end of the list, it will be treated like the last element of the list.
// If key does not exist, OK will be returned without changes to the database.
//
// For example:
// result, err := client.LTrim("my_list", 0, 1)
// result.Value(): "OK"
// result.IsNil(): false
//
// [valkey.io]: https://valkey.io/commands/ltrim/
LTrim(key string, start int64, end int64) (Result[string], error)

// Returns the length of the list stored at key.
//
// See [valkey.io] for details.
//
// Parameters:
// key - The key of the list.
//
// Return value:
// The Result[int64] containing the length of the list at key.
// If key does not exist, it is interpreted as an empty list and 0 is returned.
//
// For example:
// result, err := client.LLen("my_list")
// result.Value(): int64(3) // Indicates that there are 3 elements in the list.
// result.IsNil(): false
//
// [valkey.io]: https://valkey.io/commands/llen/
LLen(key string) (Result[int64], error)

// Removes the first count occurrences of elements equal to element from the list stored at key.
// If count is positive: Removes elements equal to element moving from head to tail.
// If count is negative: Removes elements equal to element moving from tail to head.
// If count is 0 or count is greater than the occurrences of elements equal to element, it removes all elements equal to
// element.
//
// See [valkey.io] for details.
//
// Parameters:
// key - The key of the list.
// count - The count of the occurrences of elements equal to element to remove.
// element - The element to remove from the list.
//
// Return value:
// The Result[int64] containing the number of the removed elements.
// If key does not exist, 0 is returned.
//
// For example:
// result, err := client.LRem("my_list", 2, "value")
// result.Value(): int64(2)
// result.IsNil(): false
//
// [valkey.io]: https://valkey.io/commands/lrem/
LRem(key string, count int64, element string) (Result[int64], error)

// Removes and returns the last elements of the list stored at key.
// The command pops a single element from the end of the list.
//
// See [valkey.io] for details.
//
// Parameters:
// key - The key of the list.
//
// Return value:
// The Result[string] containing the value of the last element.
// If key does not exist, [api.CreateNilStringResult()] will be returned.
//
// For example:
// 1. result, err := client.RPop("my_list")
// result.Value(): "value1"
// result.IsNil(): false
// 2. result, err := client.RPop("non_exiting_key")
// result.Value(): ""
// result.IsNil(): true
//
// [valkey.io]: https://valkey.io/commands/rpop/
RPop(key string) (Result[string], error)

// Removes and returns up to count elements from the list stored at key, depending on the list's length.
//
// See [valkey.io] for details.
//
// Parameters:
// key - The key of the list.
// count - The count of the elements to pop from the list.
//
// Return value:
// An array of popped elements as Result[string] will be returned depending on the list's length.
// If key does not exist, nil will be returned.
//
// For example:
// 1. result, err := client.RPopCount("my_list", 2)
// result: []api.Result[string]{api.CreateStringResult("value1"), api.CreateStringResult("value2")}
// 2. result, err := client.RPop("non_exiting_key")
// result: nil
//
// [valkey.io]: https://valkey.io/commands/rpop/
RPopCount(key string, count int64) ([]Result[string], error)

// Inserts element in the list at key either before or after the pivot.
//
// See [valkey.io] for details.
//
// Parameters:
// key - The key of the list.
// insertPosition - The relative position to insert into - either api.Before or api.After the pivot.
// pivot - An element of the list.
// element - The new element to insert.
//
// Return value:
// The Result[int64] containing the list length after a successful insert operation.
// If the key doesn't exist returns -1.
// If the pivot wasn't found, returns 0.
//
// For example:
// "my_list": {"Hello", "Wprld"}
// result, err := client.LInsert("my_list", api.Before, "World", "There")
// result.Value(): 3
//
// [valkey.io]: https://valkey.io/commands/linsert/
LInsert(key string, insertPosition InsertPosition, pivot string, element string) (Result[int64], error)
}
Loading

0 comments on commit 936b70a

Please sign in to comment.