func Check(fn interface{}) (*FuncInfo, error) {
	if fn == nil {
		return nil, errors.New("nil function")
	}
	info := &FuncInfo{Type: reflect.TypeOf(fn), fn: fn}
	if info.Type.Kind() != reflect.Func {
		return nil, errors.New("not a function")
	}
	if np := info.Type.NumIn(); np == 0 || np > 2 {
		return nil, errors.New("wrong number of parameters")
	} else if info.Type.In(0) != ctxType {
		return nil, errors.New("first parameter is not context.Context")
	} else if info.Type.IsVariadic() {
		return nil, errors.New("variadic functions are not supported")
	} else if np == 2 {
		info.Argument = info.Type.In(1)
	}
	no := info.Type.NumOut()
	if no < 1 || no > 2 {
		return nil, errors.New("wrong number of results")
	} else if no == 2 && info.Type.Out(1) != errType {
		return nil, errors.New("result is not of type error")
	}
	info.ReportsError = info.Type.Out(no-1) == errType
	if no == 2 || !info.ReportsError {
		info.Result = info.Type.Out(0)
	}
	return info, nil
}
Check checks whether fn can serve as a jrpc2.Handler.  The concrete value of
fn must be a function with one of the following type signature schemes, for
JSON-marshalable types X and Y:

func(context.Context) error
func(context.Context) Y
func(context.Context) (Y, error)
func(context.Context, X) error
func(context.Context, X) Y
func(context.Context, X) (Y, error)
func(context.Context, *jrpc2.Request) error
func(context.Context, *jrpc2.Request) Y
func(context.Context, *jrpc2.Request) (Y, error)
func(context.Context, *jrpc2.Request) (interface{}, error)

If fn does not have one of these forms, Check reports an error.

Note that the JSON-RPC standard restricts encoded parameter values to arrays
and objects.  Check will accept argument types that do not encode to arrays
or objects, but the wrapper will report an error when decoding the request.

The recommended solution is to define a struct type for your parameters.
For arbitrary single value types, however, another approach is to wrap it in
a 1-element array, for example:

func(ctx context.Context, sp [1]string) error {
s := sp[0] // pull the actual argument out of the array
// ...
}
package handler
import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"sort"
	"strings"
	"github.com/creachadair/jrpc2"
	"github.com/creachadair/jrpc2/code"
)
type Func func(context.Context, *jrpc2.Request) (interface{}, error)
func (m Func) Handle(ctx context.Context, req *jrpc2.Request) (interface{}, error) {
	return m(ctx, req)
}
type Map map[string]jrpc2.Handler
func (m Map) Assign(_ context.Context, method string) jrpc2.Handler { return m[method] }
func (m Map) Names() []string {
	var names []string
	for name := range m {
		names = append(names, name)
	}
	sort.Strings(names)
	return names
}
type ServiceMap map[string]jrpc2.Assigner
func (m ServiceMap) Assign(ctx context.Context, method string) jrpc2.Handler {
	parts := strings.SplitN(method, ".", 2)
	if len(parts) == 1 {
		return nil
	} else if ass, ok := m[parts[0]]; ok {
		return ass.Assign(ctx, parts[1])
	}
	return nil
}
func (m ServiceMap) Names() []string {
	var all []string
	for svc, assigner := range m {
		for _, name := range assigner.Names() {
			all = append(all, svc+"."+name)
		}
	}
	sort.Strings(all)
	return all
}
func New(fn interface{}) Func {
	fi, err := Check(fn)
	if err != nil {
		panic(err)
	}
	return fi.Wrap()
}
var (
	ctxType = reflect.TypeOf((*context.Context)(nil)).Elem()  
	errType = reflect.TypeOf((*error)(nil)).Elem()            
	reqType = reflect.TypeOf((*jrpc2.Request)(nil))           
	strictType = reflect.TypeOf((*interface{ DisallowUnknownFields() })(nil)).Elem()
	errNoParameters = &jrpc2.Error{Code: code.InvalidParams, Message: "no parameters accepted"}
)
type FuncInfo struct {
	Type         reflect.Type  
	Argument     reflect.Type  
	Result       reflect.Type  
	ReportsError bool          
	strictFields bool          
	fn interface{}  
}
func (fi *FuncInfo) Wrap() Func {
	if fi == nil || fi.fn == nil {
		panic("handler: invalid FuncInfo value")
	}
	if f, ok := fi.fn.(func(context.Context, *jrpc2.Request) (interface{}, error)); ok {
		return Func(f)
	}
	wrapArg := func(v reflect.Value) interface{} { return v.Interface() }
	if fi.strictFields && !fi.Argument.Implements(strictType) {
		wrapArg = func(v reflect.Value) interface{} { return &strict{v.Interface()} }
	}
	var newInput func(ctx reflect.Value, req *jrpc2.Request) ([]reflect.Value, error)
	if fi.Argument == nil {
		newInput = func(ctx reflect.Value, req *jrpc2.Request) ([]reflect.Value, error) {
			if req.HasParams() {
				return nil, errNoParameters
			}
			return []reflect.Value{ctx}, nil
		}
	} else if fi.Argument == reqType {
		newInput = func(ctx reflect.Value, req *jrpc2.Request) ([]reflect.Value, error) {
			return []reflect.Value{ctx, reflect.ValueOf(req)}, nil
		}
	} else if fi.Argument.Kind() == reflect.Ptr {
		newInput = func(ctx reflect.Value, req *jrpc2.Request) ([]reflect.Value, error) {
			in := reflect.New(fi.Argument.Elem())
			if err := req.UnmarshalParams(wrapArg(in)); err != nil {
				return nil, jrpc2.Errorf(code.InvalidParams, "invalid parameters: %v", err)
			}
			return []reflect.Value{ctx, in}, nil
		}
	} else {
		newInput = func(ctx reflect.Value, req *jrpc2.Request) ([]reflect.Value, error) {
			in := reflect.New(fi.Argument)  
			if err := req.UnmarshalParams(wrapArg(in)); err != nil {
				return nil, jrpc2.Errorf(code.InvalidParams, "invalid parameters: %v", err)
			}
			return []reflect.Value{ctx, in.Elem()}, nil
		}
	}
	var decodeOut func([]reflect.Value) (interface{}, error)
	if fi.Result == nil {
		decodeOut = func(vals []reflect.Value) (interface{}, error) {
			oerr := vals[0].Interface()
			if oerr != nil {
				return nil, oerr.(error)
			}
			return nil, nil
		}
	} else if !fi.ReportsError {
		decodeOut = func(vals []reflect.Value) (interface{}, error) {
			return vals[0].Interface(), nil
		}
	} else {
		decodeOut = func(vals []reflect.Value) (interface{}, error) {
			if oerr := vals[1].Interface(); oerr != nil {
				return nil, oerr.(error)
			}
			return vals[0].Interface(), nil
		}
	}
	call := reflect.ValueOf(fi.fn).Call
	return Func(func(ctx context.Context, req *jrpc2.Request) (interface{}, error) {
		args, ierr := newInput(reflect.ValueOf(ctx), req)
		if ierr != nil {
			return nil, ierr
		}
		return decodeOut(call(args))
	})
}