diff --git a/drpc.go b/drpc.go index 12b86e0..0828df8 100644 --- a/drpc.go +++ b/drpc.go @@ -30,6 +30,11 @@ type Transport interface { // This exists so that one can use whatever protobuf library/runtime they want. type Message interface{} +type VTProtoMessage interface { + FromVTPool() interface{} + ReturnToVTPool() +} + // Conn represents a client connection to a server. type Conn interface { // Close closes the connection. diff --git a/drpcmux/handle_rpc.go b/drpcmux/handle_rpc.go index 9bc6c12..ee3ec14 100644 --- a/drpcmux/handle_rpc.go +++ b/drpcmux/handle_rpc.go @@ -18,11 +18,29 @@ func (m *Mux) HandleRPC(stream drpc.Stream, rpc string) (err error) { return drpc.ProtocolError.New("unknown rpc: %q", rpc) } - in := interface{}(stream) + var ( + in = interface{}(stream) + msg drpc.Message + ) if data.in1 != streamType { - msg, ok := reflect.New(data.in1.Elem()).Interface().(drpc.Message) - if !ok { - return drpc.InternalError.New("invalid rpc input type") + // If its an vtprotobuf supported message type + if data.in1.Implements(vtMessageType) { + p := reflect.New(data.in1.Elem()).Interface().(drpc.VTProtoMessage).FromVTPool() + if p == nil { + return drpc.InternalError.New("unable to get message from vt pool") + } + msg, ok = p.(drpc.Message) + if !ok { + return drpc.InternalError.New("invalid rpc input type") + } + + defer p.(drpc.VTProtoMessage).ReturnToVTPool() + } else { + m, ok := reflect.New(data.in1.Elem()).Interface().(drpc.Message) + if !ok { + return drpc.InternalError.New("invalid rpc input type") + } + msg = m } if err := stream.MsgRecv(msg, data.enc); err != nil { return errs.Wrap(err) diff --git a/drpcmux/mux.go b/drpcmux/mux.go index 50ca443..a552928 100644 --- a/drpcmux/mux.go +++ b/drpcmux/mux.go @@ -25,8 +25,9 @@ func New() *Mux { } var ( - streamType = reflect.TypeOf((*drpc.Stream)(nil)).Elem() - messageType = reflect.TypeOf((*drpc.Message)(nil)).Elem() + streamType = reflect.TypeOf((*drpc.Stream)(nil)).Elem() + messageType = reflect.TypeOf((*drpc.Message)(nil)).Elem() + vtMessageType = reflect.TypeOf((*drpc.VTProtoMessage)(nil)).Elem() ) type rpcData struct { diff --git a/examples/drpc/pb/sesamestreet.pb.go b/examples/drpc/pb/sesamestreet.pb.go index 741afe3..68df099 100644 --- a/examples/drpc/pb/sesamestreet.pb.go +++ b/examples/drpc/pb/sesamestreet.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.21.12 +// protoc v4.25.3 // source: sesamestreet.proto package pb diff --git a/examples/drpc/pb/sesamestreet_drpc.pb.go b/examples/drpc/pb/sesamestreet_drpc.pb.go index ac4b759..833bb61 100644 --- a/examples/drpc/pb/sesamestreet_drpc.pb.go +++ b/examples/drpc/pb/sesamestreet_drpc.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-drpc. DO NOT EDIT. -// protoc-gen-go-drpc version: (devel) +// protoc-gen-go-drpc version: v0.0.33 // source: sesamestreet.proto package pb diff --git a/examples/drpc/pb/storj.io/drpc/examples/drpc/pb/sesamestreet_vtproto.pb.go b/examples/drpc/pb/storj.io/drpc/examples/drpc/pb/sesamestreet_vtproto.pb.go new file mode 100644 index 0000000..3f1923a --- /dev/null +++ b/examples/drpc/pb/storj.io/drpc/examples/drpc/pb/sesamestreet_vtproto.pb.go @@ -0,0 +1,285 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: v0.6.0 +// source: sesamestreet.proto + +package pb + +import ( + fmt "fmt" + protohelpers "github.com/planetscale/vtprotobuf/protohelpers" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *Cookie) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Cookie) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Cookie) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Type != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Crumbs) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Crumbs) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Crumbs) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Cookie != nil { + size, err := m.Cookie.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Cookie) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Type != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Type)) + } + n += len(m.unknownFields) + return n +} + +func (m *Crumbs) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Cookie != nil { + l = m.Cookie.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *Cookie) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Cookie: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Cookie: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= Cookie_Type(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Crumbs) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Crumbs: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Crumbs: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Cookie", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Cookie == nil { + m.Cookie = &Cookie{} + } + if err := m.Cookie.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/examples/drpc_vtproto/README.md b/examples/drpc_vtproto/README.md new file mode 100644 index 0000000..e466d62 --- /dev/null +++ b/examples/drpc_vtproto/README.md @@ -0,0 +1,16 @@ +# DRPC example + +This example is a bare-bones DRPC use case. It is intended +to show the minimal differences from the gRPC basic example. + + +``` +protoc --go_out=paths=source_relative:. --plugin protoc-gen-go="${GOPATH}/bin/protoc-gen-go" \ + --go-grpc_out=paths=source_relative:. --plugin protoc-gen-go-grpc="${GOPATH}/bin/protoc-gen-go-grpc" \ + --go-drpc_out=paths=source_relative:. --plugin protoc-gen-go-drpc="${GOPATH}/bin/protoc-gen-go-drpc" \ + --go-vtproto_out=paths=source_relative:. --plugin protoc-gen-go-vtproto="${GOPATH}/bin/protoc-gen-go-vtproto" \ + --go-vtproto_opt=pool=storj.io/drpc/examples/drpc_vtproto/pb.Cookie \ + --go-vtproto_opt=pool=storj.io/drpc/examples/drpc_vtproto/pb.CookiePool \ + --go-vtproto_opt=features=marshal+unmarshal+equal+clone+size+pool \ + sesamestreet.proto +``` diff --git a/examples/drpc_vtproto/client/main.go b/examples/drpc_vtproto/client/main.go new file mode 100644 index 0000000..4104eff --- /dev/null +++ b/examples/drpc_vtproto/client/main.go @@ -0,0 +1,57 @@ +// Copyright (C) 2021 Storj Labs, Inc. +// See LICENSE for copying information. + +package main + +import ( + "context" + "fmt" + "net" + "time" + + "storj.io/drpc/drpcconn" + + "storj.io/drpc/examples/drpc_vtproto/pb" +) + +func main() { + err := Main(context.Background()) + if err != nil { + panic(err) + } +} + +func Main(ctx context.Context) error { + // dial the drpc server + rawconn, err := net.Dial("tcp", "localhost:8080") + if err != nil { + return err + } + // N.B.: If you want TLS, you need to wrap the net.Conn with TLS before + // making a DRPC conn. + + // convert the net.Conn to a drpc.Conn + conn := drpcconn.New(rawconn) + defer conn.Close() + + // make a drpc proto-specific client + client := pb.NewDRPCCookieMonsterClient(conn) + + // set a deadline for the operation + ctx, cancel := context.WithTimeout(ctx, time.Second) + defer cancel() + + // run the RPC + crumbs, err := client.EatCookie(ctx, &pb.CookiePool{ + Cookie: &pb.Cookie{ + Type: pb.Cookie_Oatmeal, + }, + }) + if err != nil { + return err + } + + // check the results + _, err = fmt.Println(crumbs.Cookie.Type.String()) + return err +} diff --git a/examples/drpc_vtproto/client/main_test.go b/examples/drpc_vtproto/client/main_test.go new file mode 100644 index 0000000..6421001 --- /dev/null +++ b/examples/drpc_vtproto/client/main_test.go @@ -0,0 +1,34 @@ +package main + +import ( + "reflect" + "testing" + "unsafe" +) + +var C any + +type CookiePool struct { + Cookie *Cookie +} + +type Cookie struct { + A, B, C, D, E, F, G, H, I string + Z [10]byte +} + +func BenchmarkAllocate(b *testing.B) { + var cookie *CookiePool + in1 := reflect.TypeOf(cookie) + + for j := 0; j < b.N; j++ { + for i := 0; i < 1000; i++ { + C = reflect.New(in1.Elem()).Interface() + } + } + + b.Logf("size %d", in1.Size()) + b.Logf("unsafe size %d", unsafe.Sizeof(cookie)) + b.Logf("unsafe size %d", unsafe.Sizeof(reflect.New(in1.Elem()))) + b.Logf("Cookie: %+v, %t", C, C) +} diff --git a/examples/drpc_vtproto/go.mod b/examples/drpc_vtproto/go.mod new file mode 100644 index 0000000..99c4946 --- /dev/null +++ b/examples/drpc_vtproto/go.mod @@ -0,0 +1,21 @@ +module storj.io/drpc/examples/drpc_vtproto + +go 1.19 + +require ( + github.com/planetscale/vtprotobuf v0.6.0 + google.golang.org/grpc v1.62.0 + google.golang.org/protobuf v1.32.0 + storj.io/drpc v0.0.17 +) + +require ( + github.com/golang/protobuf v1.5.3 // indirect + github.com/zeebo/errs v1.2.2 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect +) + +replace storj.io/drpc => ../.. diff --git a/examples/drpc_vtproto/go.sum b/examples/drpc_vtproto/go.sum new file mode 100644 index 0000000..93a8983 --- /dev/null +++ b/examples/drpc_vtproto/go.sum @@ -0,0 +1,62 @@ +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/planetscale/vtprotobuf v0.6.0 h1:nBeETjudeJ5ZgBHUz1fVHvbqUKnYOXNhsIEabROxmNA= +github.com/planetscale/vtprotobuf v0.6.0/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/spacemonkeygo/monkit/v3 v3.0.7/go.mod h1:kj1ViJhlyADa7DiA4xVnTuPA46lFKbM7mxQTrXCuJP4= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= +github.com/zeebo/errs v1.2.2 h1:5NFypMTuSdoySVTqlNs1dEoU21QVamMQJxW/Fii5O7g= +github.com/zeebo/errs v1.2.2/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +storj.io/drpc v0.0.17/go.mod h1:BfRXHVXDa/CLZNFgnyShsOi90LdMtA6X/aj/tZAjFbk= diff --git a/examples/drpc_vtproto/pb/gen.go b/examples/drpc_vtproto/pb/gen.go new file mode 100644 index 0000000..d59eb0b --- /dev/null +++ b/examples/drpc_vtproto/pb/gen.go @@ -0,0 +1,7 @@ +// Copyright (C) 2021 Storj Labs, Inc. +// See LICENSE for copying information. + +// Package pb includes protobufs for this example. +package pb + +//go:generate protoc --go_out=paths=source_relative:. --go-drpc_out=paths=source_relative:. --go-vtproto_out=. --plugin protoc-gen-go-vtproto="${GOBIN/protoc-gen-go-vtproto}" sesamestreet.proto diff --git a/examples/drpc_vtproto/pb/sesamestreet.go b/examples/drpc_vtproto/pb/sesamestreet.go new file mode 100644 index 0000000..6d1c23b --- /dev/null +++ b/examples/drpc_vtproto/pb/sesamestreet.go @@ -0,0 +1,20 @@ +package pb + +import ( + "storj.io/drpc" +) + +var _ drpc.VTProtoMessage = &Cookie{} +var _ drpc.VTProtoMessage = &CookiePool{} + +func (m *Cookie) FromVTPool() interface{} { + mm := CookieFromVTPool() + m = mm + return m +} + +func (m *CookiePool) FromVTPool() interface{} { + mm := CookiePoolFromVTPool() + m = mm + return m +} diff --git a/examples/drpc_vtproto/pb/sesamestreet.pb.go b/examples/drpc_vtproto/pb/sesamestreet.pb.go new file mode 100644 index 0000000..dcf2051 --- /dev/null +++ b/examples/drpc_vtproto/pb/sesamestreet.pb.go @@ -0,0 +1,340 @@ +// Copyright (C) 2021 Storj Labs, Inc. +// See LICENSE for copying information. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v4.25.3 +// source: sesamestreet.proto + +package pb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Cookie_Type int32 + +const ( + Cookie_Sugar Cookie_Type = 0 + Cookie_Oatmeal Cookie_Type = 1 + Cookie_Chocolate Cookie_Type = 2 +) + +// Enum value maps for Cookie_Type. +var ( + Cookie_Type_name = map[int32]string{ + 0: "Sugar", + 1: "Oatmeal", + 2: "Chocolate", + } + Cookie_Type_value = map[string]int32{ + "Sugar": 0, + "Oatmeal": 1, + "Chocolate": 2, + } +) + +func (x Cookie_Type) Enum() *Cookie_Type { + p := new(Cookie_Type) + *p = x + return p +} + +func (x Cookie_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Cookie_Type) Descriptor() protoreflect.EnumDescriptor { + return file_sesamestreet_proto_enumTypes[0].Descriptor() +} + +func (Cookie_Type) Type() protoreflect.EnumType { + return &file_sesamestreet_proto_enumTypes[0] +} + +func (x Cookie_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Cookie_Type.Descriptor instead. +func (Cookie_Type) EnumDescriptor() ([]byte, []int) { + return file_sesamestreet_proto_rawDescGZIP(), []int{1, 0} +} + +type CookiePool struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cookie *Cookie `protobuf:"bytes,1,opt,name=cookie,proto3" json:"cookie,omitempty"` +} + +func (x *CookiePool) Reset() { + *x = CookiePool{} + if protoimpl.UnsafeEnabled { + mi := &file_sesamestreet_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CookiePool) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CookiePool) ProtoMessage() {} + +func (x *CookiePool) ProtoReflect() protoreflect.Message { + mi := &file_sesamestreet_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CookiePool.ProtoReflect.Descriptor instead. +func (*CookiePool) Descriptor() ([]byte, []int) { + return file_sesamestreet_proto_rawDescGZIP(), []int{0} +} + +func (x *CookiePool) GetCookie() *Cookie { + if x != nil { + return x.Cookie + } + return nil +} + +type Cookie struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type Cookie_Type `protobuf:"varint,1,opt,name=type,proto3,enum=sesamestreet.Cookie_Type" json:"type,omitempty"` +} + +func (x *Cookie) Reset() { + *x = Cookie{} + if protoimpl.UnsafeEnabled { + mi := &file_sesamestreet_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Cookie) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Cookie) ProtoMessage() {} + +func (x *Cookie) ProtoReflect() protoreflect.Message { + mi := &file_sesamestreet_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Cookie.ProtoReflect.Descriptor instead. +func (*Cookie) Descriptor() ([]byte, []int) { + return file_sesamestreet_proto_rawDescGZIP(), []int{1} +} + +func (x *Cookie) GetType() Cookie_Type { + if x != nil { + return x.Type + } + return Cookie_Sugar +} + +type Crumbs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cookie *Cookie `protobuf:"bytes,1,opt,name=cookie,proto3" json:"cookie,omitempty"` +} + +func (x *Crumbs) Reset() { + *x = Crumbs{} + if protoimpl.UnsafeEnabled { + mi := &file_sesamestreet_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Crumbs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Crumbs) ProtoMessage() {} + +func (x *Crumbs) ProtoReflect() protoreflect.Message { + mi := &file_sesamestreet_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Crumbs.ProtoReflect.Descriptor instead. +func (*Crumbs) Descriptor() ([]byte, []int) { + return file_sesamestreet_proto_rawDescGZIP(), []int{2} +} + +func (x *Crumbs) GetCookie() *Cookie { + if x != nil { + return x.Cookie + } + return nil +} + +var File_sesamestreet_proto protoreflect.FileDescriptor + +var file_sesamestreet_proto_rawDesc = []byte{ + 0x0a, 0x12, 0x73, 0x65, 0x73, 0x61, 0x6d, 0x65, 0x73, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x73, 0x65, 0x73, 0x61, 0x6d, 0x65, 0x73, 0x74, 0x72, 0x65, + 0x65, 0x74, 0x22, 0x3a, 0x0a, 0x0a, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x50, 0x6f, 0x6f, 0x6c, + 0x12, 0x2c, 0x0a, 0x06, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x73, 0x65, 0x73, 0x61, 0x6d, 0x65, 0x73, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2e, + 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x22, 0x66, + 0x0a, 0x06, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x73, 0x65, 0x73, 0x61, 0x6d, 0x65, 0x73, + 0x74, 0x72, 0x65, 0x65, 0x74, 0x2e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x2e, 0x54, 0x79, 0x70, + 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2d, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x09, 0x0a, 0x05, 0x53, 0x75, 0x67, 0x61, 0x72, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x61, + 0x74, 0x6d, 0x65, 0x61, 0x6c, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x68, 0x6f, 0x63, 0x6f, + 0x6c, 0x61, 0x74, 0x65, 0x10, 0x02, 0x22, 0x36, 0x0a, 0x06, 0x43, 0x72, 0x75, 0x6d, 0x62, 0x73, + 0x12, 0x2c, 0x0a, 0x06, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x73, 0x65, 0x73, 0x61, 0x6d, 0x65, 0x73, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2e, + 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x32, 0x4e, + 0x0a, 0x0d, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x4d, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x72, 0x12, + 0x3d, 0x0a, 0x09, 0x45, 0x61, 0x74, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x12, 0x18, 0x2e, 0x73, + 0x65, 0x73, 0x61, 0x6d, 0x65, 0x73, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2e, 0x43, 0x6f, 0x6f, 0x6b, + 0x69, 0x65, 0x50, 0x6f, 0x6f, 0x6c, 0x1a, 0x14, 0x2e, 0x73, 0x65, 0x73, 0x61, 0x6d, 0x65, 0x73, + 0x74, 0x72, 0x65, 0x65, 0x74, 0x2e, 0x43, 0x72, 0x75, 0x6d, 0x62, 0x73, 0x22, 0x00, 0x42, 0x28, + 0x5a, 0x26, 0x73, 0x74, 0x6f, 0x72, 0x6a, 0x2e, 0x69, 0x6f, 0x2f, 0x64, 0x72, 0x70, 0x63, 0x2f, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x64, 0x72, 0x70, 0x63, 0x5f, 0x76, 0x74, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_sesamestreet_proto_rawDescOnce sync.Once + file_sesamestreet_proto_rawDescData = file_sesamestreet_proto_rawDesc +) + +func file_sesamestreet_proto_rawDescGZIP() []byte { + file_sesamestreet_proto_rawDescOnce.Do(func() { + file_sesamestreet_proto_rawDescData = protoimpl.X.CompressGZIP(file_sesamestreet_proto_rawDescData) + }) + return file_sesamestreet_proto_rawDescData +} + +var file_sesamestreet_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_sesamestreet_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_sesamestreet_proto_goTypes = []interface{}{ + (Cookie_Type)(0), // 0: sesamestreet.Cookie.Type + (*CookiePool)(nil), // 1: sesamestreet.CookiePool + (*Cookie)(nil), // 2: sesamestreet.Cookie + (*Crumbs)(nil), // 3: sesamestreet.Crumbs +} +var file_sesamestreet_proto_depIdxs = []int32{ + 2, // 0: sesamestreet.CookiePool.cookie:type_name -> sesamestreet.Cookie + 0, // 1: sesamestreet.Cookie.type:type_name -> sesamestreet.Cookie.Type + 2, // 2: sesamestreet.Crumbs.cookie:type_name -> sesamestreet.Cookie + 1, // 3: sesamestreet.CookieMonster.EatCookie:input_type -> sesamestreet.CookiePool + 3, // 4: sesamestreet.CookieMonster.EatCookie:output_type -> sesamestreet.Crumbs + 4, // [4:5] is the sub-list for method output_type + 3, // [3:4] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_sesamestreet_proto_init() } +func file_sesamestreet_proto_init() { + if File_sesamestreet_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_sesamestreet_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CookiePool); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_sesamestreet_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Cookie); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_sesamestreet_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Crumbs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_sesamestreet_proto_rawDesc, + NumEnums: 1, + NumMessages: 3, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_sesamestreet_proto_goTypes, + DependencyIndexes: file_sesamestreet_proto_depIdxs, + EnumInfos: file_sesamestreet_proto_enumTypes, + MessageInfos: file_sesamestreet_proto_msgTypes, + }.Build() + File_sesamestreet_proto = out.File + file_sesamestreet_proto_rawDesc = nil + file_sesamestreet_proto_goTypes = nil + file_sesamestreet_proto_depIdxs = nil +} diff --git a/examples/drpc_vtproto/pb/sesamestreet.proto b/examples/drpc_vtproto/pb/sesamestreet.proto new file mode 100644 index 0000000..83be488 --- /dev/null +++ b/examples/drpc_vtproto/pb/sesamestreet.proto @@ -0,0 +1,29 @@ +// Copyright (C) 2021 Storj Labs, Inc. +// See LICENSE for copying information. + +syntax = "proto3"; +option go_package = "storj.io/drpc/examples/drpc_vtproto/pb"; + +package sesamestreet; + +message CookiePool { + Cookie cookie = 1; +} + +message Cookie { + enum Type { + Sugar = 0; + Oatmeal = 1; + Chocolate = 2; + } + + Type type = 1; +} + +message Crumbs { + Cookie cookie = 1; +} + +service CookieMonster { + rpc EatCookie(CookiePool) returns (Crumbs) {} +} diff --git a/examples/drpc_vtproto/pb/sesamestreet_drpc.pb.go b/examples/drpc_vtproto/pb/sesamestreet_drpc.pb.go new file mode 100644 index 0000000..2dab3da --- /dev/null +++ b/examples/drpc_vtproto/pb/sesamestreet_drpc.pb.go @@ -0,0 +1,111 @@ +// Code generated by protoc-gen-go-drpc. DO NOT EDIT. +// protoc-gen-go-drpc version: v0.0.33 +// source: sesamestreet.proto + +package pb + +import ( + context "context" + errors "errors" + protojson "google.golang.org/protobuf/encoding/protojson" + proto "google.golang.org/protobuf/proto" + drpc "storj.io/drpc" + drpcerr "storj.io/drpc/drpcerr" +) + +type drpcEncoding_File_sesamestreet_proto struct{} + +func (drpcEncoding_File_sesamestreet_proto) Marshal(msg drpc.Message) ([]byte, error) { + return proto.Marshal(msg.(proto.Message)) +} + +func (drpcEncoding_File_sesamestreet_proto) MarshalAppend(buf []byte, msg drpc.Message) ([]byte, error) { + return proto.MarshalOptions{}.MarshalAppend(buf, msg.(proto.Message)) +} + +func (drpcEncoding_File_sesamestreet_proto) Unmarshal(buf []byte, msg drpc.Message) error { + return proto.Unmarshal(buf, msg.(proto.Message)) +} + +func (drpcEncoding_File_sesamestreet_proto) JSONMarshal(msg drpc.Message) ([]byte, error) { + return protojson.Marshal(msg.(proto.Message)) +} + +func (drpcEncoding_File_sesamestreet_proto) JSONUnmarshal(buf []byte, msg drpc.Message) error { + return protojson.Unmarshal(buf, msg.(proto.Message)) +} + +type DRPCCookieMonsterClient interface { + DRPCConn() drpc.Conn + + EatCookie(ctx context.Context, in *CookiePool) (*Crumbs, error) +} + +type drpcCookieMonsterClient struct { + cc drpc.Conn +} + +func NewDRPCCookieMonsterClient(cc drpc.Conn) DRPCCookieMonsterClient { + return &drpcCookieMonsterClient{cc} +} + +func (c *drpcCookieMonsterClient) DRPCConn() drpc.Conn { return c.cc } + +func (c *drpcCookieMonsterClient) EatCookie(ctx context.Context, in *CookiePool) (*Crumbs, error) { + out := new(Crumbs) + err := c.cc.Invoke(ctx, "/sesamestreet.CookieMonster/EatCookie", drpcEncoding_File_sesamestreet_proto{}, in, out) + if err != nil { + return nil, err + } + return out, nil +} + +type DRPCCookieMonsterServer interface { + EatCookie(context.Context, *CookiePool) (*Crumbs, error) +} + +type DRPCCookieMonsterUnimplementedServer struct{} + +func (s *DRPCCookieMonsterUnimplementedServer) EatCookie(context.Context, *CookiePool) (*Crumbs, error) { + return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented) +} + +type DRPCCookieMonsterDescription struct{} + +func (DRPCCookieMonsterDescription) NumMethods() int { return 1 } + +func (DRPCCookieMonsterDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) { + switch n { + case 0: + return "/sesamestreet.CookieMonster/EatCookie", drpcEncoding_File_sesamestreet_proto{}, + func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) { + return srv.(DRPCCookieMonsterServer). + EatCookie( + ctx, + in1.(*CookiePool), + ) + }, DRPCCookieMonsterServer.EatCookie, true + default: + return "", nil, nil, nil, false + } +} + +func DRPCRegisterCookieMonster(mux drpc.Mux, impl DRPCCookieMonsterServer) error { + return mux.Register(impl, DRPCCookieMonsterDescription{}) +} + +type DRPCCookieMonster_EatCookieStream interface { + drpc.Stream + SendAndClose(*Crumbs) error +} + +type drpcCookieMonster_EatCookieStream struct { + drpc.Stream +} + +func (x *drpcCookieMonster_EatCookieStream) SendAndClose(m *Crumbs) error { + if err := x.MsgSend(m, drpcEncoding_File_sesamestreet_proto{}); err != nil { + return err + } + return x.CloseSend() +} diff --git a/examples/drpc_vtproto/pb/sesamestreet_grpc.pb.go b/examples/drpc_vtproto/pb/sesamestreet_grpc.pb.go new file mode 100644 index 0000000..ebedc1f --- /dev/null +++ b/examples/drpc_vtproto/pb/sesamestreet_grpc.pb.go @@ -0,0 +1,105 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v4.25.3 +// source: sesamestreet.proto + +package pb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// CookieMonsterClient is the client API for CookieMonster service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type CookieMonsterClient interface { + EatCookie(ctx context.Context, in *CookiePool, opts ...grpc.CallOption) (*Crumbs, error) +} + +type cookieMonsterClient struct { + cc grpc.ClientConnInterface +} + +func NewCookieMonsterClient(cc grpc.ClientConnInterface) CookieMonsterClient { + return &cookieMonsterClient{cc} +} + +func (c *cookieMonsterClient) EatCookie(ctx context.Context, in *CookiePool, opts ...grpc.CallOption) (*Crumbs, error) { + out := new(Crumbs) + err := c.cc.Invoke(ctx, "/sesamestreet.CookieMonster/EatCookie", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// CookieMonsterServer is the server API for CookieMonster service. +// All implementations must embed UnimplementedCookieMonsterServer +// for forward compatibility +type CookieMonsterServer interface { + EatCookie(context.Context, *CookiePool) (*Crumbs, error) + mustEmbedUnimplementedCookieMonsterServer() +} + +// UnimplementedCookieMonsterServer must be embedded to have forward compatible implementations. +type UnimplementedCookieMonsterServer struct { +} + +func (UnimplementedCookieMonsterServer) EatCookie(context.Context, *CookiePool) (*Crumbs, error) { + return nil, status.Errorf(codes.Unimplemented, "method EatCookie not implemented") +} +func (UnimplementedCookieMonsterServer) mustEmbedUnimplementedCookieMonsterServer() {} + +// UnsafeCookieMonsterServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to CookieMonsterServer will +// result in compilation errors. +type UnsafeCookieMonsterServer interface { + mustEmbedUnimplementedCookieMonsterServer() +} + +func RegisterCookieMonsterServer(s grpc.ServiceRegistrar, srv CookieMonsterServer) { + s.RegisterService(&CookieMonster_ServiceDesc, srv) +} + +func _CookieMonster_EatCookie_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CookiePool) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CookieMonsterServer).EatCookie(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/sesamestreet.CookieMonster/EatCookie", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CookieMonsterServer).EatCookie(ctx, req.(*CookiePool)) + } + return interceptor(ctx, in, info, handler) +} + +// CookieMonster_ServiceDesc is the grpc.ServiceDesc for CookieMonster service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var CookieMonster_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "sesamestreet.CookieMonster", + HandlerType: (*CookieMonsterServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "EatCookie", + Handler: _CookieMonster_EatCookie_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "sesamestreet.proto", +} diff --git a/examples/drpc_vtproto/pb/sesamestreet_vtproto.pb.go b/examples/drpc_vtproto/pb/sesamestreet_vtproto.pb.go new file mode 100644 index 0000000..412dc93 --- /dev/null +++ b/examples/drpc_vtproto/pb/sesamestreet_vtproto.pb.go @@ -0,0 +1,581 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: v0.6.0 +// source: sesamestreet.proto + +package pb + +import ( + fmt "fmt" + protohelpers "github.com/planetscale/vtprotobuf/protohelpers" + proto "google.golang.org/protobuf/proto" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *CookiePool) CloneVT() *CookiePool { + if m == nil { + return (*CookiePool)(nil) + } + r := CookiePoolFromVTPool() + r.Cookie = m.Cookie.CloneVT() + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *CookiePool) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *Cookie) CloneVT() *Cookie { + if m == nil { + return (*Cookie)(nil) + } + r := CookieFromVTPool() + r.Type = m.Type + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *Cookie) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *Crumbs) CloneVT() *Crumbs { + if m == nil { + return (*Crumbs)(nil) + } + r := new(Crumbs) + r.Cookie = m.Cookie.CloneVT() + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *Crumbs) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (this *CookiePool) EqualVT(that *CookiePool) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if !this.Cookie.EqualVT(that.Cookie) { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *CookiePool) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*CookiePool) + if !ok { + return false + } + return this.EqualVT(that) +} +func (this *Cookie) EqualVT(that *Cookie) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.Type != that.Type { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *Cookie) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*Cookie) + if !ok { + return false + } + return this.EqualVT(that) +} +func (this *Crumbs) EqualVT(that *Crumbs) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if !this.Cookie.EqualVT(that.Cookie) { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *Crumbs) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*Crumbs) + if !ok { + return false + } + return this.EqualVT(that) +} +func (m *CookiePool) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CookiePool) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *CookiePool) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Cookie != nil { + size, err := m.Cookie.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Cookie) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Cookie) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Cookie) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Type != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Crumbs) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Crumbs) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Crumbs) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Cookie != nil { + size, err := m.Cookie.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +var vtprotoPool_CookiePool = sync.Pool{ + New: func() interface{} { + return &CookiePool{} + }, +} + +func (m *CookiePool) ResetVT() { + if m != nil { + m.Cookie.ReturnToVTPool() + m.Reset() + } +} +func (m *CookiePool) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_CookiePool.Put(m) + } +} +func CookiePoolFromVTPool() *CookiePool { + return vtprotoPool_CookiePool.Get().(*CookiePool) +} + +var vtprotoPool_Cookie = sync.Pool{ + New: func() interface{} { + return &Cookie{} + }, +} + +func (m *Cookie) ResetVT() { + if m != nil { + m.Reset() + } +} +func (m *Cookie) ReturnToVTPool() { + if m != nil { + m.ResetVT() + vtprotoPool_Cookie.Put(m) + } +} +func CookieFromVTPool() *Cookie { + return vtprotoPool_Cookie.Get().(*Cookie) +} +func (m *CookiePool) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Cookie != nil { + l = m.Cookie.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *Cookie) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Type != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Type)) + } + n += len(m.unknownFields) + return n +} + +func (m *Crumbs) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Cookie != nil { + l = m.Cookie.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *CookiePool) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CookiePool: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CookiePool: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Cookie", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Cookie == nil { + m.Cookie = CookieFromVTPool() + } + if err := m.Cookie.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Cookie) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Cookie: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Cookie: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= Cookie_Type(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Crumbs) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Crumbs: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Crumbs: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Cookie", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Cookie == nil { + m.Cookie = &Cookie{} + } + if err := m.Cookie.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/examples/drpc_vtproto/server/main.go b/examples/drpc_vtproto/server/main.go new file mode 100644 index 0000000..6c06e2c --- /dev/null +++ b/examples/drpc_vtproto/server/main.go @@ -0,0 +1,61 @@ +// Copyright (C) 2021 Storj Labs, Inc. +// See LICENSE for copying information. + +package main + +import ( + "context" + "net" + + "storj.io/drpc/drpcmux" + "storj.io/drpc/drpcserver" + + "storj.io/drpc/examples/drpc_vtproto/pb" +) + +type CookieMonsterServer struct { + pb.DRPCCookieMonsterUnimplementedServer + // struct fields +} + +// EatCookie turns a cookie into crumbs. +func (s *CookieMonsterServer) EatCookie(ctx context.Context, cookie *pb.CookiePool) (*pb.Crumbs, error) { + return &pb.Crumbs{ + Cookie: cookie.Cookie, + }, nil +} + +func main() { + err := Main(context.Background()) + if err != nil { + panic(err) + } +} + +func Main(ctx context.Context) error { + // create an RPC server + cookieMonster := &CookieMonsterServer{} + + // create a drpc RPC mux + m := drpcmux.New() + + // register the proto-specific methods on the mux + err := pb.DRPCRegisterCookieMonster(m, cookieMonster) + if err != nil { + return err + } + + // create a drpc server + s := drpcserver.New(m) + + // listen on a tcp socket + lis, err := net.Listen("tcp", ":8080") + if err != nil { + return err + } + + // run the server + // N.B.: if you want TLS, you need to wrap the net.Listener with + // TLS before passing to Serve here. + return s.Serve(ctx, lis) +}