Welcome to mirror list, hosted at ThFree Co, Russian Federation.

request_factory.go « protoregistry « praefect « internal - gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 20e702b20595c4e3d9e87bc67b22bdb41e91ca4d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package protoregistry

import (
	"fmt"
	"reflect"
	"strings"

	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/protoc-gen-go/descriptor"
)

// requestFactory returns a function to allocate a new instance of the request
// message type for an RPC method. This is useful in gRPC components that treat
// messages generically, like a stream interceptor.
func requestFactory(mdp *descriptor.MethodDescriptorProto) (func() (proto.Message, error), error) {
	// not sure why this has a leading dot
	reqTypeName := strings.TrimPrefix(mdp.GetInputType(), ".")

	reqType := proto.MessageType(reqTypeName)
	if reqType == nil {
		return nil, fmt.Errorf("unable to retrieve protobuf message type for %s", reqTypeName)
	}

	factory := func() (proto.Message, error) {
		newReq := reflect.New(reqType.Elem())

		val, ok := newReq.Interface().(proto.Message)
		if !ok {
			return nil, fmt.Errorf("method request factory does not return proto message: %#v", newReq)
		}

		return val, nil
	}

	// does the factory actually work? kick the tires...
	if _, err := factory(); err != nil {
		return nil, fmt.Errorf("defective factory function: %q", err)
	}

	return factory, nil
}