Skip to content

Commit

Permalink
Allow passing empty/nil params in case all are optional (#1078)
Browse files Browse the repository at this point in the history
  • Loading branch information
kirugan authored Aug 16, 2023
1 parent 20e96ff commit 9fbb30c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 2 deletions.
22 changes: 20 additions & 2 deletions jsonrpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,15 @@ func (s *Server) handleRequest(ctx context.Context, req *request) (*response, er

func (s *Server) buildArguments(ctx context.Context, params any, method Method) ([]reflect.Value, error) {
if isNil(params) {
if len(method.Params) > 0 {
allParamsAreOptional := utils.All(method.Params, func(p Parameter) bool {
return p.Optional
})

if len(method.Params) > 0 && !allParamsAreOptional {
return nil, errors.New("missing non-optional param field")
}

return make([]reflect.Value, 0), nil
return s.buildDefaultArguments(ctx, method)
}

handlerType := reflect.TypeOf(method.Handler)
Expand Down Expand Up @@ -423,6 +427,20 @@ func (s *Server) buildArguments(ctx context.Context, params any, method Method)
return args, nil
}

func (s *Server) buildDefaultArguments(_ context.Context, method Method) ([]reflect.Value, error) {
handlerType := reflect.TypeOf(method.Handler)

numArgs := handlerType.NumIn()
args := make([]reflect.Value, 0, numArgs)

for i := 0; i < numArgs; i++ {
arg := reflect.New(handlerType.In(i)).Elem()
args = append(args, arg)
}

return args, nil
}

func (s *Server) parseParam(param any, t reflect.Type) (reflect.Value, error) {
handlerParam := reflect.New(t)
valueMarshaled, err := json.Marshal(param) // we have to marshal the value into JSON again
Expand Down
5 changes: 5 additions & 0 deletions utils/slices.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@ func IndexFunc[T comparable](slice []T, f func(T) bool) int {

return -1
}

// All returns true if all elements match the given predicate
func All[T comparable](slice []T, f func(T) bool) bool {
return IndexFunc(slice, func(e T) bool { return !f(e) }) == -1
}
24 changes: 24 additions & 0 deletions utils/slices_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,27 @@ func TestIndexFunc(t *testing.T) {
assert.Equal(t, 2, idx)
})
}

func TestAll(t *testing.T) {
t.Run("nil slice", func(t *testing.T) {
var input []int
allValue := All(input, func(int) bool {
return false
})
assert.True(t, allValue)
})
t.Run("no element matches the predicate", func(t *testing.T) {
input := []int{1, 2, 3, 4}
allEven := All(input, func(v int) bool {
return v%2 == 0
})
assert.False(t, allEven)
})
t.Run("all elements match the predicate", func(t *testing.T) {
input := []int{1, 3, 5, 7}
allOdd := All(input, func(v int) bool {
return v%2 != 0
})
assert.True(t, allOdd)
})
}

0 comments on commit 9fbb30c

Please sign in to comment.