protoc-gen-psrpc (#3)

* protoc-gen-psrpc

* static check

* install protoc-gen-go, add generate workflow

* combine actions

* add more testing

* increate test timeouts

* add small wait after subscribing

* errors
This commit is contained in:
David Colburn
2022-12-22 11:47:34 -08:00
committed by GitHub
parent 2296750065
commit f879402619
108 changed files with 7220 additions and 667 deletions
+20 -15
View File
@@ -3,22 +3,18 @@ name: Test
on:
workflow_dispatch:
push:
branches: [ main ]
pull_request:
branches: [ main ]
branches-ignore: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
- name: Install Protoc
uses: arduino/setup-protoc@v1
with:
path: |
~/go/pkg/mod
~/go/bin
~/.cache
key: livekit-psrpc
version: '3.x'
- name: Set up Go
uses: actions/setup-go@v3
@@ -28,12 +24,14 @@ jobs:
- name: Download Go modules
run: go mod download
- name: Static Check
uses: dominikh/staticcheck-action@v1.2.0
- name: Install protoc-gen-go
run: go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.1
- name: Generate Protobuf
uses: magefile/mage-action@v2
with:
min-go-version: 1.18
version: 2022.1
install-go: false
version: latest
args: proto
- name: Start Redis
uses: supercharge/[email protected]
@@ -45,4 +43,11 @@ jobs:
uses: magefile/mage-action@v2
with:
version: latest
args: test
args: testall
- name: Add changes
uses: EndBug/add-and-commit@v9
with:
add: livekit
default_author: github_actions
message: generated protobuf
+202 -292
View File
@@ -3,339 +3,249 @@
Create custom protobuf-based golang RPCs built on pub/sub.
Supports:
* Redis or Nats as a backend
* Protobuf service definitions
* Redis or Nats as a communication layer
* Custom server selection for RPC handling based on user-defined [affinity](#Affinity)
* Single RPCs (RequestSingle) - one request is handled by one server, used for normal RPCs
* Multi RPCs (RequestAll) - one request is handled by every server, used for distributed updates or result aggregation
* Single RPC streams (JoinStreamQueue) - updates sent from the server will only be processed by a single client
* Multi RPC streams (JoinStream) - updates sent be the server will be processed by every client
* RPC topics - any RPC can be divided into topics, (e.g. by region)
* Single RPCs - one request is handled by one server, used for normal RPCs
* Multi RPCs - one request is handled by every server, used for distributed updates or result aggregation
* Queue Subscriptions - updates sent from the server will only be processed by a single client
* Subscriptions - updates sent be the server will be processed by every client
## Interfaces
## Usage
### RPCServer
### Protobuf
PSRPC is generated from proto files, and we've added a few custom method options:
```protobuf
message Options {
// For RPCs, each client request will receive a response from every server.
// For subscriptions, every client will receive every update.
bool multi = 1;
// This method is a pub/sub.
bool subscription = 2;
// This method uses topics.
bool topics = 3;
// Your service will supply an affinity function for handler selection.
bool affinity_func = 4;
}
```
Start with your service definition. Here's an example using different method options:
```protobuf
syntax = "proto3";
import "options.proto";
option go_package = "/api";
service MyService {
// A normal RPC - one request, one response. The request will be handled by the first available server
rpc NormalRPC(MyRequest) returns (MyResponse);
// An RPC with a server affinity function for handler selection.
rpc IntensiveRPC(MyRequest) returns (MyResponse) {
option (psrpc.options).affinity_func = true;
};
// A multi-rpc - a client will send one request, and receive one response each from every server
rpc GetStats(MyRequest) returns (MyResponse) {
option (psrpc.options).multi = true;
};
// An RPC with topics - a client can send one request, and receive one response from each server in one region
rpc GetRegionStats(MyRequest) returns (MyResponse) {
option (psrpc.options).topics = true;
option (psrpc.options).multi = true;
}
// A queue subscription - even if multiple clients are subscribed, only one will receive this update.
// The request parameter (in this case, Ignored) will always be ignored when generating go files.
rpc ProcessUpdate(Ignored) returns (MyUpdate) {
option (psrpc.options).subscription = true;
};
// A normal subscription - every client will receive every update.
// The request parameter (in this case, Ignored) will always be ignored when generating go files.
rpc UpdateState(Ignored) returns (MyUpdate) {
option (psrpc.options).subscription = true;
option (psrpc.options).multi = true;
};
// A subscription with topics - every client subscribed to the topic will receive every update.
// The request parameter (in this case, Ignored) will always be ignored when generating go files.
rpc UpdateRegionState(Ignored) returns (MyUpdate) {
option (psrpc.options).subscription = true;
option (psrpc.options).topics = true;
option (psrpc.options).multi = true;
}
}
message Ignored {}
message MyRequest {}
message MyResponse {}
message MyUpdate {}
```
### Generation
Install `protoc-gen-psrpc` by running `go install github.com/livekit/psrpc/protoc-gen-psrpc`.
If using the custom options above, you'll also need to download [options.proto](protoc-gen-psrpc/options/options.proto).
Use the `--psrpc_out` with `protoc` and include the options file.
```shell
protoc \
--go_out=paths=source_relative:. \
--psrpc_out=paths=source_relative:. \
-I ./protoc-gen-psrpc/options \
-I=. my_service.proto
```
This will create a `my_service.psrpc.go` file
### Client
A `MyServiceClient` will be generated based on your rpc definitions:
```go
type RPCServer interface {
// register a handler
RegisterHandler(h Handler) error
type MyServiceClient interface {
// A normal RPC - one request, one response. The request will be handled by the first available server
NormalRPC(ctx context.Context, req *MyRequest, opts ...psrpc.RequestOpt) (*MyResponse, error)
// An RPC with a server affinity function for handler selection.
IntensiveRPC(ctx context.Context, req *MyRequest, opts ...psrpc.RequestOpt) (*MyResponse, error)
// A multi-rpc - a client will send one request, and receive one response each from every server
GetStats(ctx context.Context, req *MyRequest, opts ...psrpc.RequestOpt) (<-chan *psrpc.Response[*MyResponse], error)
// An RPC with topics - a client can send one request, and receive one response from each server in one region
GetRegionStats(ctx context.Context, topic string, req *Request, opts ...psrpc.RequestOpt) (<-chan *psrpc.Response[*MyResponse], error)
// A queue subscription - even if multiple clients are subscribed, only one will receive this update.
SubscribeProcessUpdate(ctx context.Context) (psrpc.Subscription[*MyUpdate], error)
// A subscription with topics - every client subscribed to the topic will receive every update.
SubscribeUpdateRegionState(ctx context.Context, topic string) (psrpc.Subscription[*MyUpdate], error)
}
// publish updates to a streaming rpc
PublishToStream(ctx context.Context, rpc string, message proto.Message) error
// stop listening for requests for a rpc
DeregisterHandler(rpc string) error
// close all subscriptions and stop
Close()
// NewMyServiceClient creates a psrpc client that implements the MyServiceClient interface.
func NewMyServiceClient(clientID string, bus psrpc.MessageBus, opts ...psrpc.ClientOpt) (MyServiceClient, error) {
...
}
```
### RPCClient
Multi-RPCs will return a `chan *psrpc.Response`, where you will receive an individual response or error from each server:
```go
// send a request to a single server, and receive one response
func RequestSingle[ResponseType proto.Message](
ctx context.Context,
client RPCClient,
rpc string,
request proto.Message,
opts ...RequestOption,
) (ResponseType, error)
// send a request to all servers, and receive one response per server
func RequestAll[ResponseType proto.Message](
ctx context.Context,
client RPCClient,
rpc string,
request proto.Message,
opts ...RequestOption,
) (<-chan *Response[ResponseType], error)
// subscribe to a streaming rpc (all subscribed clients will receive every message)
func JoinStream[ResponseType proto.Message](
ctx context.Context,
client RPCClient,
rpc string,
) (Subscription[ResponseType], error)
// join a queue for a streaming rpc (each message is only received by a single client)
func JoinStreamQueue[ResponseType proto.Message](
ctx context.Context,
client RPCClient,
rpc string,
) (Subscription[ResponseType], error)
// types
type Response[ResponseType proto.Message] struct {
Result ResponseType
Err error
}
```
Subscription RPCs will return a `psrpc.Subscription`, where you can listen for updates on its channel:
```go
type Subscription[MessageType proto.Message] interface {
Channel() <-chan MessageType
Close() error
}
```
### ServerImpl
A `<ServiceName>ServerImpl` interface will be also be generated from your rpcs. Your service will need to fulfill its interface:
```go
type MyServiceServerImpl interface {
// A normal RPC - one request, one response. The request will be handled by the first available server
NormalRPC(ctx context.Context, req *MyRequest) (*MyResponse, error)
// An RPC with a server affinity function for handler selection.
IntensiveRPC(ctx context.Context, req *MyRequest) (*MyResponse, error)
IntensiveRPCAffinity(req *MyRequest) float32
// A multi-rpc - a client will send one request, and receive one response each from every server
GetStats(ctx context.Context, req *MyRequest) (*MyResponse, error)
// An RPC with topics - a client can send one request, and receive one response from each server in one region
GetRegionStats(ctx context.Context, req *MyRequest) (*MyResponse, error)
}
```
### Server
Finally, a `<ServiceName>Server` will be generated. This is used to start your rpc server, as well as register and deregister topics:
```go
type MyServiceServer interface {
// An RPC with topics - a client can send one request, and receive one response from each server in one region
RegisterGetRegionStatsTopic(topic string) error
DeregisterGetRegionStatsTopic(topic string) error
// A queue subscription - even if multiple clients are subscribed, only one will receive this update.
PublishProcessUpdate(ctx context.Context, msg *MyUpdate) error
// A subscription with topics - every client subscribed to the topic will receive every update.
PublishUpdateRegionState(ctx context.Context, topic string, msg *MyUpdate) error
}
// NewMyServiceServer builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewMyServiceServer(serverID string, svc MyServiceServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOpt) (MyServiceServer, error) {
...
}
```
## Affinity
### AffinityFunc
The server can register an AffinityFunc for the client to decide which instance should take a SingleRequest.
The server can implement an affinity function for the client to decide which instance should take a SingleRequest.
A higher affinity score is better, and a score of 0 means the server is not available.
For example, the following could be used to return an affinity based on cpu load:
```protobuf
rpc IntensiveRPC(MyRequest) returns (MyResponse) {
option (psrpc.options).affinity_func = true;
};
```
```go
func main() {
...
rpcServer.RegisterHandler(psrpc.NewHandlerWithAffinity("MyRPC", handlerFunc, getAffinity))
...
func (s *MyService) IntensiveRPC(ctx context.Context, req *api.MyRequest) (*api.MyResponse, error) {
... // do something CPU intensive
}
func getAffinity(req *api.Request) float32 {
func (s *MyService) IntensiveRPCAffinity(_ *MyRequest) float32 {
return stats.GetIdleCPU()
}
```
### AffinityOptions
### SelectionOpts
On the client side, you can also set affinity options for server selection with SendSingleRequest.
Affinity options:
* AcceptFirstAvailable: if true, the first server to respond with an affinity greater than 0 and MinimumAffinity will be selected.
* MinimumAffinity: Minimum affinity for a server to be considered a valid handler.
* AffinityTimeout: if AcceptFirstAvailable is false, the client will wait this amount of time, then select the server with the highest affinity score.
* ShortCircuitTimeout: if AcceptFirstAvailable is false, the client will wait this amount of time after receiving its first valid response, then select the server with the highest affinity score.
If no options are supplied, the client will choose the first server to respond with an affinity score > 0.
On the client side, you can also set server selection options with single RPCs.
```go
affinityOpts := psrpc.AffinityOpts{
type SelectionOpts struct {
MinimumAffinity float32 // (default 0) minimum affinity for a server to be considered a valid handler
AcceptFirstAvailable bool // (default true)
AffinityTimeout time.Duration // (default 0 (none)) server selection deadline
ShortCircuitTimeout time.Duration // (default 0 (none)) deadline imposed after receiving first response
}
```
```go
selectionOpts := psrpc.SelectionOpts{
MinimumAffinity: 0.5,
AffinityTimeout: time.Second,
ShortCircuitTimeout: time.Millisecond * 250,
}
res, err := psrpc.RequestSingle[*api.Response](
context.Background(),
rpcClient,
"MyRPC",
&api.Request{},
psrpc.WithAffinityOpts(affinityOpts))
```
For a full example, see the [Advanced example](#Advanced) below.
## Examples
### SingleRequest
Proto:
```protobuf
package api;
message AddRequest {
int32 increment = 1;
}
message AddResult {
int32 value = 1;
}
```
Server:
```go
func main() {
rc := redis.NewUniversalClient(&redis.UniversalOptions{Addrs: []string{"localhost:6379"}})
serverID := "test_server"
rpcServer := psrpc.NewRPCServer("CountingService", serverID, psrpc.NewRedisMessageBus(rc))
svc := &CountingService{}
rpcServer.RegisterHandler(psrpc.NewHandler("AddValue", svc.AddValue))
...
}
type CountingService struct {
counter atomic.Int32
}
func (s *CountingService) AddValue(ctx context.Context, req *api.AddReqest) (*api.AddResult, error) {
value := counter.Add(req.Increment)
return &proto.AddResult{Value: value}, nil
}
```
Client:
```go
func main() {
rc := redis.NewUniversalClient(&redis.UniversalOptions{Addrs: []string{"localhost:6379"}})
clientID := "test_client"
rpcClient := psrpc.NewRPCClient("CountingService", clientID, psrpc.NewRedisMessageBus(rc))
res, err := psrpc.RequestSingle[*api.AddResult](
context.Background(),
rpcClient,
"AddValue",
&api.AddRequest{Increment: 3})
if err != nil {
return
}
fmt.Println(res.Value)
}
```
### MultiRequest
Proto:
```protobuf
package api;
message GetValueRequest {}
message ValueResult {
int32 value = 1;
}
```
Server:
```go
func main() {
rc := redis.NewUniversalClient(&redis.UniversalOptions{Addrs: []string{"localhost:6379"}})
serverID := "test_server"
rpcServer := psrpc.NewRPCServer("CountingService", serverID, psrpc.NewRedisMessageBus(rc))
svc := &Service{}
rpcServer.RegisterHandler(psrpc.NewHandler("GetValue", svc.GetValue))
...
}
type Service struct {
counter atomic.Int32
}
func (s *Service) GetValue(ctx context.Context, req *api.GetValueRequest) (*api.ValueResult, error) {
return &api.ValueResult{Value: s.counter.Load()}, nil
}
```
Client:
```go
func main() {
rc := redis.NewUniversalClient(&redis.UniversalOptions{Addrs: []string{"localhost:6379"}})
clientID := "test_client"
rpcClient := psrpc.NewRPCClient("CountingService", clientID, psrpc.NewRedisMessageBus(rc))
sub, err := psrpc.RequestAll[*api.ValueResult](
context.Background(),
rpcClient,
"GetValue",
&api.GetValueRequest{})
if err != nil {
return
}
defer sub.Close()
total := 0
for {
response, ok := <-sub.Channel()
if !ok {
// channel has been closed
break
}
if response.Err != nil {
fmt.Println("error:", err)
} else {
total += response.Result.Value
}
}
fmt.Println("total:", total)
}
```
### Advanced
Proto:
```protobuf
package api;
message CalculateUserStatsRequest {
int64 from_unix_time = 1;
int64 to_unix_time = 2;
}
message CalculateUserStatsResponse {
int32 unique_users = 1;
int32 new_users = 2;
int32 inactive_users = 3;
int32 daily_active_users = 4;
}
```
Server:
```go
func main() {
svc := NewProcessingService()
rc := redis.NewUniversalClient(&redis.UniversalOptions{Addrs: []string{"localhost:6379"}})
serverID := "test_server"
rpcServer := psrpc.NewRPCServer("ProcessingService", serverID, psrpc.NewRedisMessageBus(rc))
defer rpcServer.Close()
rpcServer.RegisterHandler(psrpc.NewHandlerWithAffinity("CalculateUserStats", svc.CalculateUserStats, getAffinity))
...
}
// The CalculateUserStats rpc requires a lot of CPU - use idle CPUs for the affinity metric
func getAffinity(req *api.CalculateUserStatsRequest) float32 {
return stats.GetIdleCPU()
}
type ProcessingService struct {}
func (s *ProcessingService) CalculateUserStats(ctx context.Context, req *api.CalculateUserStatsRequest) (*api.CalculateUserStatsResponse, error) {
userStats, err := getUserStats(req.FromUnixTime, req.ToUnixTime)
if err != nil {
return nil, err
}
return &api.CalculateUserStatsResponse{
UniqueUsers: userStats.uniqueUsers,
NewUsers: userStats.newUsers,
InactiveUsers: userStats.inactiveUsers,
DailyActiveUsers: userStats.dailyActiveUsers,
}, nil
}
```
Client:
```go
func main() {
rc := redis.NewUniversalClient(&redis.UniversalOptions{Addrs: []string{"localhost:6379"}})
clientID := "test_client"
rpcClient := psrpc.NewRPCClient("ProcessingService", clientID, psrpc.NewRedisMessageBus(rc))
req := &api.CalculateUserStatsRequest{
FromUnixTime: time.Now().Add(-time.Day * 30).UnixNano(),
ToUnixTime: time.Now().UnixNano()
}
// allow one second for server selection, with at least 0.5 cpu available
// once the first valid server is found, selection will occur 250ms later
affinityOpts := psrpc.AffinityOpts{
MinimumAffinity: 0.5,
AffinityTimeout: time.Second,
ShortCircuitTimeout: time.Millisecond * 250,
}
res, err := psrpc.RequestSingle[*api.CalculateUserStatsResponse](
context.Background(),
rpcClient,
"CalculateUserStats",
req,
psrpc.WithAffinityOpts(affinityOpts),
psrpc.WithTimeout(time.Second * 30)) // this query takes a while for larger ranges, use a longer timeout
fmt.Printf("%+v", res)
}
res, err := myClient.IntensiveRPC(ctx, req, psrpc.WithSelectionOpts(selectionOpts))
```
+40 -33
View File
@@ -22,6 +22,46 @@ type MessageBus interface {
getNC() *nats.Conn
}
type Subscription[MessageType proto.Message] interface {
Channel() <-chan MessageType
Close() error
}
var ErrBusNotConnected = errors.New("bus not connected")
func Publish(bus MessageBus, ctx context.Context, channel string, msg proto.Message) error {
switch bus.getBusType() {
case redisBus:
return redisPublish(bus.getRC(), ctx, channel, msg)
case natsBus:
return natsPublish(bus.getNC(), ctx, channel, msg)
default:
return ErrBusNotConnected
}
}
func Subscribe[MessageType proto.Message](bus MessageBus, ctx context.Context, channel string) (Subscription[MessageType], error) {
switch bus.getBusType() {
case redisBus:
return redisSubscribe[MessageType](bus.getRC(), ctx, channel)
case natsBus:
return natsSubscribe[MessageType](bus.getNC(), ctx, channel)
default:
return nil, ErrBusNotConnected
}
}
func SubscribeQueue[MessageType proto.Message](bus MessageBus, ctx context.Context, channel string) (Subscription[MessageType], error) {
switch bus.getBusType() {
case redisBus:
return redisSubscribeQueue[MessageType](bus.getRC(), ctx, channel)
case natsBus:
return natsSubscribeQueue[MessageType](bus.getNC(), ctx, channel)
default:
return nil, ErrBusNotConnected
}
}
type bus struct {
MessageBus
busType
@@ -41,36 +81,3 @@ func (b *bus) getRC() redis.UniversalClient {
func (b *bus) getNC() *nats.Conn {
return b.nc
}
func Publish(bus MessageBus, ctx context.Context, channel string, msg proto.Message) error {
switch bus.getBusType() {
case redisBus:
return redisPublish(bus.getRC(), ctx, channel, msg)
case natsBus:
return natsPublish(bus.getNC(), ctx, channel, msg)
default:
return errors.New("not connected")
}
}
func Subscribe[MessageType proto.Message](bus MessageBus, ctx context.Context, channel string) (Subscription[MessageType], error) {
switch bus.getBusType() {
case redisBus:
return redisSubscribe[MessageType](bus.getRC(), ctx, channel)
case natsBus:
return natsSubscribe[MessageType](bus.getNC(), ctx, channel)
default:
return nil, errors.New("not connected")
}
}
func SubscribeQueue[MessageType proto.Message](bus MessageBus, ctx context.Context, channel string) (Subscription[MessageType], error) {
switch bus.getBusType() {
case redisBus:
return redisSubscribeQueue[MessageType](bus.getRC(), ctx, channel)
case natsBus:
return natsSubscribeQueue[MessageType](bus.getNC(), ctx, channel)
default:
return nil, errors.New("not connected")
}
}
+1
View File
@@ -8,6 +8,7 @@ require (
github.com/lithammer/shortuuid/v3 v3.0.7
github.com/livekit/mageutil v0.0.0-20221002073820-d9198083cfdc
github.com/nats-io/nats.go v1.21.0
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.8.1
google.golang.org/protobuf v1.28.1
)
+2
View File
@@ -34,6 +34,8 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+22 -7
View File
@@ -2,7 +2,6 @@ package psrpc
import (
"fmt"
"strings"
"github.com/lithammer/shortuuid/v3"
"google.golang.org/protobuf/proto"
@@ -13,20 +12,36 @@ func newRequestID() string {
return "REQ_" + shortuuid.New()[:12]
}
func getRPCChannel(serviceName, rpc string) string {
return strings.ToUpper(fmt.Sprintf("%s|%s|REQ", serviceName, rpc))
func getRPCChannel(serviceName, rpc, topic string) string {
if topic != "" {
return fmt.Sprintf("%s|%s|%s|REQ", serviceName, rpc, topic)
} else {
return fmt.Sprintf("%s|%s|REQ", serviceName, rpc)
}
}
func getHandlerKey(rpc, topic string) string {
if topic != "" {
return fmt.Sprintf("%s|%s", rpc, topic)
} else {
return rpc
}
}
func getResponseChannel(serviceName, clientID string) string {
return strings.ToUpper(fmt.Sprintf("%s|%s|RES", serviceName, clientID))
return fmt.Sprintf("%s|%s|RES", serviceName, clientID)
}
func getClaimRequestChannel(serviceName, clientID string) string {
return strings.ToUpper(fmt.Sprintf("%s|%s|CLAIM", serviceName, clientID))
return fmt.Sprintf("%s|%s|CLAIM", serviceName, clientID)
}
func getClaimResponseChannel(serviceName, rpc string) string {
return strings.ToUpper(fmt.Sprintf("%s|%s|RCLAIM", serviceName, rpc))
func getClaimResponseChannel(serviceName, rpc, topic string) string {
if topic != "" {
return fmt.Sprintf("%s|%s|%s|RCLAIM", serviceName, rpc, topic)
} else {
return fmt.Sprintf("%s|%s|RCLAIM", serviceName, rpc)
}
}
func serialize(msg proto.Message) ([]byte, error) {
+32
View File
@@ -0,0 +1,32 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package gen
import (
"log"
"os"
"strings"
)
func Fail(msgs ...string) {
s := strings.Join(msgs, " ")
log.Print("error:", s)
os.Exit(1)
}
func Error(err error, msgs ...string) {
s := strings.Join(msgs, " ") + ":" + err.Error()
log.Print("error:", s)
os.Exit(1)
}
+78
View File
@@ -0,0 +1,78 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package gen
import (
"io"
"os"
"google.golang.org/protobuf/proto"
descriptor "google.golang.org/protobuf/types/descriptorpb"
plugin "google.golang.org/protobuf/types/pluginpb"
)
type Generator interface {
Generate(in *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse
}
func Main(g Generator) {
req := readGenRequest(os.Stdin)
resp := g.Generate(req)
writeResponse(os.Stdout, resp)
}
func FilesToGenerate(req *plugin.CodeGeneratorRequest) []*descriptor.FileDescriptorProto {
genFiles := make([]*descriptor.FileDescriptorProto, 0)
Outer:
for _, name := range req.FileToGenerate {
for _, f := range req.ProtoFile {
if f.GetName() == name {
genFiles = append(genFiles, f)
continue Outer
}
}
Fail("could not find file named", name)
}
return genFiles
}
func readGenRequest(r io.Reader) *plugin.CodeGeneratorRequest {
data, err := io.ReadAll(r)
if err != nil {
Error(err, "reading input")
}
req := new(plugin.CodeGeneratorRequest)
if err = proto.Unmarshal(data, req); err != nil {
Error(err, "parsing input proto")
}
if len(req.FileToGenerate) == 0 {
Fail("no files to generate")
}
return req
}
func writeResponse(w io.Writer, resp *plugin.CodeGeneratorResponse) {
data, err := proto.Marshal(resp)
if err != nil {
Error(err, "marshaling response")
}
_, err = w.Write(data)
if err != nil {
Error(err, "writing response")
}
}
+106
View File
@@ -0,0 +1,106 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package stringutils
import (
"strings"
"unicode"
)
// Is c an ASCII lower-case letter?
func isASCIILower(c byte) bool {
return 'a' <= c && c <= 'z'
}
// Is c an ASCII digit?
func isASCIIDigit(c byte) bool {
return '0' <= c && c <= '9'
}
// CamelCase converts a string from snake_case to CamelCased.
//
// If there is an interior underscore followed by a lower case letter, drop the
// underscore and convert the letter to upper case. There is a remote
// possibility of this rewrite causing a name collision, but it's so remote
// we're prepared to pretend it's nonexistent - since the C++ generator
// lowercases names, it's extremely unlikely to have two fields with different
// capitalizations. In short, _my_field_name_2 becomes XMyFieldName_2.
func CamelCase(s string) string {
if s == "" {
return ""
}
t := make([]byte, 0, 32)
i := 0
if s[0] == '_' {
// Need a capital letter; drop the '_'.
t = append(t, 'X')
i++
}
// Invariant: if the next letter is lower case, it must be converted
// to upper case.
//
// That is, we process a word at a time, where words are marked by _ or upper
// case letter. Digits are treated as words.
for ; i < len(s); i++ {
c := s[i]
if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) {
continue // Skip the underscore in s.
}
if isASCIIDigit(c) {
t = append(t, c)
continue
}
// Assume we have a letter now - if not, it's a bogus identifier. The next
// word is a sequence of characters that must start upper case.
if isASCIILower(c) {
c ^= ' ' // Make it a capital letter.
}
t = append(t, c) // Guaranteed not lower case.
// Accept lower case sequence that follows.
for i+1 < len(s) && isASCIILower(s[i+1]) {
i++
t = append(t, s[i])
}
}
return string(t)
}
// AlphaDigitize replaces non-letter, non-digit, non-underscore characters with
// underscore.
func AlphaDigitize(r rune) rune {
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' {
return r
}
return '_'
}
// CleanIdentifier makes sure s is a valid 'identifier' string: it contains only
// letters, numbers, and underscore.
func CleanIdentifier(s string) string {
return strings.Map(AlphaDigitize, s)
}
// BaseName the last path element of a slash-delimited name, with the last
// dotted suffix removed.
func BaseName(name string) string {
// First, find the last element
if i := strings.LastIndex(name, "/"); i >= 0 {
name = name[i+1:]
}
// Now drop the suffix
if i := strings.LastIndex(name, "."); i >= 0 {
name = name[0:i]
}
return name
}
Binary file not shown.
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package testdata
//go:generate protoc --descriptor_set_out=fileset.pb --include_imports --include_source_info ./service.proto
+11
View File
@@ -0,0 +1,11 @@
syntax = "proto3";
package psrpc.internal.gen.typemap.testdata.importer;
import "root_pkg.proto";
message ImporterMsg {
root_pkg.RootMsg a = 1;
message ImporterInner {}
}
+14
View File
@@ -0,0 +1,14 @@
syntax = "proto3";
package psrpc.internal.gen.typemap.testdata.public_importer;
import public "root_pkg.proto";
import public "importer.proto";
message PublicImporterMsgA {
importer.ImporterMsg a = 1;
}
message PublicImporterMsgB {
root_pkg.RootMsg a = 1;
}
+12
View File
@@ -0,0 +1,12 @@
syntax = "proto3";
package psrpc.internal.gen.typemap.testdata.public_reimporter;
import public "public_importer.proto";
message PublicReimporterMsg {
public_importer.PublicImporterMsgA a = 1;
public_importer.PublicImporterMsgB b = 2;
root_pkg.RootMsg c = 3;
importer.ImporterMsg d = 4;
}
+6
View File
@@ -0,0 +1,6 @@
syntax = "proto3";
package psrpc.internal.gen.typemap.testdata.root_pkg;
// RootMsg leading
message RootMsg {}
+37
View File
@@ -0,0 +1,37 @@
syntax = "proto3";
package psrpc.internal.gen.typemap.testdata.public_reimporter;
import public "public_reimporter.proto";
message ServiceMsg {
public_importer.PublicImporterMsgA a = 1;
public_importer.PublicImporterMsgB b = 2;
root_pkg.RootMsg c = 3;
importer.ImporterMsg d = 4;
}
message Parent {
message NestedOuter{
message NestedInner{}
}
}
service EmptyService {}
service ServiceWithOneMethod{
// Method1 leading
rpc Method1(root_pkg.RootMsg) returns (importer.ImporterMsg);
// Method1 trailing
}
// ServiceWithManyMethods leading
service ServiceWithManyMethods{
// Method1 leading
rpc Method1(root_pkg.RootMsg) returns (importer.ImporterMsg);
// Method2 leading
rpc Method2(Parent) returns (Parent.NestedOuter);
// Method2 trailing
rpc Method3(importer.ImporterMsg.ImporterInner) returns (Parent.NestedOuter.NestedInner);
}
+309
View File
@@ -0,0 +1,309 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package typemap
import (
"github.com/pkg/errors"
descriptor "google.golang.org/protobuf/types/descriptorpb"
)
type Registry struct {
allFiles []*descriptor.FileDescriptorProto
filesByName map[string]*descriptor.FileDescriptorProto
// Mapping of fully-qualified names to their definitions
messagesByProtoName map[string]*MessageDefinition
}
func New(files []*descriptor.FileDescriptorProto) *Registry {
r := &Registry{
allFiles: files,
filesByName: make(map[string]*descriptor.FileDescriptorProto),
messagesByProtoName: make(map[string]*MessageDefinition),
}
// First, index the file descriptors by name. We need this so
// messageDefsForFile can correctly scan imports.
for _, f := range files {
r.filesByName[f.GetName()] = f
}
// Next, index all the message definitions by their fully-qualified proto
// names.
for _, f := range files {
defs := messageDefsForFile(f, r.filesByName)
for name, def := range defs {
r.messagesByProtoName[name] = def
}
}
return r
}
func (r *Registry) FileComments(file *descriptor.FileDescriptorProto) (DefinitionComments, error) {
return commentsAtPath([]int32{packagePath}, file), nil
}
func (r *Registry) ServiceComments(file *descriptor.FileDescriptorProto, svc *descriptor.ServiceDescriptorProto) (DefinitionComments, error) {
for i, s := range file.Service {
if s == svc {
path := []int32{servicePath, int32(i)}
return commentsAtPath(path, file), nil
}
}
return DefinitionComments{}, errors.Errorf("service not found in file")
}
func (r *Registry) MethodComments(file *descriptor.FileDescriptorProto, svc *descriptor.ServiceDescriptorProto, method *descriptor.MethodDescriptorProto) (DefinitionComments, error) {
for i, s := range file.Service {
if s == svc {
path := []int32{servicePath, int32(i)}
for j, m := range s.Method {
if m == method {
path = append(path, serviceMethodPath, int32(j))
return commentsAtPath(path, file), nil
}
}
}
}
return DefinitionComments{}, errors.Errorf("service not found in file")
}
func (r *Registry) MethodInputDefinition(method *descriptor.MethodDescriptorProto) *MessageDefinition {
return r.messagesByProtoName[method.GetInputType()]
}
func (r *Registry) MethodOutputDefinition(method *descriptor.MethodDescriptorProto) *MessageDefinition {
return r.messagesByProtoName[method.GetOutputType()]
}
func (r *Registry) MessageDefinition(name string) *MessageDefinition {
return r.messagesByProtoName[name]
}
type MessageDefinition struct {
// Descriptor is the DescriptorProto defining the message.
Descriptor *descriptor.DescriptorProto
// File is the File that the message was defined in. Or, if it has been
// publicly imported, what File was that import performed in?
File *descriptor.FileDescriptorProto
// Parent is the parent message, if this was defined as a nested message. If
// this was defiend at the top level, parent is nil.
Parent *MessageDefinition
// Comments describes the comments surrounding a message's definition. If it
// was publicly imported, then these comments are from the actual source file,
// not the file that the import was performed in.
Comments DefinitionComments
// path is the 'SourceCodeInfo' path. See the documentation for
// google.golang.org/protobuf/types/descriptorpb.SourceCodeInfo for an
// explanation of its format.
path []int32
}
// ProtoName returns the dot-delimited, fully-qualified protobuf name of the
// message.
func (m *MessageDefinition) ProtoName() string {
prefix := "."
if pkg := m.File.GetPackage(); pkg != "" {
prefix += pkg + "."
}
if lineage := m.Lineage(); len(lineage) > 0 {
for _, parent := range lineage {
prefix += parent.Descriptor.GetName() + "."
}
}
return prefix + m.Descriptor.GetName()
}
// Lineage returns m's parental chain all the way back up to a top-level message
// definition. The first element of the returned slice is the highest-level
// parent.
func (m *MessageDefinition) Lineage() []*MessageDefinition {
var parents []*MessageDefinition
for p := m.Parent; p != nil; p = p.Parent {
parents = append([]*MessageDefinition{p}, parents...)
}
return parents
}
// descendants returns all the submessages defined within m, and all the
// descendants of those, recursively.
func (m *MessageDefinition) descendants() []*MessageDefinition {
descendants := make([]*MessageDefinition, 0)
for i, child := range m.Descriptor.NestedType {
path := append(m.path, []int32{messageMessagePath, int32(i)}...)
childDef := &MessageDefinition{
Descriptor: child,
File: m.File,
Parent: m,
Comments: commentsAtPath(path, m.File),
path: path,
}
descendants = append(descendants, childDef)
descendants = append(descendants, childDef.descendants()...)
}
return descendants
}
// messageDefsForFile gathers a mapping of fully-qualified protobuf names to
// their definitions. It scans a singles file at a time. It requires a mapping
// of .proto file names to their definitions in order to correctly handle
// 'import public' declarations; this mapping should include all files
// transitively imported by f.
func messageDefsForFile(f *descriptor.FileDescriptorProto, filesByName map[string]*descriptor.FileDescriptorProto) map[string]*MessageDefinition {
byProtoName := make(map[string]*MessageDefinition)
// First, gather all the messages defined at the top level.
for i, d := range f.MessageType {
path := []int32{messagePath, int32(i)}
def := &MessageDefinition{
Descriptor: d,
File: f,
Parent: nil,
Comments: commentsAtPath(path, f),
path: path,
}
byProtoName[def.ProtoName()] = def
// Next, all nested message definitions.
for _, child := range def.descendants() {
byProtoName[child.ProtoName()] = child
}
}
// Finally, all messages imported publicly.
for _, depIdx := range f.PublicDependency {
depFileName := f.Dependency[depIdx]
depFile := filesByName[depFileName]
depDefs := messageDefsForFile(depFile, filesByName)
for _, def := range depDefs {
imported := &MessageDefinition{
Descriptor: def.Descriptor,
File: f,
Parent: def.Parent,
Comments: commentsAtPath(def.path, depFile),
path: def.path,
}
byProtoName[imported.ProtoName()] = imported
}
}
return byProtoName
}
// DefinitionComments contains the comments surrounding a definition in a
// protobuf file.
//
// These follow the rules described by protobuf:
//
// A series of line comments appearing on consecutive lines, with no other
// tokens appearing on those lines, will be treated as a single comment.
//
// leading_detached_comments will keep paragraphs of comments that appear
// before (but not connected to) the current element. Each paragraph,
// separated by empty lines, will be one comment element in the repeated
// field.
//
// Only the comment content is provided; comment markers (e.g. //) are
// stripped out. For block comments, leading whitespace and an asterisk
// will be stripped from the beginning of each line other than the first.
// Newlines are included in the output.
//
// Examples:
//
// optional int32 foo = 1; // Comment attached to foo.
// // Comment attached to bar.
// optional int32 bar = 2;
//
// optional string baz = 3;
// // Comment attached to baz.
// // Another line attached to baz.
//
// // Comment attached to qux.
// //
// // Another line attached to qux.
// optional double qux = 4;
//
// // Detached comment for corge. This is not leading or trailing comments
// // to qux or corge because there are blank lines separating it from
// // both.
//
// // Detached comment for corge paragraph 2.
//
// optional string corge = 5;
// /* Block comment attached
// * to corge. Leading asterisks
// * will be removed. */
// /* Block comment attached to
// * grault. */
// optional int32 grault = 6;
//
// // ignored detached comments.
type DefinitionComments struct {
Leading string
Trailing string
LeadingDetached []string
}
func commentsAtPath(path []int32, sourceFile *descriptor.FileDescriptorProto) DefinitionComments {
if sourceFile.SourceCodeInfo == nil {
// The compiler didn't provide us with comments.
return DefinitionComments{}
}
for _, loc := range sourceFile.SourceCodeInfo.Location {
if pathEqual(path, loc.Path) {
return DefinitionComments{
Leading: loc.GetLeadingComments(),
LeadingDetached: loc.GetLeadingDetachedComments(),
Trailing: loc.GetTrailingComments(),
}
}
}
return DefinitionComments{}
}
func pathEqual(path1, path2 []int32) bool {
if len(path1) != len(path2) {
return false
}
for i, v := range path1 {
if path2[i] != v {
return false
}
}
return true
}
const (
// tag numbers in FileDescriptorProto
packagePath = 2 // package
messagePath = 4 // message_type
// enumPath = 5 // enum_type
servicePath = 6 // service
// tag numbers in DescriptorProto
// messageFieldPath = 2 // field
messageMessagePath = 3 // nested_type
// messageEnumPath = 4 // enum_type
// messageOneofPath = 8 // oneof_decl
// tag numbers in ServiceDescriptorProto
// serviceNamePath = 1 // name
serviceMethodPath = 2 // method
// serviceOptionsPath = 3 // options
// tag numbers in MethodDescriptorProto
// methodNamePath = 1 // name
// methodInputPath = 2 // input_type
// methodOutputPath = 3 // output_type
)
+82
View File
@@ -0,0 +1,82 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package typemap
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
descriptor "google.golang.org/protobuf/types/descriptorpb"
)
func loadTestPb(t *testing.T) []*descriptor.FileDescriptorProto {
f, err := os.ReadFile(filepath.Join("testdata", "fileset.pb"))
require.NoError(t, err, "unable to read testdata protobuf file")
set := new(descriptor.FileDescriptorSet)
err = proto.Unmarshal(f, set)
require.NoError(t, err, "unable to unmarshal testdata protobuf file")
return set.File
}
func protoFile(files []*descriptor.FileDescriptorProto, name string) *descriptor.FileDescriptorProto {
for _, f := range files {
if filepath.Base(f.GetName()) == name {
return f
}
}
return nil
}
func service(f *descriptor.FileDescriptorProto, name string) *descriptor.ServiceDescriptorProto {
for _, s := range f.Service {
if s.GetName() == name {
return s
}
}
return nil
}
func method(s *descriptor.ServiceDescriptorProto, name string) *descriptor.MethodDescriptorProto {
for _, m := range s.Method {
if m.GetName() == name {
return m
}
}
return nil
}
func TestNewRegistry(t *testing.T) {
files := loadTestPb(t)
file := protoFile(files, "service.proto")
service := service(file, "ServiceWithManyMethods")
reg := New(files)
comments, err := reg.ServiceComments(file, service)
require.NoError(t, err, "unable to load service comments")
assert.Equal(t, " ServiceWithManyMethods leading\n", comments.Leading)
method1 := method(service, "Method1")
require.NotNil(t, method1)
method1Input := reg.MethodInputDefinition(method1)
require.NotNil(t, method1Input)
assert.Equal(t, "RootMsg", method1Input.Descriptor.GetName())
}
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package gen
const Version = "v0.0.1"
+45 -45
View File
@@ -309,45 +309,45 @@ var File_internal_proto protoreflect.FileDescriptor
var file_internal_proto_rawDesc = []byte{
0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x07, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbc, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12,
0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07,
0x73, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x73,
0x65, 0x6e, 0x74, 0x41, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x18,
0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x12, 0x14, 0x0a,
0x05, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x6d, 0x75,
0x6c, 0x74, 0x69, 0x12, 0x2e, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x06,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x22, 0xa7, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12,
0x1b, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07,
0x73, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x73,
0x65, 0x6e, 0x74, 0x41, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x08, 0x72,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72,
0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x66, 0x0a,
0x0c, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a,
0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x66, 0x66,
0x69, 0x6e, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x61, 0x66, 0x66,
0x69, 0x6e, 0x69, 0x74, 0x79, 0x22, 0x4b, 0x0a, 0x0d, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x49, 0x64, 0x42, 0x23, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2f, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2f, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x12, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbc, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64,
0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a,
0x07, 0x73, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06,
0x73, 0x65, 0x6e, 0x74, 0x41, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79,
0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x12, 0x14,
0x0a, 0x05, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x6d,
0x75, 0x6c, 0x74, 0x69, 0x12, 0x2e, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18,
0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x72, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x22, 0xa7, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64,
0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a,
0x07, 0x73, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06,
0x73, 0x65, 0x6e, 0x74, 0x41, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x08,
0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f,
0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x66,
0x0a, 0x0c, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d,
0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a,
0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x66,
0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x61, 0x66,
0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x22, 0x4b, 0x0a, 0x0d, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x49, 0x64, 0x42, 0x23, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2f, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2f,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -364,15 +364,15 @@ func file_internal_proto_rawDescGZIP() []byte {
var file_internal_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_internal_proto_goTypes = []interface{}{
(*Request)(nil), // 0: livekit.Request
(*Response)(nil), // 1: livekit.Response
(*ClaimRequest)(nil), // 2: livekit.ClaimRequest
(*ClaimResponse)(nil), // 3: livekit.ClaimResponse
(*Request)(nil), // 0: internal.Request
(*Response)(nil), // 1: internal.Response
(*ClaimRequest)(nil), // 2: internal.ClaimRequest
(*ClaimResponse)(nil), // 3: internal.ClaimResponse
(*anypb.Any)(nil), // 4: google.protobuf.Any
}
var file_internal_proto_depIdxs = []int32{
4, // 0: livekit.Request.request:type_name -> google.protobuf.Any
4, // 1: livekit.Response.response:type_name -> google.protobuf.Any
4, // 0: internal.Request.request:type_name -> google.protobuf.Any
4, // 1: internal.Response.response:type_name -> google.protobuf.Any
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
+1 -1
View File
@@ -1,6 +1,6 @@
syntax = "proto3";
package livekit;
package internal;
option go_package = "github.com/livekit/psrpc/internal";
import "google/protobuf/any.proto";
@@ -0,0 +1,20 @@
// Copyright 2019 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package empty_service
import "testing"
func TestCompilation(t *testing.T) {
// Test passes if this package compiles
}
@@ -0,0 +1,64 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: empty_service.proto
package empty_service
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
)
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)
)
var File_empty_service_proto protoreflect.FileDescriptor
var file_empty_service_proto_rawDesc = []byte{
0x0a, 0x13, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x65, 0x6d, 0x70, 0x74, 0x79,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x32, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79,
0x42, 0x10, 0x5a, 0x0e, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var file_empty_service_proto_goTypes = []interface{}{}
var file_empty_service_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_empty_service_proto_init() }
func file_empty_service_proto_init() {
if File_empty_service_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_empty_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_empty_service_proto_goTypes,
DependencyIndexes: file_empty_service_proto_depIdxs,
}.Build()
File_empty_service_proto = out.File
file_empty_service_proto_rawDesc = nil
file_empty_service_proto_goTypes = nil
file_empty_service_proto_depIdxs = nil
}
@@ -0,0 +1,8 @@
syntax = "proto3";
package psrpc.internal.test.emptyservice;
// Test to make sure that a service with no methods doesn't break.
option go_package = "/empty_service";
service Empty{}
@@ -0,0 +1,77 @@
// Code generated by protoc-gen-psrpc v0.0.1, DO NOT EDIT.
// source: empty_service.proto
package empty_service
import psrpc "github.com/livekit/psrpc"
// ======================
// Empty Client Interface
// ======================
type EmptyClient interface {
}
// ==========================
// Empty ServerImpl Interface
// ==========================
type EmptyServerImpl interface {
}
// ======================
// Empty Server Interface
// ======================
type EmptyServer interface {
}
// ============
// Empty Client
// ============
type emptyClient struct {
client psrpc.RPCClient
}
// NewEmptyClient creates a psrpc client that implements the EmptyClient interface.
func NewEmptyClient(clientID string, bus psrpc.MessageBus, opts ...psrpc.ClientOpt) (EmptyClient, error) {
rpcClient, err := psrpc.NewRPCClient("Empty", clientID, bus, opts...)
if err != nil {
return nil, err
}
return &emptyClient{
client: rpcClient,
}, nil
}
// ============
// Empty Server
// ============
type emptyServer struct {
svc EmptyServerImpl
rpc psrpc.RPCServer
}
// NewEmptyServer builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewEmptyServer(serverID string, svc EmptyServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOpt) (EmptyServer, error) {
rpcServer := psrpc.NewRPCServer("Empty", serverID, bus, opts...)
return &emptyServer{
svc: svc,
rpc: rpcServer,
}, nil
}
var psrpcFileDescriptor0 = []byte{
// 90 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4e, 0xcd, 0x2d, 0x28,
0xa9, 0x8c, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17,
0x52, 0x28, 0x28, 0x2e, 0x2a, 0x48, 0xd6, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1,
0x2b, 0x49, 0x2d, 0x2e, 0xd1, 0x03, 0x2b, 0x84, 0xaa, 0x33, 0x62, 0xe7, 0x62, 0x75, 0x05, 0xf1,
0x9d, 0x04, 0xa2, 0xf8, 0xf4, 0x51, 0x8c, 0x48, 0x62, 0x03, 0x9b, 0x61, 0x0c, 0x08, 0x00, 0x00,
0xff, 0xff, 0x16, 0x6b, 0xfe, 0x68, 0x5a, 0x00, 0x00, 0x00,
}
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2019 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package empty_service
//go:generate protoc --go_out=paths=source_relative:. --psrpc_out=paths=source_relative:. empty_service.proto
@@ -0,0 +1,20 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package google_protobuf_imports
import "testing"
func TestCompilation(t *testing.T) {
// Test passes if this package compiles
}
@@ -0,0 +1,16 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package google_protobuf_imports
//go:generate protoc --go_out=paths=source_relative:. --psrpc_out=paths=source_relative:. service.proto
@@ -0,0 +1,79 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: service.proto
package google_protobuf_imports
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
wrapperspb "google.golang.org/protobuf/types/known/wrapperspb"
reflect "reflect"
)
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)
)
var File_service_proto protoreflect.FileDescriptor
var file_service_proto_rawDesc = []byte{
0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x1d, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e,
0x74, 0x65, 0x73, 0x74, 0x2e, 0x75, 0x73, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1b,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f,
0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61,
0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x43, 0x0a, 0x03, 0x53,
0x76, 0x63, 0x12, 0x3c, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72,
0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
0x42, 0x1a, 0x5a, 0x18, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var file_service_proto_goTypes = []interface{}{
(*wrapperspb.StringValue)(nil), // 0: google.protobuf.StringValue
(*emptypb.Empty)(nil), // 1: google.protobuf.Empty
}
var file_service_proto_depIdxs = []int32{
0, // 0: psrpc.internal.test.use_empty.Svc.Send:input_type -> google.protobuf.StringValue
1, // 1: psrpc.internal.test.use_empty.Svc.Send:output_type -> google.protobuf.Empty
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_service_proto_init() }
func file_service_proto_init() {
if File_service_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_service_proto_goTypes,
DependencyIndexes: file_service_proto_depIdxs,
}.Build()
File_service_proto = out.File
file_service_proto_rawDesc = nil
file_service_proto_goTypes = nil
file_service_proto_depIdxs = nil
}
@@ -0,0 +1,11 @@
syntax = "proto3";
package psrpc.internal.test.use_empty;
option go_package = "/google_protobuf_imports";
import "google/protobuf/empty.proto";
import "google/protobuf/wrappers.proto";
service Svc {
rpc Send(google.protobuf.StringValue) returns(google.protobuf.Empty);
}
@@ -0,0 +1,99 @@
// Code generated by protoc-gen-psrpc v0.0.1, DO NOT EDIT.
// source: service.proto
package google_protobuf_imports
import context "context"
import psrpc "github.com/livekit/psrpc"
import google_protobuf "google.golang.org/protobuf/types/known/emptypb"
import google_protobuf1 "google.golang.org/protobuf/types/known/wrapperspb"
// ====================
// Svc Client Interface
// ====================
type SvcClient interface {
Send(context.Context, *google_protobuf1.StringValue, ...psrpc.RequestOpt) (*google_protobuf.Empty, error)
}
// ========================
// Svc ServerImpl Interface
// ========================
type SvcServerImpl interface {
Send(context.Context, *google_protobuf1.StringValue) (*google_protobuf.Empty, error)
}
// ====================
// Svc Server Interface
// ====================
type SvcServer interface {
}
// ==========
// Svc Client
// ==========
type svcClient struct {
client psrpc.RPCClient
}
// NewSvcClient creates a psrpc client that implements the SvcClient interface.
func NewSvcClient(clientID string, bus psrpc.MessageBus, opts ...psrpc.ClientOpt) (SvcClient, error) {
rpcClient, err := psrpc.NewRPCClient("Svc", clientID, bus, opts...)
if err != nil {
return nil, err
}
return &svcClient{
client: rpcClient,
}, nil
}
func (c *svcClient) Send(ctx context.Context, req *google_protobuf1.StringValue, opts ...psrpc.RequestOpt) (*google_protobuf.Empty, error) {
return psrpc.RequestTopicSingle[*google_protobuf.Empty](ctx, c.client, "Send", "", req, opts...)
}
// ==========
// Svc Server
// ==========
type svcServer struct {
svc SvcServerImpl
rpc psrpc.RPCServer
}
// NewSvcServer builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewSvcServer(serverID string, svc SvcServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOpt) (SvcServer, error) {
rpcServer := psrpc.NewRPCServer("Svc", serverID, bus, opts...)
var err error
err = rpcServer.RegisterHandler(psrpc.NewHandler("Send", svc.Send))
if err != nil {
rpcServer.Close()
return nil, err
}
return &svcServer{
svc: svc,
rpc: rpcServer,
}, nil
}
var psrpcFileDescriptor0 = []byte{
// 166 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0xcd, 0xbf, 0x0a, 0xc2, 0x40,
0x0c, 0xc7, 0xf1, 0x41, 0x71, 0x28, 0xb8, 0x74, 0x10, 0x39, 0xff, 0x3c, 0x42, 0x0a, 0xba, 0x3a,
0x29, 0x3e, 0x41, 0xc1, 0xc1, 0xa5, 0xb4, 0x35, 0x96, 0x83, 0xf6, 0x2e, 0x24, 0xb9, 0x8a, 0x6f,
0x2f, 0xde, 0xd1, 0x45, 0xd7, 0xdf, 0xe7, 0x1b, 0x92, 0x2d, 0x05, 0x79, 0xb4, 0x2d, 0x02, 0xb1,
0x57, 0x9f, 0xef, 0x48, 0x98, 0x5a, 0xb0, 0x4e, 0x91, 0x5d, 0xdd, 0x83, 0xa2, 0x28, 0x04, 0xc1,
0x0a, 0x07, 0xd2, 0xb7, 0xd9, 0x74, 0xde, 0x77, 0x3d, 0x16, 0x31, 0x6e, 0xc2, 0xb3, 0x88, 0x73,
0xba, 0x35, 0xfb, 0x5f, 0x7c, 0x71, 0x4d, 0x84, 0x2c, 0xc9, 0x0f, 0x97, 0x6c, 0x56, 0x8e, 0x6d,
0x7e, 0xca, 0xe6, 0x25, 0xba, 0x47, 0xbe, 0x85, 0xd4, 0xc3, 0xd4, 0x43, 0xa9, 0x6c, 0x5d, 0x77,
0xab, 0xfb, 0x80, 0x66, 0xf5, 0xa7, 0xd7, 0xef, 0xab, 0xb3, 0xb9, 0xaf, 0x8b, 0x24, 0xd5, 0x24,
0x95, 0x1d, 0xc8, 0xb3, 0x4a, 0xb3, 0x88, 0xcb, 0xf1, 0x13, 0x00, 0x00, 0xff, 0xff, 0x0a, 0xfa,
0x30, 0x79, 0xd4, 0x00, 0x00, 0x00,
}
+20
View File
@@ -0,0 +1,20 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package importable
import "testing"
func TestCompilation(t *testing.T) {
// Test passes if this package compiles
}
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package importable
//go:generate protoc --go_out=paths=source_relative:. --psrpc_out=paths=source_relative:. importable.proto
+144
View File
@@ -0,0 +1,144 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: importable.proto
// Test to make sure that importing other packages doesnt break
package importable
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 Msg struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Msg) Reset() {
*x = Msg{}
if protoimpl.UnsafeEnabled {
mi := &file_importable_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Msg) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Msg) ProtoMessage() {}
func (x *Msg) ProtoReflect() protoreflect.Message {
mi := &file_importable_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 Msg.ProtoReflect.Descriptor instead.
func (*Msg) Descriptor() ([]byte, []int) {
return file_importable_proto_rawDescGZIP(), []int{0}
}
var File_importable_proto protoreflect.FileDescriptor
var file_importable_proto_rawDesc = []byte{
0x0a, 0x10, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x1e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62,
0x6c, 0x65, 0x22, 0x05, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x32, 0x57, 0x0a, 0x03, 0x53, 0x76, 0x63,
0x12, 0x50, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x23, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63,
0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69,
0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x1a, 0x23, 0x2e,
0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74,
0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x4d,
0x73, 0x67, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2f, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2f, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x69, 0x6d, 0x70,
0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_importable_proto_rawDescOnce sync.Once
file_importable_proto_rawDescData = file_importable_proto_rawDesc
)
func file_importable_proto_rawDescGZIP() []byte {
file_importable_proto_rawDescOnce.Do(func() {
file_importable_proto_rawDescData = protoimpl.X.CompressGZIP(file_importable_proto_rawDescData)
})
return file_importable_proto_rawDescData
}
var file_importable_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_importable_proto_goTypes = []interface{}{
(*Msg)(nil), // 0: psrpc.internal.test.importable.Msg
}
var file_importable_proto_depIdxs = []int32{
0, // 0: psrpc.internal.test.importable.Svc.Send:input_type -> psrpc.internal.test.importable.Msg
0, // 1: psrpc.internal.test.importable.Svc.Send:output_type -> psrpc.internal.test.importable.Msg
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_importable_proto_init() }
func file_importable_proto_init() {
if File_importable_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_importable_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Msg); 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_importable_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_importable_proto_goTypes,
DependencyIndexes: file_importable_proto_depIdxs,
MessageInfos: file_importable_proto_msgTypes,
}.Build()
File_importable_proto = out.File
file_importable_proto_rawDesc = nil
file_importable_proto_goTypes = nil
file_importable_proto_depIdxs = nil
}
+11
View File
@@ -0,0 +1,11 @@
syntax = "proto3";
// Test to make sure that importing other packages doesnt break
package psrpc.internal.test.importable;
option go_package = "github.com/livekit/psrpc/internal/test/importable";
message Msg {}
service Svc {
rpc Send(Msg) returns(Msg);
}
@@ -0,0 +1,97 @@
// Code generated by protoc-gen-psrpc v0.0.1, DO NOT EDIT.
// source: importable.proto
// Test to make sure that importing other packages doesnt break
package importable
import context "context"
import psrpc "github.com/livekit/psrpc"
// ====================
// Svc Client Interface
// ====================
type SvcClient interface {
Send(context.Context, *Msg, ...psrpc.RequestOpt) (*Msg, error)
}
// ========================
// Svc ServerImpl Interface
// ========================
type SvcServerImpl interface {
Send(context.Context, *Msg) (*Msg, error)
}
// ====================
// Svc Server Interface
// ====================
type SvcServer interface {
}
// ==========
// Svc Client
// ==========
type svcClient struct {
client psrpc.RPCClient
}
// NewSvcClient creates a psrpc client that implements the SvcClient interface.
func NewSvcClient(clientID string, bus psrpc.MessageBus, opts ...psrpc.ClientOpt) (SvcClient, error) {
rpcClient, err := psrpc.NewRPCClient("Svc", clientID, bus, opts...)
if err != nil {
return nil, err
}
return &svcClient{
client: rpcClient,
}, nil
}
func (c *svcClient) Send(ctx context.Context, req *Msg, opts ...psrpc.RequestOpt) (*Msg, error) {
return psrpc.RequestTopicSingle[*Msg](ctx, c.client, "Send", "", req, opts...)
}
// ==========
// Svc Server
// ==========
type svcServer struct {
svc SvcServerImpl
rpc psrpc.RPCServer
}
// NewSvcServer builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewSvcServer(serverID string, svc SvcServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOpt) (SvcServer, error) {
rpcServer := psrpc.NewRPCServer("Svc", serverID, bus, opts...)
var err error
err = rpcServer.RegisterHandler(psrpc.NewHandler("Send", svc.Send))
if err != nil {
rpcServer.Close()
return nil, err
}
return &svcServer{
svc: svc,
rpc: rpcServer,
}, nil
}
var psrpcFileDescriptor0 = []byte{
// 140 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0xcc, 0x2d, 0xc8,
0x2f, 0x2a, 0x49, 0x4c, 0xca, 0x49, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x2b, 0x28,
0x2e, 0x2a, 0x48, 0xd6, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x2b, 0x49, 0x2d,
0x2e, 0xd1, 0x43, 0xa8, 0x52, 0x62, 0xe5, 0x62, 0xf6, 0x2d, 0x4e, 0x37, 0x0a, 0xe7, 0x62, 0x0e,
0x2e, 0x4b, 0x16, 0x0a, 0xe0, 0x62, 0x09, 0x4e, 0xcd, 0x4b, 0x11, 0x52, 0xd6, 0xc3, 0xaf, 0x4d,
0xcf, 0xb7, 0x38, 0x5d, 0x8a, 0x18, 0x45, 0x4e, 0xc6, 0x51, 0x86, 0xe9, 0x99, 0x25, 0x19, 0xa5,
0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x39, 0x99, 0x65, 0xa9, 0xd9, 0x99, 0x25, 0xfa, 0x60, 0x8d,
0xfa, 0x30, 0x8d, 0xfa, 0x20, 0x8d, 0xfa, 0x08, 0x8d, 0x49, 0x6c, 0x60, 0xb7, 0x1b, 0x03, 0x02,
0x00, 0x00, 0xff, 0xff, 0xb6, 0xdf, 0xe8, 0x19, 0xcf, 0x00, 0x00, 0x00,
}
+20
View File
@@ -0,0 +1,20 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package importer
import "testing"
func TestCompilation(t *testing.T) {
// Test passes if this package compiles
}
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package importer
//go:generate protoc -I=. -I=../importable --go_out=paths=source_relative:. --psrpc_out=paths=source_relative:. importer.proto
+79
View File
@@ -0,0 +1,79 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: importer.proto
// Test to make sure that importing other packages doesnt break
package importer
import (
importable "github.com/livekit/psrpc/internal/test/importable"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
)
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)
)
var File_importer_proto protoreflect.FileDescriptor
var file_importer_proto_rawDesc = []byte{
0x0a, 0x0e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x1c, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x1a, 0x10,
0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x32, 0x58, 0x0a, 0x04, 0x53, 0x76, 0x63, 0x32, 0x12, 0x50, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64,
0x12, 0x23, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c,
0x65, 0x2e, 0x4d, 0x73, 0x67, 0x1a, 0x23, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f,
0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69,
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74,
0x2f, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f,
0x74, 0x65, 0x73, 0x74, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var file_importer_proto_goTypes = []interface{}{
(*importable.Msg)(nil), // 0: psrpc.internal.test.importable.Msg
}
var file_importer_proto_depIdxs = []int32{
0, // 0: psrpc.internal.test.importer.Svc2.Send:input_type -> psrpc.internal.test.importable.Msg
0, // 1: psrpc.internal.test.importer.Svc2.Send:output_type -> psrpc.internal.test.importable.Msg
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_importer_proto_init() }
func file_importer_proto_init() {
if File_importer_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_importer_proto_rawDesc,
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_importer_proto_goTypes,
DependencyIndexes: file_importer_proto_depIdxs,
}.Build()
File_importer_proto = out.File
file_importer_proto_rawDesc = nil
file_importer_proto_goTypes = nil
file_importer_proto_depIdxs = nil
}
+11
View File
@@ -0,0 +1,11 @@
syntax = "proto3";
// Test to make sure that importing other packages doesnt break
package psrpc.internal.test.importer;
option go_package = "github.com/livekit/psrpc/internal/test/importer";
import "importable.proto";
service Svc2 {
rpc Send(importable.Msg) returns(importable.Msg);
}
+98
View File
@@ -0,0 +1,98 @@
// Code generated by protoc-gen-psrpc v0.0.1, DO NOT EDIT.
// source: importer.proto
// Test to make sure that importing other packages doesnt break
package importer
import context "context"
import psrpc "github.com/livekit/psrpc"
import psrpc_internal_test_importable "github.com/livekit/psrpc/internal/test/importable"
// =====================
// Svc2 Client Interface
// =====================
type Svc2Client interface {
Send(context.Context, *psrpc_internal_test_importable.Msg, ...psrpc.RequestOpt) (*psrpc_internal_test_importable.Msg, error)
}
// =========================
// Svc2 ServerImpl Interface
// =========================
type Svc2ServerImpl interface {
Send(context.Context, *psrpc_internal_test_importable.Msg) (*psrpc_internal_test_importable.Msg, error)
}
// =====================
// Svc2 Server Interface
// =====================
type Svc2Server interface {
}
// ===========
// Svc2 Client
// ===========
type svc2Client struct {
client psrpc.RPCClient
}
// NewSvc2Client creates a psrpc client that implements the Svc2Client interface.
func NewSvc2Client(clientID string, bus psrpc.MessageBus, opts ...psrpc.ClientOpt) (Svc2Client, error) {
rpcClient, err := psrpc.NewRPCClient("Svc2", clientID, bus, opts...)
if err != nil {
return nil, err
}
return &svc2Client{
client: rpcClient,
}, nil
}
func (c *svc2Client) Send(ctx context.Context, req *psrpc_internal_test_importable.Msg, opts ...psrpc.RequestOpt) (*psrpc_internal_test_importable.Msg, error) {
return psrpc.RequestTopicSingle[*psrpc_internal_test_importable.Msg](ctx, c.client, "Send", "", req, opts...)
}
// ===========
// Svc2 Server
// ===========
type svc2Server struct {
svc Svc2ServerImpl
rpc psrpc.RPCServer
}
// NewSvc2Server builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewSvc2Server(serverID string, svc Svc2ServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOpt) (Svc2Server, error) {
rpcServer := psrpc.NewRPCServer("Svc2", serverID, bus, opts...)
var err error
err = rpcServer.RegisterHandler(psrpc.NewHandler("Send", svc.Send))
if err != nil {
rpcServer.Close()
return nil, err
}
return &svc2Server{
svc: svc,
rpc: rpcServer,
}, nil
}
var psrpcFileDescriptor0 = []byte{
// 143 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcb, 0xcc, 0x2d, 0xc8,
0x2f, 0x2a, 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x29, 0x28, 0x2e, 0x2a,
0x48, 0xd6, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x2b, 0x49, 0x2d, 0x2e, 0xd1,
0x83, 0xa9, 0x91, 0x12, 0x80, 0xb0, 0x12, 0x93, 0x72, 0x52, 0x21, 0xea, 0x8d, 0x22, 0xb8, 0x58,
0x82, 0xcb, 0x92, 0x8d, 0x84, 0x02, 0xb8, 0x58, 0x82, 0x53, 0xf3, 0x52, 0x84, 0x94, 0xf5, 0x70,
0x1b, 0x00, 0xd6, 0xe6, 0x5b, 0x9c, 0x2e, 0x45, 0x8c, 0x22, 0x27, 0xc3, 0x28, 0xfd, 0xf4, 0xcc,
0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0x9c, 0xcc, 0xb2, 0xd4, 0xec, 0xcc, 0x12,
0x7d, 0xb0, 0x46, 0x7d, 0x98, 0x46, 0x7d, 0x90, 0x46, 0x7d, 0x98, 0xf3, 0x92, 0xd8, 0xc0, 0x6e,
0x32, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xa3, 0x10, 0x21, 0xbe, 0xd5, 0x00, 0x00, 0x00,
}
@@ -0,0 +1,20 @@
// Copyright 2019 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package importer_local
import "testing"
func TestCompilation(t *testing.T) {
// Test passes if this package compiles
}
+17
View File
@@ -0,0 +1,17 @@
// Copyright 2019 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package importer_local
//go:generate protoc --go_out=paths=source_relative:. --psrpc_out=paths=source_relative:. importer_local_msgdef.proto
//go:generate protoc --go_out=paths=source_relative:. --psrpc_out=paths=source_relative:. importer_local.proto
@@ -0,0 +1,79 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: importer_local.proto
package importer_local
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
)
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)
)
var File_importer_local_proto protoreflect.FileDescriptor
var file_importer_local_proto_rawDesc = []byte{
0x0a, 0x14, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x22, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f,
0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x1a, 0x1b, 0x69, 0x6d, 0x70, 0x6f,
0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x67, 0x64, 0x65,
0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x5f, 0x0a, 0x03, 0x53, 0x76, 0x63, 0x12, 0x58,
0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x27, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70,
0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2e, 0x4d, 0x73, 0x67, 0x1a,
0x27, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68,
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2f, 0x70,
0x73, 0x72, 0x70, 0x63, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65,
0x73, 0x74, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var file_importer_local_proto_goTypes = []interface{}{
(*Msg)(nil), // 0: psrpc.internal.test.importer_local.Msg
}
var file_importer_local_proto_depIdxs = []int32{
0, // 0: psrpc.internal.test.importer_local.Svc.Send:input_type -> psrpc.internal.test.importer_local.Msg
0, // 1: psrpc.internal.test.importer_local.Svc.Send:output_type -> psrpc.internal.test.importer_local.Msg
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_importer_local_proto_init() }
func file_importer_local_proto_init() {
if File_importer_local_proto != nil {
return
}
file_importer_local_msgdef_proto_init()
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_importer_local_proto_rawDesc,
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_importer_local_proto_goTypes,
DependencyIndexes: file_importer_local_proto_depIdxs,
}.Build()
File_importer_local_proto = out.File
file_importer_local_proto_rawDesc = nil
file_importer_local_proto_goTypes = nil
file_importer_local_proto_depIdxs = nil
}
@@ -0,0 +1,10 @@
syntax = "proto3";
package psrpc.internal.test.importer_local;
option go_package = "github.com/livekit/psrpc/internal/test/importer_local";
import "importer_local_msgdef.proto";
service Svc {
rpc Send(Msg) returns (Msg);
}
@@ -0,0 +1,96 @@
// Code generated by protoc-gen-psrpc v0.0.1, DO NOT EDIT.
// source: importer_local.proto
package importer_local
import context "context"
import psrpc "github.com/livekit/psrpc"
// ====================
// Svc Client Interface
// ====================
type SvcClient interface {
Send(context.Context, *Msg, ...psrpc.RequestOpt) (*Msg, error)
}
// ========================
// Svc ServerImpl Interface
// ========================
type SvcServerImpl interface {
Send(context.Context, *Msg) (*Msg, error)
}
// ====================
// Svc Server Interface
// ====================
type SvcServer interface {
}
// ==========
// Svc Client
// ==========
type svcClient struct {
client psrpc.RPCClient
}
// NewSvcClient creates a psrpc client that implements the SvcClient interface.
func NewSvcClient(clientID string, bus psrpc.MessageBus, opts ...psrpc.ClientOpt) (SvcClient, error) {
rpcClient, err := psrpc.NewRPCClient("Svc", clientID, bus, opts...)
if err != nil {
return nil, err
}
return &svcClient{
client: rpcClient,
}, nil
}
func (c *svcClient) Send(ctx context.Context, req *Msg, opts ...psrpc.RequestOpt) (*Msg, error) {
return psrpc.RequestTopicSingle[*Msg](ctx, c.client, "Send", "", req, opts...)
}
// ==========
// Svc Server
// ==========
type svcServer struct {
svc SvcServerImpl
rpc psrpc.RPCServer
}
// NewSvcServer builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewSvcServer(serverID string, svc SvcServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOpt) (SvcServer, error) {
rpcServer := psrpc.NewRPCServer("Svc", serverID, bus, opts...)
var err error
err = rpcServer.RegisterHandler(psrpc.NewHandler("Send", svc.Send))
if err != nil {
rpcServer.Close()
return nil, err
}
return &svcServer{
svc: svc,
rpc: rpcServer,
}, nil
}
var psrpcFileDescriptor0 = []byte{
// 150 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc9, 0xcc, 0x2d, 0xc8,
0x2f, 0x2a, 0x49, 0x2d, 0x8a, 0xcf, 0xc9, 0x4f, 0x4e, 0xcc, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9,
0x17, 0x52, 0x2a, 0x28, 0x2e, 0x2a, 0x48, 0xd6, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc,
0xd1, 0x2b, 0x49, 0x2d, 0x2e, 0xd1, 0x43, 0x55, 0x29, 0x25, 0x8d, 0xca, 0x8f, 0xcf, 0x2d, 0x4e,
0x4f, 0x49, 0x4d, 0x83, 0x18, 0x60, 0x14, 0xcf, 0xc5, 0x1c, 0x5c, 0x96, 0x2c, 0x14, 0xc1, 0xc5,
0x12, 0x9c, 0x9a, 0x97, 0x22, 0xa4, 0xae, 0x47, 0xd8, 0x40, 0x3d, 0xdf, 0xe2, 0x74, 0x29, 0x62,
0x15, 0x3a, 0x99, 0x47, 0x99, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea,
0xe7, 0x64, 0x96, 0xa5, 0x66, 0x67, 0x96, 0xe8, 0x83, 0x35, 0xeb, 0xc3, 0x34, 0xeb, 0x83, 0x34,
0xeb, 0xa3, 0x6a, 0x4e, 0x62, 0x03, 0x3b, 0xd0, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x18, 0x5a,
0x95, 0x49, 0xf9, 0x00, 0x00, 0x00,
}
@@ -0,0 +1,136 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: importer_local_msgdef.proto
package importer_local
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 Msg struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Msg) Reset() {
*x = Msg{}
if protoimpl.UnsafeEnabled {
mi := &file_importer_local_msgdef_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Msg) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Msg) ProtoMessage() {}
func (x *Msg) ProtoReflect() protoreflect.Message {
mi := &file_importer_local_msgdef_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 Msg.ProtoReflect.Descriptor instead.
func (*Msg) Descriptor() ([]byte, []int) {
return file_importer_local_msgdef_proto_rawDescGZIP(), []int{0}
}
var File_importer_local_msgdef_proto protoreflect.FileDescriptor
var file_importer_local_msgdef_proto_rawDesc = []byte{
0x0a, 0x1b, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
0x5f, 0x6d, 0x73, 0x67, 0x64, 0x65, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x22, 0x70,
0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65,
0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x22, 0x05, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68,
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2f, 0x70,
0x73, 0x72, 0x70, 0x63, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65,
0x73, 0x74, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_importer_local_msgdef_proto_rawDescOnce sync.Once
file_importer_local_msgdef_proto_rawDescData = file_importer_local_msgdef_proto_rawDesc
)
func file_importer_local_msgdef_proto_rawDescGZIP() []byte {
file_importer_local_msgdef_proto_rawDescOnce.Do(func() {
file_importer_local_msgdef_proto_rawDescData = protoimpl.X.CompressGZIP(file_importer_local_msgdef_proto_rawDescData)
})
return file_importer_local_msgdef_proto_rawDescData
}
var file_importer_local_msgdef_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_importer_local_msgdef_proto_goTypes = []interface{}{
(*Msg)(nil), // 0: psrpc.internal.test.importer_local.Msg
}
var file_importer_local_msgdef_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_importer_local_msgdef_proto_init() }
func file_importer_local_msgdef_proto_init() {
if File_importer_local_msgdef_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_importer_local_msgdef_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Msg); 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_importer_local_msgdef_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_importer_local_msgdef_proto_goTypes,
DependencyIndexes: file_importer_local_msgdef_proto_depIdxs,
MessageInfos: file_importer_local_msgdef_proto_msgTypes,
}.Build()
File_importer_local_msgdef_proto = out.File
file_importer_local_msgdef_proto_rawDesc = nil
file_importer_local_msgdef_proto_goTypes = nil
file_importer_local_msgdef_proto_depIdxs = nil
}
@@ -0,0 +1,6 @@
syntax = "proto3";
package psrpc.internal.test.importer_local;
option go_package = "github.com/livekit/psrpc/internal/test/importer_local";
message Msg {}
@@ -0,0 +1,20 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package importmapping
import "testing"
func TestCompilation(t *testing.T) {
// Test passes if this package compiles
}
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package importmapping
//go:generate ./gen.sh
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail
protoc --go_out=. --psrpc_out=. \
--go_opt=paths=source_relative \
--go_opt=My/y.proto=github.com/livekit/psrpc/internal/test/importmapping/y \
--psrpc_opt=paths=source_relative \
--psrpc_opt=My/y.proto=github.com/livekit/psrpc/internal/test/importmapping/y \
y/y.proto
protoc --go_out=. --psrpc_out=. \
--go_opt=paths=source_relative \
--go_opt=My/y.proto=github.com/livekit/psrpc/internal/test/importmapping/y \
--go_opt=Mx/x.proto=github.com/livekit/psrpc/internal/test/importmapping/x \
--psrpc_opt=paths=source_relative \
--psrpc_opt=My/y.proto=github.com/livekit/psrpc/internal/test/importmapping/y \
--psrpc_opt=Mx/x.proto=github.com/livekit/psrpc/internal/test/importmapping/x \
x/x.proto
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
# Pull into variable since both protoc-gen-go and protoc-gen-psrpc need the map.
Y_IMPORT_MAPPING="y/y.proto=github.com/livekit/psrpc/internal/test/importmapping/y"
PROTOC_GEN_GO_PARAMS="M${Y_IMPORT_MAPPING}" \
PROTOC_GEN_PSRPC_PARAMS="go_import_mapping@${Y_IMPORT_MAPPING}" \
../../protoc_gen.sh x/x.proto
+76
View File
@@ -0,0 +1,76 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: x/x.proto
package x
import (
y "github.com/livekit/psrpc/internal/test/importmapping/y"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
)
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)
)
var File_x_x_proto protoreflect.FileDescriptor
var file_x_x_proto_rawDesc = []byte{
0x0a, 0x09, 0x78, 0x2f, 0x78, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x23, 0x70, 0x73, 0x72,
0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74,
0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x78,
0x1a, 0x09, 0x79, 0x2f, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x64, 0x0a, 0x04, 0x53,
0x76, 0x63, 0x31, 0x12, 0x5c, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x29, 0x2e, 0x70, 0x73,
0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73,
0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e,
0x79, 0x2e, 0x4d, 0x73, 0x67, 0x59, 0x1a, 0x29, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70,
0x6f, 0x72, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x79, 0x2e, 0x4d, 0x73, 0x67,
0x59, 0x42, 0x1f, 0x5a, 0x1d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x77, 0x69, 0x6c, 0x6c, 0x2f, 0x62, 0x65, 0x2f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64,
0x2f, 0x78, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var file_x_x_proto_goTypes = []interface{}{
(*y.MsgY)(nil), // 0: psrpc.internal.test.importmapping.y.MsgY
}
var file_x_x_proto_depIdxs = []int32{
0, // 0: psrpc.internal.test.importmapping.x.Svc1.Send:input_type -> psrpc.internal.test.importmapping.y.MsgY
0, // 1: psrpc.internal.test.importmapping.x.Svc1.Send:output_type -> psrpc.internal.test.importmapping.y.MsgY
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_x_x_proto_init() }
func file_x_x_proto_init() {
if File_x_x_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_x_x_proto_rawDesc,
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_x_x_proto_goTypes,
DependencyIndexes: file_x_x_proto_depIdxs,
}.Build()
File_x_x_proto = out.File
file_x_x_proto_rawDesc = nil
file_x_x_proto_goTypes = nil
file_x_x_proto_depIdxs = nil
}
+10
View File
@@ -0,0 +1,10 @@
syntax = "proto3";
package psrpc.internal.test.importmapping.x;
option go_package = "example.com/will/be/ignored/x";
import "y/y.proto";
service Svc1 {
rpc Send(y.MsgY) returns (y.MsgY);
}
+97
View File
@@ -0,0 +1,97 @@
// Code generated by protoc-gen-psrpc v0.0.1, DO NOT EDIT.
// source: x/x.proto
package x
import context "context"
import psrpc "github.com/livekit/psrpc"
import psrpc_internal_test_importmapping_y "github.com/livekit/psrpc/internal/test/importmapping/y"
// =====================
// Svc1 Client Interface
// =====================
type Svc1Client interface {
Send(context.Context, *psrpc_internal_test_importmapping_y.MsgY, ...psrpc.RequestOpt) (*psrpc_internal_test_importmapping_y.MsgY, error)
}
// =========================
// Svc1 ServerImpl Interface
// =========================
type Svc1ServerImpl interface {
Send(context.Context, *psrpc_internal_test_importmapping_y.MsgY) (*psrpc_internal_test_importmapping_y.MsgY, error)
}
// =====================
// Svc1 Server Interface
// =====================
type Svc1Server interface {
}
// ===========
// Svc1 Client
// ===========
type svc1Client struct {
client psrpc.RPCClient
}
// NewSvc1Client creates a psrpc client that implements the Svc1Client interface.
func NewSvc1Client(clientID string, bus psrpc.MessageBus, opts ...psrpc.ClientOpt) (Svc1Client, error) {
rpcClient, err := psrpc.NewRPCClient("Svc1", clientID, bus, opts...)
if err != nil {
return nil, err
}
return &svc1Client{
client: rpcClient,
}, nil
}
func (c *svc1Client) Send(ctx context.Context, req *psrpc_internal_test_importmapping_y.MsgY, opts ...psrpc.RequestOpt) (*psrpc_internal_test_importmapping_y.MsgY, error) {
return psrpc.RequestTopicSingle[*psrpc_internal_test_importmapping_y.MsgY](ctx, c.client, "Send", "", req, opts...)
}
// ===========
// Svc1 Server
// ===========
type svc1Server struct {
svc Svc1ServerImpl
rpc psrpc.RPCServer
}
// NewSvc1Server builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewSvc1Server(serverID string, svc Svc1ServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOpt) (Svc1Server, error) {
rpcServer := psrpc.NewRPCServer("Svc1", serverID, bus, opts...)
var err error
err = rpcServer.RegisterHandler(psrpc.NewHandler("Send", svc.Send))
if err != nil {
rpcServer.Close()
return nil, err
}
return &svc1Server{
svc: svc,
rpc: rpcServer,
}, nil
}
var psrpcFileDescriptor0 = []byte{
// 147 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0xce, 0x3d, 0x0a, 0x02, 0x31,
0x10, 0x40, 0xe1, 0x66, 0x11, 0x76, 0xcb, 0x94, 0x0b, 0x62, 0x61, 0x65, 0x33, 0x83, 0x7a, 0x03,
0x7b, 0xab, 0xad, 0x14, 0x9b, 0x6c, 0x32, 0x84, 0x40, 0x7e, 0x86, 0x24, 0xe8, 0xe4, 0xf6, 0x82,
0x1e, 0x40, 0xfb, 0x8f, 0xc7, 0x9b, 0x46, 0x41, 0x01, 0x2e, 0xb9, 0x65, 0xb5, 0xe7, 0x5a, 0xd8,
0x80, 0x4f, 0x8d, 0x4a, 0xd2, 0x01, 0x1a, 0xd5, 0x06, 0x3e, 0x72, 0x2e, 0x2d, 0x6a, 0x66, 0x9f,
0x1c, 0xc8, 0x3c, 0x76, 0xec, 0x5f, 0x7f, 0xb2, 0xd3, 0xb0, 0x3c, 0xcd, 0x51, 0x3d, 0xa6, 0x61,
0xa1, 0x64, 0xd5, 0x01, 0x7e, 0x07, 0x3a, 0x5c, 0xab, 0xbb, 0xcd, 0xff, 0xd3, 0xcb, 0xee, 0xbe,
0x25, 0xd1, 0x91, 0x03, 0x81, 0xc9, 0x11, 0x5f, 0x3e, 0x04, 0x5c, 0x09, 0xbd, 0x4b, 0xb9, 0x90,
0x45, 0x59, 0x37, 0x9f, 0x9b, 0xf3, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x6b, 0x1a, 0xa1, 0xca,
0x00, 0x00, 0x00,
}
+134
View File
@@ -0,0 +1,134 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: y/y.proto
package y
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 MsgY struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *MsgY) Reset() {
*x = MsgY{}
if protoimpl.UnsafeEnabled {
mi := &file_y_y_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MsgY) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MsgY) ProtoMessage() {}
func (x *MsgY) ProtoReflect() protoreflect.Message {
mi := &file_y_y_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 MsgY.ProtoReflect.Descriptor instead.
func (*MsgY) Descriptor() ([]byte, []int) {
return file_y_y_proto_rawDescGZIP(), []int{0}
}
var File_y_y_proto protoreflect.FileDescriptor
var file_y_y_proto_rawDesc = []byte{
0x0a, 0x09, 0x79, 0x2f, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x23, 0x70, 0x73, 0x72,
0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74,
0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x79,
0x22, 0x06, 0x0a, 0x04, 0x4d, 0x73, 0x67, 0x59, 0x42, 0x1f, 0x5a, 0x1d, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x69, 0x6c, 0x6c, 0x2f, 0x62, 0x65, 0x2f,
0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x2f, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var (
file_y_y_proto_rawDescOnce sync.Once
file_y_y_proto_rawDescData = file_y_y_proto_rawDesc
)
func file_y_y_proto_rawDescGZIP() []byte {
file_y_y_proto_rawDescOnce.Do(func() {
file_y_y_proto_rawDescData = protoimpl.X.CompressGZIP(file_y_y_proto_rawDescData)
})
return file_y_y_proto_rawDescData
}
var file_y_y_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_y_y_proto_goTypes = []interface{}{
(*MsgY)(nil), // 0: psrpc.internal.test.importmapping.y.MsgY
}
var file_y_y_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_y_y_proto_init() }
func file_y_y_proto_init() {
if File_y_y_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_y_y_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MsgY); 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_y_y_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_y_y_proto_goTypes,
DependencyIndexes: file_y_y_proto_depIdxs,
MessageInfos: file_y_y_proto_msgTypes,
}.Build()
File_y_y_proto = out.File
file_y_y_proto_rawDesc = nil
file_y_y_proto_goTypes = nil
file_y_y_proto_depIdxs = nil
}
+6
View File
@@ -0,0 +1,6 @@
syntax = "proto3";
package psrpc.internal.test.importmapping.y;
option go_package = "example.com/will/be/ignored/y";
message MsgY {}
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package multiple
//go:generate protoc --go_out=paths=source_relative:. --psrpc_out=paths=source_relative:. multiple1.proto multiple2.proto
+142
View File
@@ -0,0 +1,142 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: multiple1.proto
// Multiple proto files in one package
package multiple
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 Msg1 struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Msg1) Reset() {
*x = Msg1{}
if protoimpl.UnsafeEnabled {
mi := &file_multiple1_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Msg1) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Msg1) ProtoMessage() {}
func (x *Msg1) ProtoReflect() protoreflect.Message {
mi := &file_multiple1_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 Msg1.ProtoReflect.Descriptor instead.
func (*Msg1) Descriptor() ([]byte, []int) {
return file_multiple1_proto_rawDescGZIP(), []int{0}
}
var File_multiple1_proto protoreflect.FileDescriptor
var file_multiple1_proto_rawDesc = []byte{
0x0a, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x1c, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x22,
0x06, 0x0a, 0x04, 0x4d, 0x73, 0x67, 0x31, 0x32, 0x56, 0x0a, 0x04, 0x53, 0x76, 0x63, 0x31, 0x12,
0x4e, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x22, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x6d, 0x75,
0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x31, 0x1a, 0x22, 0x2e, 0x70, 0x73,
0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73,
0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x31, 0x42,
0x0b, 0x5a, 0x09, 0x2f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var (
file_multiple1_proto_rawDescOnce sync.Once
file_multiple1_proto_rawDescData = file_multiple1_proto_rawDesc
)
func file_multiple1_proto_rawDescGZIP() []byte {
file_multiple1_proto_rawDescOnce.Do(func() {
file_multiple1_proto_rawDescData = protoimpl.X.CompressGZIP(file_multiple1_proto_rawDescData)
})
return file_multiple1_proto_rawDescData
}
var file_multiple1_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_multiple1_proto_goTypes = []interface{}{
(*Msg1)(nil), // 0: psrpc.internal.test.multiple.Msg1
}
var file_multiple1_proto_depIdxs = []int32{
0, // 0: psrpc.internal.test.multiple.Svc1.Send:input_type -> psrpc.internal.test.multiple.Msg1
0, // 1: psrpc.internal.test.multiple.Svc1.Send:output_type -> psrpc.internal.test.multiple.Msg1
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_multiple1_proto_init() }
func file_multiple1_proto_init() {
if File_multiple1_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_multiple1_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Msg1); 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_multiple1_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_multiple1_proto_goTypes,
DependencyIndexes: file_multiple1_proto_depIdxs,
MessageInfos: file_multiple1_proto_msgTypes,
}.Build()
File_multiple1_proto = out.File
file_multiple1_proto_rawDesc = nil
file_multiple1_proto_goTypes = nil
file_multiple1_proto_depIdxs = nil
}
+11
View File
@@ -0,0 +1,11 @@
syntax = "proto3";
// Multiple proto files in one package
package psrpc.internal.test.multiple;
option go_package = "/multiple";
message Msg1 {}
service Svc1 {
rpc Send(Msg1) returns (Msg1);
}
+96
View File
@@ -0,0 +1,96 @@
// Code generated by protoc-gen-psrpc v0.0.1, DO NOT EDIT.
// source: multiple1.proto
// Multiple proto files in one package
package multiple
import context "context"
import psrpc "github.com/livekit/psrpc"
// =====================
// Svc1 Client Interface
// =====================
type Svc1Client interface {
Send(context.Context, *Msg1, ...psrpc.RequestOpt) (*Msg1, error)
}
// =========================
// Svc1 ServerImpl Interface
// =========================
type Svc1ServerImpl interface {
Send(context.Context, *Msg1) (*Msg1, error)
}
// =====================
// Svc1 Server Interface
// =====================
type Svc1Server interface {
}
// ===========
// Svc1 Client
// ===========
type svc1Client struct {
client psrpc.RPCClient
}
// NewSvc1Client creates a psrpc client that implements the Svc1Client interface.
func NewSvc1Client(clientID string, bus psrpc.MessageBus, opts ...psrpc.ClientOpt) (Svc1Client, error) {
rpcClient, err := psrpc.NewRPCClient("Svc1", clientID, bus, opts...)
if err != nil {
return nil, err
}
return &svc1Client{
client: rpcClient,
}, nil
}
func (c *svc1Client) Send(ctx context.Context, req *Msg1, opts ...psrpc.RequestOpt) (*Msg1, error) {
return psrpc.RequestTopicSingle[*Msg1](ctx, c.client, "Send", "", req, opts...)
}
// ===========
// Svc1 Server
// ===========
type svc1Server struct {
svc Svc1ServerImpl
rpc psrpc.RPCServer
}
// NewSvc1Server builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewSvc1Server(serverID string, svc Svc1ServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOpt) (Svc1Server, error) {
rpcServer := psrpc.NewRPCServer("Svc1", serverID, bus, opts...)
var err error
err = rpcServer.RegisterHandler(psrpc.NewHandler("Send", svc.Send))
if err != nil {
rpcServer.Close()
return nil, err
}
return &svc1Server{
svc: svc,
rpc: rpcServer,
}, nil
}
var psrpcFileDescriptor0 = []byte{
// 113 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcf, 0x2d, 0xcd, 0x29,
0xc9, 0x2c, 0xc8, 0x49, 0x35, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x29, 0x28, 0x2e,
0x2a, 0x48, 0xd6, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x2b, 0x49, 0x2d, 0x2e,
0xd1, 0x83, 0x29, 0x52, 0x62, 0xe3, 0x62, 0xf1, 0x2d, 0x4e, 0x37, 0x34, 0x0a, 0xe3, 0x62, 0x09,
0x2e, 0x4b, 0x36, 0x14, 0xf2, 0xe3, 0x62, 0x09, 0x4e, 0xcd, 0x4b, 0x11, 0x52, 0xd2, 0xc3, 0xa7,
0x4d, 0x0f, 0xa4, 0x47, 0x8a, 0x08, 0x35, 0x4e, 0xdc, 0x51, 0x9c, 0xfa, 0x30, 0x91, 0x24, 0x36,
0xb0, 0x8b, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x3d, 0x3e, 0x25, 0xa4, 0x00, 0x00,
0x00,
}
+153
View File
@@ -0,0 +1,153 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: multiple2.proto
// Multiple proto files in one package
package multiple
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 Msg2 struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Msg2) Reset() {
*x = Msg2{}
if protoimpl.UnsafeEnabled {
mi := &file_multiple2_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Msg2) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Msg2) ProtoMessage() {}
func (x *Msg2) ProtoReflect() protoreflect.Message {
mi := &file_multiple2_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 Msg2.ProtoReflect.Descriptor instead.
func (*Msg2) Descriptor() ([]byte, []int) {
return file_multiple2_proto_rawDescGZIP(), []int{0}
}
var File_multiple2_proto protoreflect.FileDescriptor
var file_multiple2_proto_rawDesc = []byte{
0x0a, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x1c, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x1a,
0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x22, 0x06, 0x0a, 0x04, 0x4d, 0x73, 0x67, 0x32, 0x32, 0xb8, 0x01, 0x0a, 0x04, 0x53, 0x76, 0x63,
0x32, 0x12, 0x4e, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x22, 0x2e, 0x70, 0x73, 0x72, 0x70,
0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e,
0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x32, 0x1a, 0x22, 0x2e,
0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74,
0x65, 0x73, 0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67,
0x32, 0x12, 0x60, 0x0a, 0x16, 0x53, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x22, 0x2e, 0x70, 0x73,
0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73,
0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x31, 0x1a,
0x22, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2e, 0x4d,
0x73, 0x67, 0x31, 0x42, 0x0b, 0x5a, 0x09, 0x2f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_multiple2_proto_rawDescOnce sync.Once
file_multiple2_proto_rawDescData = file_multiple2_proto_rawDesc
)
func file_multiple2_proto_rawDescGZIP() []byte {
file_multiple2_proto_rawDescOnce.Do(func() {
file_multiple2_proto_rawDescData = protoimpl.X.CompressGZIP(file_multiple2_proto_rawDescData)
})
return file_multiple2_proto_rawDescData
}
var file_multiple2_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_multiple2_proto_goTypes = []interface{}{
(*Msg2)(nil), // 0: psrpc.internal.test.multiple.Msg2
(*Msg1)(nil), // 1: psrpc.internal.test.multiple.Msg1
}
var file_multiple2_proto_depIdxs = []int32{
0, // 0: psrpc.internal.test.multiple.Svc2.Send:input_type -> psrpc.internal.test.multiple.Msg2
1, // 1: psrpc.internal.test.multiple.Svc2.SamePackageProtoImport:input_type -> psrpc.internal.test.multiple.Msg1
0, // 2: psrpc.internal.test.multiple.Svc2.Send:output_type -> psrpc.internal.test.multiple.Msg2
1, // 3: psrpc.internal.test.multiple.Svc2.SamePackageProtoImport:output_type -> psrpc.internal.test.multiple.Msg1
2, // [2:4] is the sub-list for method output_type
0, // [0:2] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_multiple2_proto_init() }
func file_multiple2_proto_init() {
if File_multiple2_proto != nil {
return
}
file_multiple1_proto_init()
if !protoimpl.UnsafeEnabled {
file_multiple2_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Msg2); 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_multiple2_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_multiple2_proto_goTypes,
DependencyIndexes: file_multiple2_proto_depIdxs,
MessageInfos: file_multiple2_proto_msgTypes,
}.Build()
File_multiple2_proto = out.File
file_multiple2_proto_rawDesc = nil
file_multiple2_proto_goTypes = nil
file_multiple2_proto_depIdxs = nil
}
+14
View File
@@ -0,0 +1,14 @@
syntax = "proto3";
// Multiple proto files in one package
package psrpc.internal.test.multiple;
option go_package = "/multiple";
import "multiple1.proto";
message Msg2 {}
service Svc2 {
rpc Send(Msg2) returns (Msg2);
rpc SamePackageProtoImport(Msg1) returns (Msg1);
}
+112
View File
@@ -0,0 +1,112 @@
// Code generated by protoc-gen-psrpc v0.0.1, DO NOT EDIT.
// source: multiple2.proto
// Multiple proto files in one package
package multiple
import context "context"
import psrpc "github.com/livekit/psrpc"
// =====================
// Svc2 Client Interface
// =====================
type Svc2Client interface {
Send(context.Context, *Msg2, ...psrpc.RequestOpt) (*Msg2, error)
SamePackageProtoImport(context.Context, *Msg1, ...psrpc.RequestOpt) (*Msg1, error)
}
// =========================
// Svc2 ServerImpl Interface
// =========================
type Svc2ServerImpl interface {
Send(context.Context, *Msg2) (*Msg2, error)
SamePackageProtoImport(context.Context, *Msg1) (*Msg1, error)
}
// =====================
// Svc2 Server Interface
// =====================
type Svc2Server interface {
}
// ===========
// Svc2 Client
// ===========
type svc2Client struct {
client psrpc.RPCClient
}
// NewSvc2Client creates a psrpc client that implements the Svc2Client interface.
func NewSvc2Client(clientID string, bus psrpc.MessageBus, opts ...psrpc.ClientOpt) (Svc2Client, error) {
rpcClient, err := psrpc.NewRPCClient("Svc2", clientID, bus, opts...)
if err != nil {
return nil, err
}
return &svc2Client{
client: rpcClient,
}, nil
}
func (c *svc2Client) Send(ctx context.Context, req *Msg2, opts ...psrpc.RequestOpt) (*Msg2, error) {
return psrpc.RequestTopicSingle[*Msg2](ctx, c.client, "Send", "", req, opts...)
}
func (c *svc2Client) SamePackageProtoImport(ctx context.Context, req *Msg1, opts ...psrpc.RequestOpt) (*Msg1, error) {
return psrpc.RequestTopicSingle[*Msg1](ctx, c.client, "SamePackageProtoImport", "", req, opts...)
}
// ===========
// Svc2 Server
// ===========
type svc2Server struct {
svc Svc2ServerImpl
rpc psrpc.RPCServer
}
// NewSvc2Server builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewSvc2Server(serverID string, svc Svc2ServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOpt) (Svc2Server, error) {
rpcServer := psrpc.NewRPCServer("Svc2", serverID, bus, opts...)
var err error
err = rpcServer.RegisterHandler(psrpc.NewHandler("Send", svc.Send))
if err != nil {
rpcServer.Close()
return nil, err
}
err = rpcServer.RegisterHandler(psrpc.NewHandler("SamePackageProtoImport", svc.SamePackageProtoImport))
if err != nil {
rpcServer.Close()
return nil, err
}
return &svc2Server{
svc: svc,
rpc: rpcServer,
}, nil
}
var psrpcFileDescriptor1 = []byte{
// 151 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcf, 0x2d, 0xcd, 0x29,
0xc9, 0x2c, 0xc8, 0x49, 0x35, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x29, 0x28, 0x2e,
0x2a, 0x48, 0xd6, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x2b, 0x49, 0x2d, 0x2e,
0xd1, 0x83, 0x29, 0x92, 0x82, 0x2b, 0x37, 0x84, 0x28, 0x57, 0x62, 0xe3, 0x62, 0xf1, 0x2d, 0x4e,
0x37, 0x32, 0xda, 0xc1, 0xc8, 0xc5, 0x12, 0x5c, 0x96, 0x6c, 0x24, 0xe4, 0xc7, 0xc5, 0x12, 0x9c,
0x9a, 0x97, 0x22, 0xa4, 0xa4, 0x87, 0xcf, 0x20, 0x3d, 0x90, 0x26, 0x29, 0x22, 0xd4, 0x08, 0x25,
0x70, 0x89, 0x05, 0x27, 0xe6, 0xa6, 0x06, 0x24, 0x26, 0x67, 0x27, 0xa6, 0xa7, 0x06, 0x80, 0x2c,
0xf5, 0xcc, 0x2d, 0xc8, 0x2f, 0x2a, 0x21, 0xc2, 0x06, 0x43, 0x22, 0x6c, 0x30, 0x74, 0xe2, 0x8e,
0xe2, 0xd4, 0x87, 0x89, 0x24, 0xb1, 0x81, 0xbd, 0x65, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x06,
0x9e, 0x42, 0x70, 0x18, 0x01, 0x00, 0x00,
}
+20
View File
@@ -0,0 +1,20 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package multiple
import "testing"
func TestCompilation(t *testing.T) {
// Test passes if this package compiles
}
+7
View File
@@ -0,0 +1,7 @@
package my_service
import "testing"
func TestCompilation(t *testing.T) {
// Test passes if this package compiles
}
+3
View File
@@ -0,0 +1,3 @@
package my_service
//go:generate protoc --go_out=paths=source_relative:. --psrpc_out=paths=source_relative:. -I ../../../protoc-gen-psrpc/options -I=. my_service.proto
+347
View File
@@ -0,0 +1,347 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: my_service.proto
package my_service
import (
_ "github.com/livekit/psrpc/protoc-gen-psrpc/options"
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 Ignored struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Ignored) Reset() {
*x = Ignored{}
if protoimpl.UnsafeEnabled {
mi := &file_my_service_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Ignored) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Ignored) ProtoMessage() {}
func (x *Ignored) ProtoReflect() protoreflect.Message {
mi := &file_my_service_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 Ignored.ProtoReflect.Descriptor instead.
func (*Ignored) Descriptor() ([]byte, []int) {
return file_my_service_proto_rawDescGZIP(), []int{0}
}
type MyRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *MyRequest) Reset() {
*x = MyRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_my_service_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MyRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MyRequest) ProtoMessage() {}
func (x *MyRequest) ProtoReflect() protoreflect.Message {
mi := &file_my_service_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 MyRequest.ProtoReflect.Descriptor instead.
func (*MyRequest) Descriptor() ([]byte, []int) {
return file_my_service_proto_rawDescGZIP(), []int{1}
}
type MyResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *MyResponse) Reset() {
*x = MyResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_my_service_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MyResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MyResponse) ProtoMessage() {}
func (x *MyResponse) ProtoReflect() protoreflect.Message {
mi := &file_my_service_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 MyResponse.ProtoReflect.Descriptor instead.
func (*MyResponse) Descriptor() ([]byte, []int) {
return file_my_service_proto_rawDescGZIP(), []int{2}
}
type MyUpdate struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *MyUpdate) Reset() {
*x = MyUpdate{}
if protoimpl.UnsafeEnabled {
mi := &file_my_service_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MyUpdate) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MyUpdate) ProtoMessage() {}
func (x *MyUpdate) ProtoReflect() protoreflect.Message {
mi := &file_my_service_proto_msgTypes[3]
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 MyUpdate.ProtoReflect.Descriptor instead.
func (*MyUpdate) Descriptor() ([]byte, []int) {
return file_my_service_proto_rawDescGZIP(), []int{3}
}
var File_my_service_proto protoreflect.FileDescriptor
var file_my_service_proto_rawDesc = []byte{
0x0a, 0x10, 0x6d, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x21, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x1a, 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x22, 0x09, 0x0a, 0x07, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x22,
0x0b, 0x0a, 0x09, 0x4d, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0c, 0x0a, 0x0a,
0x4d, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0a, 0x0a, 0x08, 0x4d, 0x79,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x32, 0xcd, 0x05, 0x0a, 0x09, 0x4d, 0x79, 0x53, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x12, 0x68, 0x0a, 0x09, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x52, 0x50,
0x43, 0x12, 0x2c, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x2d, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x2e, 0x4d, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73,
0x0a, 0x0c, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x76, 0x65, 0x52, 0x50, 0x43, 0x12, 0x2c,
0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e,
0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x2e, 0x4d, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x70,
0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65,
0x73, 0x74, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x2e, 0x4d, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xb2, 0x89, 0x01,
0x02, 0x20, 0x01, 0x12, 0x6f, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12,
0x2c, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x2e, 0x4d, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e,
0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74,
0x65, 0x73, 0x74, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x2e, 0x4d, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xb2, 0x89,
0x01, 0x02, 0x08, 0x01, 0x12, 0x7b, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f,
0x6e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x2c, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x75, 0x73,
0x74, 0x6f, 0x6d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x79, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f,
0x6d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x0c, 0xb2, 0x89, 0x01, 0x02, 0x18, 0x01, 0xb2, 0x89, 0x01, 0x02, 0x08,
0x01, 0x12, 0x70, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x55, 0x70, 0x64, 0x61,
0x74, 0x65, 0x12, 0x2a, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x1a, 0x2b,
0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e,
0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x2e, 0x4d, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, 0x06, 0xb2, 0x89, 0x01,
0x02, 0x10, 0x01, 0x12, 0x80, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65,
0x67, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2a, 0x2e, 0x70, 0x73, 0x72, 0x70,
0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e,
0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, 0x67,
0x6e, 0x6f, 0x72, 0x65, 0x64, 0x1a, 0x2b, 0x2e, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x75, 0x73, 0x74,
0x6f, 0x6d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x79, 0x55, 0x70, 0x64, 0x61,
0x74, 0x65, 0x22, 0x12, 0xb2, 0x89, 0x01, 0x02, 0x10, 0x01, 0xb2, 0x89, 0x01, 0x02, 0x18, 0x01,
0xb2, 0x89, 0x01, 0x02, 0x08, 0x01, 0x42, 0x0d, 0x5a, 0x0b, 0x2f, 0x6d, 0x79, 0x5f, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_my_service_proto_rawDescOnce sync.Once
file_my_service_proto_rawDescData = file_my_service_proto_rawDesc
)
func file_my_service_proto_rawDescGZIP() []byte {
file_my_service_proto_rawDescOnce.Do(func() {
file_my_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_my_service_proto_rawDescData)
})
return file_my_service_proto_rawDescData
}
var file_my_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_my_service_proto_goTypes = []interface{}{
(*Ignored)(nil), // 0: psrpc.internal.test.customservice.Ignored
(*MyRequest)(nil), // 1: psrpc.internal.test.customservice.MyRequest
(*MyResponse)(nil), // 2: psrpc.internal.test.customservice.MyResponse
(*MyUpdate)(nil), // 3: psrpc.internal.test.customservice.MyUpdate
}
var file_my_service_proto_depIdxs = []int32{
1, // 0: psrpc.internal.test.customservice.MyService.NormalRPC:input_type -> psrpc.internal.test.customservice.MyRequest
1, // 1: psrpc.internal.test.customservice.MyService.IntensiveRPC:input_type -> psrpc.internal.test.customservice.MyRequest
1, // 2: psrpc.internal.test.customservice.MyService.GetStats:input_type -> psrpc.internal.test.customservice.MyRequest
1, // 3: psrpc.internal.test.customservice.MyService.GetRegionStats:input_type -> psrpc.internal.test.customservice.MyRequest
0, // 4: psrpc.internal.test.customservice.MyService.ProcessUpdate:input_type -> psrpc.internal.test.customservice.Ignored
0, // 5: psrpc.internal.test.customservice.MyService.UpdateRegionState:input_type -> psrpc.internal.test.customservice.Ignored
2, // 6: psrpc.internal.test.customservice.MyService.NormalRPC:output_type -> psrpc.internal.test.customservice.MyResponse
2, // 7: psrpc.internal.test.customservice.MyService.IntensiveRPC:output_type -> psrpc.internal.test.customservice.MyResponse
2, // 8: psrpc.internal.test.customservice.MyService.GetStats:output_type -> psrpc.internal.test.customservice.MyResponse
2, // 9: psrpc.internal.test.customservice.MyService.GetRegionStats:output_type -> psrpc.internal.test.customservice.MyResponse
3, // 10: psrpc.internal.test.customservice.MyService.ProcessUpdate:output_type -> psrpc.internal.test.customservice.MyUpdate
3, // 11: psrpc.internal.test.customservice.MyService.UpdateRegionState:output_type -> psrpc.internal.test.customservice.MyUpdate
6, // [6:12] is the sub-list for method output_type
0, // [0:6] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_my_service_proto_init() }
func file_my_service_proto_init() {
if File_my_service_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_my_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Ignored); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_my_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MyRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_my_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MyResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_my_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MyUpdate); 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_my_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_my_service_proto_goTypes,
DependencyIndexes: file_my_service_proto_depIdxs,
MessageInfos: file_my_service_proto_msgTypes,
}.Build()
File_my_service_proto = out.File
file_my_service_proto_rawDesc = nil
file_my_service_proto_goTypes = nil
file_my_service_proto_depIdxs = nil
}
+48
View File
@@ -0,0 +1,48 @@
syntax = "proto3";
package psrpc.internal.test.customservice;
import "options.proto";
// Test to make sure that a service with no methods doesn't break.
option go_package = "/my_service";
service MyService {
// A normal RPC - one request, one response. The request will be handled by the first available server
rpc NormalRPC(MyRequest) returns (MyResponse);
// An RPC with a server affinity function for handler selection.
rpc IntensiveRPC(MyRequest) returns (MyResponse) {
option (psrpc.options).affinity_func = true;
};
// A multi-rpc - a client will send one request, and receive one response each from every server
rpc GetStats(MyRequest) returns (MyResponse) {
option (psrpc.options).multi = true;
};
// An RPC with topics - a client can send one request, and receive one response from each server in one region
rpc GetRegionStats(MyRequest) returns (MyResponse) {
option (psrpc.options).topics = true;
option (psrpc.options).multi = true;
}
// A queue subscription - even if multiple clients are subscribed, only one will receive this update.
// The request parameter (Ignored) will be ignored when generating go files.
rpc ProcessUpdate(Ignored) returns (MyUpdate) {
option (psrpc.options).subscription = true;
};
// A subscription with topics - every client subscribed to the topic will receive every update.
// The request parameter (Ignored) will be ignored when generating go files.
rpc UpdateRegionState(Ignored) returns (MyUpdate) {
option (psrpc.options).subscription = true;
option (psrpc.options).topics = true;
option (psrpc.options).multi = true;
}
}
message Ignored {}
message MyRequest {}
message MyResponse {}
message MyUpdate {}
@@ -0,0 +1,192 @@
// Code generated by protoc-gen-psrpc v0.0.1, DO NOT EDIT.
// source: my_service.proto
package my_service
import context "context"
import psrpc1 "github.com/livekit/psrpc"
// ==========================
// MyService Client Interface
// ==========================
type MyServiceClient interface {
// A normal RPC - one request, one response. The request will be handled by the first available server
NormalRPC(context.Context, *MyRequest, ...psrpc1.RequestOpt) (*MyResponse, error)
// An RPC with a server affinity function for handler selection.
IntensiveRPC(context.Context, *MyRequest, ...psrpc1.RequestOpt) (*MyResponse, error)
// A multi-rpc - a client will send one request, and receive one response each from every server
GetStats(context.Context, *MyRequest, ...psrpc1.RequestOpt) (<-chan *psrpc1.Response[*MyResponse], error)
// An RPC with topics - a client can send one request, and receive one response from each server in one region
GetRegionStats(context.Context, string, *MyRequest, ...psrpc1.RequestOpt) (<-chan *psrpc1.Response[*MyResponse], error)
// A queue subscription - even if multiple clients are subscribed, only one will receive this update.
// The request parameter (Ignored) will be ignored when generating go files.
SubscribeProcessUpdate(context.Context) (psrpc1.Subscription[*MyUpdate], error)
// A subscription with topics - every client subscribed to the topic will receive every update.
// The request parameter (Ignored) will be ignored when generating go files.
SubscribeUpdateRegionState(context.Context, string) (psrpc1.Subscription[*MyUpdate], error)
}
// ==============================
// MyService ServerImpl Interface
// ==============================
type MyServiceServerImpl interface {
// A normal RPC - one request, one response. The request will be handled by the first available server
NormalRPC(context.Context, *MyRequest) (*MyResponse, error)
// An RPC with a server affinity function for handler selection.
IntensiveRPC(context.Context, *MyRequest) (*MyResponse, error)
IntensiveRPCAffinity(*MyRequest) float32
// A multi-rpc - a client will send one request, and receive one response each from every server
GetStats(context.Context, *MyRequest) (*MyResponse, error)
// An RPC with topics - a client can send one request, and receive one response from each server in one region
GetRegionStats(context.Context, *MyRequest) (*MyResponse, error)
}
// ==========================
// MyService Server Interface
// ==========================
type MyServiceServer interface {
// An RPC with topics - a client can send one request, and receive one response from each server in one region
RegisterGetRegionStatsTopic(string) error
DeregisterGetRegionStatsTopic(string) error
// A queue subscription - even if multiple clients are subscribed, only one will receive this update.
// The request parameter (Ignored) will be ignored when generating go files.
PublishProcessUpdate(context.Context, *MyUpdate) error
// A subscription with topics - every client subscribed to the topic will receive every update.
// The request parameter (Ignored) will be ignored when generating go files.
PublishUpdateRegionState(context.Context, string, *MyUpdate) error
}
// ================
// MyService Client
// ================
type myServiceClient struct {
client psrpc1.RPCClient
}
// NewMyServiceClient creates a psrpc client that implements the MyServiceClient interface.
func NewMyServiceClient(clientID string, bus psrpc1.MessageBus, opts ...psrpc1.ClientOpt) (MyServiceClient, error) {
rpcClient, err := psrpc1.NewRPCClient("MyService", clientID, bus, opts...)
if err != nil {
return nil, err
}
return &myServiceClient{
client: rpcClient,
}, nil
}
func (c *myServiceClient) NormalRPC(ctx context.Context, req *MyRequest, opts ...psrpc1.RequestOpt) (*MyResponse, error) {
return psrpc1.RequestTopicSingle[*MyResponse](ctx, c.client, "NormalRPC", "", req, opts...)
}
func (c *myServiceClient) IntensiveRPC(ctx context.Context, req *MyRequest, opts ...psrpc1.RequestOpt) (*MyResponse, error) {
return psrpc1.RequestTopicSingle[*MyResponse](ctx, c.client, "IntensiveRPC", "", req, opts...)
}
func (c *myServiceClient) GetStats(ctx context.Context, req *MyRequest, opts ...psrpc1.RequestOpt) (<-chan *psrpc1.Response[*MyResponse], error) {
return psrpc1.RequestTopicAll[*MyResponse](ctx, c.client, "GetStats", "", req, opts...)
}
func (c *myServiceClient) GetRegionStats(ctx context.Context, topic string, req *MyRequest, opts ...psrpc1.RequestOpt) (<-chan *psrpc1.Response[*MyResponse], error) {
return psrpc1.RequestTopicAll[*MyResponse](ctx, c.client, "GetRegionStats", topic, req, opts...)
}
func (c *myServiceClient) SubscribeProcessUpdate(ctx context.Context) (psrpc1.Subscription[*MyUpdate], error) {
return psrpc1.SubscribeTopicQueue[*MyUpdate](ctx, c.client, "ProcessUpdate", "")
}
func (c *myServiceClient) SubscribeUpdateRegionState(ctx context.Context, topic string) (psrpc1.Subscription[*MyUpdate], error) {
return psrpc1.SubscribeTopic[*MyUpdate](ctx, c.client, "UpdateRegionState", topic)
}
// ================
// MyService Server
// ================
type myServiceServer struct {
svc MyServiceServerImpl
rpc psrpc1.RPCServer
}
// NewMyServiceServer builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewMyServiceServer(serverID string, svc MyServiceServerImpl, bus psrpc1.MessageBus, opts ...psrpc1.ServerOpt) (MyServiceServer, error) {
rpcServer := psrpc1.NewRPCServer("MyService", serverID, bus, opts...)
var err error
err = rpcServer.RegisterHandler(psrpc1.NewHandler("NormalRPC", svc.NormalRPC))
if err != nil {
rpcServer.Close()
return nil, err
}
err = rpcServer.RegisterHandler(psrpc1.NewHandlerWithAffinity("IntensiveRPC", svc.IntensiveRPC, svc.IntensiveRPCAffinity))
if err != nil {
rpcServer.Close()
return nil, err
}
err = rpcServer.RegisterHandler(psrpc1.NewHandler("GetStats", svc.GetStats))
if err != nil {
rpcServer.Close()
return nil, err
}
return &myServiceServer{
svc: svc,
rpc: rpcServer,
}, nil
}
func (s *myServiceServer) RegisterGetRegionStatsTopic(topic string) error {
return s.rpc.RegisterHandler(psrpc1.NewTopicHandler("GetRegionStats", topic, s.svc.GetRegionStats))
}
func (s *myServiceServer) DeregisterGetRegionStatsTopic(topic string) error {
return s.rpc.DeregisterTopic("GetRegionStats", topic)
}
func (s *myServiceServer) PublishProcessUpdate(ctx context.Context, msg *MyUpdate) error {
return s.rpc.PublishTopic(ctx, "ProcessUpdate", "", msg)
}
func (s *myServiceServer) PublishUpdateRegionState(ctx context.Context, topic string, msg *MyUpdate) error {
return s.rpc.PublishTopic(ctx, "UpdateRegionState", topic, msg)
}
var psrpcFileDescriptor0 = []byte{
// 288 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x93, 0x4f, 0x4e, 0xf3, 0x30,
0x10, 0xc5, 0xe5, 0x4f, 0x1f, 0xc5, 0x9d, 0xb6, 0x28, 0x78, 0x55, 0x65, 0x05, 0x59, 0xf2, 0xc7,
0x48, 0x70, 0x03, 0x58, 0x54, 0x5d, 0x14, 0x55, 0xa9, 0xd8, 0xb0, 0x41, 0x21, 0x1d, 0x95, 0x48,
0x8d, 0x6d, 0x3c, 0xd3, 0x42, 0x8e, 0x90, 0xeb, 0xe4, 0x04, 0x1c, 0x0d, 0x15, 0x57, 0x74, 0x49,
0x36, 0xed, 0xd2, 0xd6, 0xf3, 0xfb, 0xf9, 0x69, 0xe6, 0x41, 0x54, 0x56, 0x2f, 0x84, 0x7e, 0x5d,
0xe4, 0xa8, 0x9d, 0xb7, 0x6c, 0xd5, 0xb9, 0x23, 0xef, 0x72, 0x5d, 0x18, 0x46, 0x6f, 0xb2, 0xa5,
0x66, 0x24, 0xd6, 0xf9, 0x8a, 0xd8, 0x96, 0x5b, 0x61, 0x3c, 0xb0, 0x8e, 0x0b, 0x6b, 0x28, 0xbc,
0x48, 0xba, 0x70, 0x3c, 0x5e, 0x18, 0xeb, 0x71, 0x9e, 0xf4, 0xa0, 0x3b, 0xa9, 0x52, 0x7c, 0x5f,
0x21, 0x71, 0xd2, 0x07, 0xd8, 0x1c, 0xc8, 0x59, 0x43, 0x98, 0x00, 0xc8, 0x49, 0xf5, 0xe4, 0xe6,
0x19, 0xe3, 0xed, 0xd7, 0xd1, 0x46, 0x37, 0x0b, 0x76, 0xea, 0x0d, 0xba, 0x8f, 0xd6, 0x97, 0xd9,
0x32, 0x9d, 0x3e, 0xa8, 0x2b, 0xfd, 0x27, 0x5f, 0xff, 0x22, 0xe2, 0xeb, 0x96, 0xea, 0xf0, 0x07,
0x45, 0xd0, 0x1f, 0x1b, 0x46, 0x43, 0xc5, 0x1a, 0xf7, 0x0d, 0x4b, 0x3a, 0x4d, 0x2d, 0xfe, 0x9d,
0x09, 0x65, 0x41, 0x8e, 0x90, 0x67, 0x9c, 0x31, 0x1d, 0x00, 0x28, 0x85, 0xfa, 0x80, 0x93, 0x11,
0x72, 0x8a, 0x8b, 0xc2, 0x9a, 0x03, 0x60, 0x65, 0x53, 0x8b, 0xff, 0x52, 0x0c, 0x85, 0x72, 0x30,
0x98, 0x7a, 0x9b, 0x23, 0x51, 0x98, 0xb3, 0xba, 0x68, 0xe1, 0xb4, 0x5d, 0x9d, 0xf8, 0xb2, 0x15,
0x35, 0x18, 0x87, 0xa8, 0x91, 0x50, 0x9f, 0x70, 0x1a, 0x6e, 0x76, 0x69, 0xf7, 0x48, 0x85, 0xa6,
0x16, 0x1d, 0x29, 0x22, 0x31, 0x14, 0xf7, 0x83, 0xe7, 0xde, 0xcd, 0xae, 0x3b, 0xaf, 0x9d, 0x9f,
0x2a, 0xdc, 0x7d, 0x07, 0x00, 0x00, 0xff, 0xff, 0xee, 0x5b, 0x87, 0x9b, 0x50, 0x03, 0x00, 0x00,
}
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package no_package_name
//go:generate protoc --go_out=module=github.com/livekit/psrpc/internal/test/no_package_name:. --psrpc_out=module=github.com/livekit/psrpc/internal/test/no_package_name:. no_package_name.proto
@@ -0,0 +1,137 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: no_package_name.proto
package no_package_name
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 Msg struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Msg) Reset() {
*x = Msg{}
if protoimpl.UnsafeEnabled {
mi := &file_no_package_name_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Msg) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Msg) ProtoMessage() {}
func (x *Msg) ProtoReflect() protoreflect.Message {
mi := &file_no_package_name_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 Msg.ProtoReflect.Descriptor instead.
func (*Msg) Descriptor() ([]byte, []int) {
return file_no_package_name_proto_rawDescGZIP(), []int{0}
}
var File_no_package_name_proto protoreflect.FileDescriptor
var file_no_package_name_proto_rawDesc = []byte{
0x0a, 0x15, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x05, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x32, 0x19,
0x0a, 0x03, 0x53, 0x76, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x04, 0x2e,
0x4d, 0x73, 0x67, 0x1a, 0x04, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, 0x74,
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2f,
0x70, 0x73, 0x72, 0x70, 0x63, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74,
0x65, 0x73, 0x74, 0x2f, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e,
0x61, 0x6d, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_no_package_name_proto_rawDescOnce sync.Once
file_no_package_name_proto_rawDescData = file_no_package_name_proto_rawDesc
)
func file_no_package_name_proto_rawDescGZIP() []byte {
file_no_package_name_proto_rawDescOnce.Do(func() {
file_no_package_name_proto_rawDescData = protoimpl.X.CompressGZIP(file_no_package_name_proto_rawDescData)
})
return file_no_package_name_proto_rawDescData
}
var file_no_package_name_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_no_package_name_proto_goTypes = []interface{}{
(*Msg)(nil), // 0: Msg
}
var file_no_package_name_proto_depIdxs = []int32{
0, // 0: Svc.Send:input_type -> Msg
0, // 1: Svc.Send:output_type -> Msg
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_no_package_name_proto_init() }
func file_no_package_name_proto_init() {
if File_no_package_name_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_no_package_name_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Msg); 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_no_package_name_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_no_package_name_proto_goTypes,
DependencyIndexes: file_no_package_name_proto_depIdxs,
MessageInfos: file_no_package_name_proto_msgTypes,
}.Build()
File_no_package_name_proto = out.File
file_no_package_name_proto_rawDesc = nil
file_no_package_name_proto_goTypes = nil
file_no_package_name_proto_depIdxs = nil
}
@@ -0,0 +1,11 @@
syntax = "proto3";
// No package name
option go_package = "github.com/livekit/psrpc/internal/test/no_package_name";
message Msg {}
service Svc {
rpc Send(Msg) returns(Msg);
}
@@ -0,0 +1,94 @@
// Code generated by protoc-gen-psrpc v0.0.1, DO NOT EDIT.
// source: no_package_name.proto
package no_package_name
import context "context"
import psrpc "github.com/livekit/psrpc"
// ====================
// Svc Client Interface
// ====================
type SvcClient interface {
Send(context.Context, *Msg, ...psrpc.RequestOpt) (*Msg, error)
}
// ========================
// Svc ServerImpl Interface
// ========================
type SvcServerImpl interface {
Send(context.Context, *Msg) (*Msg, error)
}
// ====================
// Svc Server Interface
// ====================
type SvcServer interface {
}
// ==========
// Svc Client
// ==========
type svcClient struct {
client psrpc.RPCClient
}
// NewSvcClient creates a psrpc client that implements the SvcClient interface.
func NewSvcClient(clientID string, bus psrpc.MessageBus, opts ...psrpc.ClientOpt) (SvcClient, error) {
rpcClient, err := psrpc.NewRPCClient("Svc", clientID, bus, opts...)
if err != nil {
return nil, err
}
return &svcClient{
client: rpcClient,
}, nil
}
func (c *svcClient) Send(ctx context.Context, req *Msg, opts ...psrpc.RequestOpt) (*Msg, error) {
return psrpc.RequestTopicSingle[*Msg](ctx, c.client, "Send", "", req, opts...)
}
// ==========
// Svc Server
// ==========
type svcServer struct {
svc SvcServerImpl
rpc psrpc.RPCServer
}
// NewSvcServer builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewSvcServer(serverID string, svc SvcServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOpt) (SvcServer, error) {
rpcServer := psrpc.NewRPCServer("Svc", serverID, bus, opts...)
var err error
err = rpcServer.RegisterHandler(psrpc.NewHandler("Send", svc.Send))
if err != nil {
rpcServer.Close()
return nil, err
}
return &svcServer{
svc: svc,
rpc: rpcServer,
}, nil
}
var psrpcFileDescriptor0 = []byte{
// 128 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcd, 0xcb, 0x8f, 0x2f,
0x48, 0x4c, 0xce, 0x4e, 0x4c, 0x4f, 0x8d, 0xcf, 0x4b, 0xcc, 0x4d, 0xd5, 0x2b, 0x28, 0xca, 0x2f,
0xc9, 0x57, 0x62, 0xe5, 0x62, 0xf6, 0x2d, 0x4e, 0x37, 0x92, 0xe4, 0x62, 0x0e, 0x2e, 0x4b, 0x16,
0x12, 0xe2, 0x62, 0x09, 0x4e, 0xcd, 0x4b, 0x11, 0x62, 0xd1, 0xf3, 0x2d, 0x4e, 0x97, 0x02, 0x93,
0x4e, 0x16, 0x51, 0x66, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x39,
0x99, 0x65, 0xa9, 0xd9, 0x99, 0x25, 0xfa, 0x05, 0xc5, 0x45, 0x05, 0xc9, 0xfa, 0x99, 0x79, 0x25,
0xa9, 0x45, 0x79, 0x89, 0x39, 0xfa, 0x25, 0xa9, 0xc5, 0x25, 0xfa, 0x68, 0x36, 0x24, 0xb1, 0x81,
0xad, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x79, 0xb2, 0x2e, 0x0a, 0x7b, 0x00, 0x00, 0x00,
}
@@ -0,0 +1,20 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package no_package_name_importer
import "testing"
func TestCompilation(t *testing.T) {
// Test passes if this package compiles
}
@@ -0,0 +1,16 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package no_package_name_importer
//go:generate protoc --proto_path=../ --go_out=module=github.com/livekit/psrpc/internal/test:../ --psrpc_out=module=github.com/livekit/psrpc/internal/test:../ ../no_package_name_importer/no_package_name_importer.proto
@@ -0,0 +1,76 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: no_package_name_importer/no_package_name_importer.proto
package no_package_name_importer
import (
no_package_name "github.com/livekit/psrpc/internal/test/no_package_name"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
)
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)
)
var File_no_package_name_importer_no_package_name_importer_proto protoreflect.FileDescriptor
var file_no_package_name_importer_no_package_name_importer_proto_rawDesc = []byte{
0x0a, 0x37, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d,
0x65, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2f, 0x6e, 0x6f, 0x5f, 0x70, 0x61,
0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72,
0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x25, 0x6e, 0x6f, 0x5f, 0x70, 0x61,
0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2f, 0x6e, 0x6f, 0x5f, 0x70, 0x61,
0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x32, 0x1c, 0x0a, 0x04, 0x53, 0x76, 0x63, 0x32, 0x12, 0x14, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68,
0x6f, 0x64, 0x12, 0x04, 0x2e, 0x4d, 0x73, 0x67, 0x1a, 0x04, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x41,
0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x76,
0x65, 0x6b, 0x69, 0x74, 0x2f, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b,
0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65,
0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var file_no_package_name_importer_no_package_name_importer_proto_goTypes = []interface{}{
(*no_package_name.Msg)(nil), // 0: Msg
}
var file_no_package_name_importer_no_package_name_importer_proto_depIdxs = []int32{
0, // 0: Svc2.Method:input_type -> Msg
0, // 1: Svc2.Method:output_type -> Msg
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_no_package_name_importer_no_package_name_importer_proto_init() }
func file_no_package_name_importer_no_package_name_importer_proto_init() {
if File_no_package_name_importer_no_package_name_importer_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_no_package_name_importer_no_package_name_importer_proto_rawDesc,
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_no_package_name_importer_no_package_name_importer_proto_goTypes,
DependencyIndexes: file_no_package_name_importer_no_package_name_importer_proto_depIdxs,
}.Build()
File_no_package_name_importer_no_package_name_importer_proto = out.File
file_no_package_name_importer_no_package_name_importer_proto_rawDesc = nil
file_no_package_name_importer_no_package_name_importer_proto_goTypes = nil
file_no_package_name_importer_no_package_name_importer_proto_depIdxs = nil
}
@@ -0,0 +1,11 @@
syntax = "proto3";
// Import another proto file that doesn't have a package name
import "no_package_name/no_package_name.proto"; // import is relative to protoc's option --proto_path
option go_package = "github.com/livekit/psrpc/internal/test/no_package_name_importer";
service Svc2 {
rpc Method(Msg) returns (Msg);
}
@@ -0,0 +1,96 @@
// Code generated by protoc-gen-psrpc v0.0.1, DO NOT EDIT.
// source: no_package_name_importer/no_package_name_importer.proto
package no_package_name_importer
import context "context"
import psrpc "github.com/livekit/psrpc"
import no_package_name "github.com/livekit/psrpc/internal/test/no_package_name"
// =====================
// Svc2 Client Interface
// =====================
type Svc2Client interface {
Method(context.Context, *no_package_name.Msg, ...psrpc.RequestOpt) (*no_package_name.Msg, error)
}
// =========================
// Svc2 ServerImpl Interface
// =========================
type Svc2ServerImpl interface {
Method(context.Context, *no_package_name.Msg) (*no_package_name.Msg, error)
}
// =====================
// Svc2 Server Interface
// =====================
type Svc2Server interface {
}
// ===========
// Svc2 Client
// ===========
type svc2Client struct {
client psrpc.RPCClient
}
// NewSvc2Client creates a psrpc client that implements the Svc2Client interface.
func NewSvc2Client(clientID string, bus psrpc.MessageBus, opts ...psrpc.ClientOpt) (Svc2Client, error) {
rpcClient, err := psrpc.NewRPCClient("Svc2", clientID, bus, opts...)
if err != nil {
return nil, err
}
return &svc2Client{
client: rpcClient,
}, nil
}
func (c *svc2Client) Method(ctx context.Context, req *no_package_name.Msg, opts ...psrpc.RequestOpt) (*no_package_name.Msg, error) {
return psrpc.RequestTopicSingle[*no_package_name.Msg](ctx, c.client, "Method", "", req, opts...)
}
// ===========
// Svc2 Server
// ===========
type svc2Server struct {
svc Svc2ServerImpl
rpc psrpc.RPCServer
}
// NewSvc2Server builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewSvc2Server(serverID string, svc Svc2ServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOpt) (Svc2Server, error) {
rpcServer := psrpc.NewRPCServer("Svc2", serverID, bus, opts...)
var err error
err = rpcServer.RegisterHandler(psrpc.NewHandler("Method", svc.Method))
if err != nil {
rpcServer.Close()
return nil, err
}
return &svc2Server{
svc: svc,
rpc: rpcServer,
}, nil
}
var psrpcFileDescriptor0 = []byte{
// 144 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0xcf, 0xcb, 0x8f, 0x2f,
0x48, 0x4c, 0xce, 0x4e, 0x4c, 0x4f, 0x8d, 0xcf, 0x4b, 0xcc, 0x4d, 0x8d, 0xcf, 0xcc, 0x2d, 0xc8,
0x2f, 0x2a, 0x49, 0x2d, 0xd2, 0xc7, 0x25, 0xa1, 0x57, 0x50, 0x94, 0x5f, 0x92, 0x2f, 0xa5, 0x8a,
0x26, 0x8f, 0xae, 0x1e, 0xa2, 0xcc, 0x48, 0x86, 0x8b, 0x25, 0xb8, 0x2c, 0xd9, 0x48, 0x48, 0x84,
0x8b, 0xcd, 0x37, 0xb5, 0x24, 0x23, 0x3f, 0x45, 0x88, 0x45, 0xcf, 0xb7, 0x38, 0x5d, 0x0a, 0x4c,
0x3a, 0x39, 0x46, 0xd9, 0xa7, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0xe7,
0x64, 0x96, 0xa5, 0x66, 0x67, 0x96, 0xe8, 0x17, 0x14, 0x17, 0x15, 0x24, 0xeb, 0x67, 0xe6, 0x95,
0xa4, 0x16, 0xe5, 0x25, 0xe6, 0xe8, 0x97, 0xa4, 0x16, 0x97, 0xe0, 0x74, 0x4d, 0x12, 0x1b, 0xd8,
0x1e, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x62, 0x56, 0x40, 0xc9, 0x00, 0x00, 0x00,
}
+199
View File
@@ -0,0 +1,199 @@
package test
import (
"context"
"math/rand"
"sync"
"testing"
"time"
"github.com/go-redis/redis/v8"
"github.com/lithammer/shortuuid/v3"
"github.com/stretchr/testify/require"
"github.com/livekit/psrpc"
"github.com/livekit/psrpc/internal/test/my_service"
)
func TestGeneratedService(t *testing.T) {
rc := redis.NewUniversalClient(&redis.UniversalOptions{Addrs: []string{"localhost:6379"}})
bus := psrpc.NewRedisMessageBus(rc)
ctx := context.Background()
req := &my_service.MyRequest{}
update := &my_service.MyUpdate{}
sA := createServer(t, bus)
sB := createServer(t, bus)
cA := createClient(t, bus)
cB := createClient(t, bus)
// rpc NormalRPC(MyRequest) returns (MyResponse);
_, err := cA.NormalRPC(ctx, req)
require.NoError(t, err)
require.Equal(t, 1, sA.counts["NormalRPC"]+sB.counts["NormalRPC"])
// rpc IntensiveRPC(MyRequest) returns (MyResponse) {
// option (psrpc.options).affinity_func = true;
_, err = cB.IntensiveRPC(ctx, req)
require.NoError(t, err)
require.Equal(t, 1, sA.counts["IntensiveRPC"]+sB.counts["IntensiveRPC"])
require.Equal(t, 1, sA.counts["IntensiveRPCAffinity"])
require.Equal(t, 1, sB.counts["IntensiveRPCAffinity"])
// rpc GetStats(MyRequest) returns (MyResponse) {
// option (psrpc.options).multi = true;
respChan, err := cA.GetStats(ctx, req)
require.NoError(t, err)
for i := 0; i < 2; i++ {
select {
case res := <-respChan:
require.NoError(t, res.Err)
case <-time.After(time.Second * 3):
t.Fatalf("timed out")
}
}
require.Equal(t, 1, sA.counts["GetStats"])
require.Equal(t, 1, sB.counts["GetStats"])
// rpc GetRegionStats(MyRequest) returns (MyResponse) {
// option (psrpc.options).topics = true;
// option (psrpc.options).multi = true;
require.NoError(t, sA.server.RegisterGetRegionStatsTopic("regionA"))
require.NoError(t, sA.server.RegisterGetRegionStatsTopic("regionB"))
require.NoError(t, sA.server.DeregisterGetRegionStatsTopic("regionB"))
require.NoError(t, sB.server.RegisterGetRegionStatsTopic("regionB"))
time.Sleep(time.Millisecond * 100)
respChan, err = cB.GetRegionStats(ctx, "regionB", req)
require.NoError(t, err)
select {
case res := <-respChan:
require.NotNil(t, res)
require.NoError(t, res.Err)
case <-time.After(time.Second):
t.Fatalf("timed out")
}
require.Equal(t, 0, sA.counts["GetRegionStats"])
require.Equal(t, 1, sB.counts["GetRegionStats"])
// rpc ProcessUpdate(Ignored) returns (MyUpdate) {
// option (psrpc.options).subscription = true;
subA, err := cA.SubscribeProcessUpdate(ctx)
require.NoError(t, err)
subB, err := cB.SubscribeProcessUpdate(ctx)
require.NoError(t, err)
time.Sleep(time.Millisecond * 100)
require.NoError(t, sA.server.PublishProcessUpdate(ctx, update))
requireOne(t, subA, subB)
require.NoError(t, subA.Close())
require.NoError(t, subB.Close())
// rpc UpdateRegionState(Ignored) returns (MyUpdate) {
// option (psrpc.options).subscription = true;
// option (psrpc.options).topics = true;
// option (psrpc.options).multi = true;
subA, err = cA.SubscribeUpdateRegionState(ctx, "regionA")
require.NoError(t, err)
subB, err = cB.SubscribeUpdateRegionState(ctx, "regionA")
require.NoError(t, err)
time.Sleep(time.Millisecond * 100)
require.NoError(t, sB.server.PublishUpdateRegionState(ctx, "regionA", update))
requireTwo(t, subA, subB)
require.NoError(t, subA.Close())
require.NoError(t, subB.Close())
}
func requireOne(t *testing.T, subA, subB psrpc.Subscription[*my_service.MyUpdate]) {
for i := 0; i < 2; i++ {
select {
case <-subA.Channel():
if i == 0 {
continue
}
case <-subB.Channel():
if i == 0 {
continue
}
case <-time.After(time.Second):
if i == 1 {
continue
}
}
t.Fatalf("%d responses received", i*2)
}
}
func requireTwo(t *testing.T, subA, subB psrpc.Subscription[*my_service.MyUpdate]) {
for i := 0; i < 2; i++ {
select {
case <-subA.Channel():
case <-subB.Channel():
case <-time.After(time.Second):
t.Fatalf("timed out")
}
}
}
func createServer(t *testing.T, bus psrpc.MessageBus) *MyService {
svc := &MyService{
counts: make(map[string]int),
}
server, err := my_service.NewMyServiceServer(newID(), svc, bus)
require.NoError(t, err)
svc.server = server
return svc
}
func createClient(t *testing.T, bus psrpc.MessageBus) my_service.MyServiceClient {
client, err := my_service.NewMyServiceClient(newID(), bus)
require.NoError(t, err)
return client
}
type MyService struct {
sync.Mutex
server my_service.MyServiceServer
counts map[string]int
}
func (s *MyService) NormalRPC(ctx context.Context, req *my_service.MyRequest) (*my_service.MyResponse, error) {
s.Lock()
s.counts["NormalRPC"]++
s.Unlock()
return &my_service.MyResponse{}, nil
}
func (s *MyService) IntensiveRPC(ctx context.Context, req *my_service.MyRequest) (*my_service.MyResponse, error) {
s.Lock()
s.counts["IntensiveRPC"]++
s.Unlock()
return &my_service.MyResponse{}, nil
}
func (s *MyService) IntensiveRPCAffinity(req *my_service.MyRequest) float32 {
s.Lock()
s.counts["IntensiveRPCAffinity"]++
s.Unlock()
return rand.Float32()
}
func (s *MyService) GetStats(ctx context.Context, req *my_service.MyRequest) (*my_service.MyResponse, error) {
s.Lock()
s.counts["GetStats"]++
s.Unlock()
return &my_service.MyResponse{}, nil
}
func (s *MyService) GetRegionStats(ctx context.Context, req *my_service.MyRequest) (*my_service.MyResponse, error) {
s.Lock()
s.counts["GetRegionStats"]++
s.Unlock()
return &my_service.MyResponse{}, nil
}
func newID() string {
return shortuuid.New()[:12]
}
@@ -0,0 +1,20 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package service_method_same_name
import "testing"
func TestCompilation(t *testing.T) {
// Test passes if this package compiles
}
@@ -0,0 +1,16 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package service_method_same_name
//go:generate protoc --go_out=paths=source_relative:. --psrpc_out=paths=source_relative:. service_method_same_name.proto
@@ -0,0 +1,136 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: service_method_same_name.proto
package service_method_same_name
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 Msg struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Msg) Reset() {
*x = Msg{}
if protoimpl.UnsafeEnabled {
mi := &file_service_method_same_name_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Msg) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Msg) ProtoMessage() {}
func (x *Msg) ProtoReflect() protoreflect.Message {
mi := &file_service_method_same_name_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 Msg.ProtoReflect.Descriptor instead.
func (*Msg) Descriptor() ([]byte, []int) {
return file_service_method_same_name_proto_rawDescGZIP(), []int{0}
}
var File_service_method_same_name_proto protoreflect.FileDescriptor
var file_service_method_same_name_proto_rawDesc = []byte{
0x0a, 0x1e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,
0x5f, 0x73, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x22, 0x05, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x32, 0x1c, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12,
0x14, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x04, 0x2e, 0x4d, 0x73, 0x67, 0x1a, 0x04, 0x2e,
0x4d, 0x73, 0x67, 0x22, 0x00, 0x42, 0x1b, 0x5a, 0x19, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x73, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x61,
0x6d, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_service_method_same_name_proto_rawDescOnce sync.Once
file_service_method_same_name_proto_rawDescData = file_service_method_same_name_proto_rawDesc
)
func file_service_method_same_name_proto_rawDescGZIP() []byte {
file_service_method_same_name_proto_rawDescOnce.Do(func() {
file_service_method_same_name_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_method_same_name_proto_rawDescData)
})
return file_service_method_same_name_proto_rawDescData
}
var file_service_method_same_name_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_service_method_same_name_proto_goTypes = []interface{}{
(*Msg)(nil), // 0: Msg
}
var file_service_method_same_name_proto_depIdxs = []int32{
0, // 0: Echo.Echo:input_type -> Msg
0, // 1: Echo.Echo:output_type -> Msg
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_service_method_same_name_proto_init() }
func file_service_method_same_name_proto_init() {
if File_service_method_same_name_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_service_method_same_name_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Msg); 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_service_method_same_name_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_service_method_same_name_proto_goTypes,
DependencyIndexes: file_service_method_same_name_proto_depIdxs,
MessageInfos: file_service_method_same_name_proto_msgTypes,
}.Build()
File_service_method_same_name_proto = out.File
file_service_method_same_name_proto_rawDesc = nil
file_service_method_same_name_proto_goTypes = nil
file_service_method_same_name_proto_depIdxs = nil
}
@@ -0,0 +1,10 @@
syntax = "proto3";
// Test to make sure that a method with the same name as its service doesn't break.
option go_package = "/service_method_same_name";
message Msg {}
service Echo {
rpc Echo(Msg) returns (Msg) {}
}
@@ -0,0 +1,93 @@
// Code generated by protoc-gen-psrpc v0.0.1, DO NOT EDIT.
// source: service_method_same_name.proto
package service_method_same_name
import context "context"
import psrpc "github.com/livekit/psrpc"
// =====================
// Echo Client Interface
// =====================
type EchoClient interface {
Echo(context.Context, *Msg, ...psrpc.RequestOpt) (*Msg, error)
}
// =========================
// Echo ServerImpl Interface
// =========================
type EchoServerImpl interface {
Echo(context.Context, *Msg) (*Msg, error)
}
// =====================
// Echo Server Interface
// =====================
type EchoServer interface {
}
// ===========
// Echo Client
// ===========
type echoClient struct {
client psrpc.RPCClient
}
// NewEchoClient creates a psrpc client that implements the EchoClient interface.
func NewEchoClient(clientID string, bus psrpc.MessageBus, opts ...psrpc.ClientOpt) (EchoClient, error) {
rpcClient, err := psrpc.NewRPCClient("Echo", clientID, bus, opts...)
if err != nil {
return nil, err
}
return &echoClient{
client: rpcClient,
}, nil
}
func (c *echoClient) Echo(ctx context.Context, req *Msg, opts ...psrpc.RequestOpt) (*Msg, error) {
return psrpc.RequestTopicSingle[*Msg](ctx, c.client, "Echo", "", req, opts...)
}
// ===========
// Echo Server
// ===========
type echoServer struct {
svc EchoServerImpl
rpc psrpc.RPCServer
}
// NewEchoServer builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewEchoServer(serverID string, svc EchoServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOpt) (EchoServer, error) {
rpcServer := psrpc.NewRPCServer("Echo", serverID, bus, opts...)
var err error
err = rpcServer.RegisterHandler(psrpc.NewHandler("Echo", svc.Echo))
if err != nil {
rpcServer.Close()
return nil, err
}
return &echoServer{
svc: svc,
rpc: rpcServer,
}, nil
}
var psrpcFileDescriptor0 = []byte{
// 97 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2b, 0x4e, 0x2d, 0x2a,
0xcb, 0x4c, 0x4e, 0x8d, 0xcf, 0x4d, 0x2d, 0xc9, 0xc8, 0x4f, 0x89, 0x2f, 0x4e, 0xcc, 0x4d, 0x8d,
0xcf, 0x4b, 0xcc, 0x4d, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x62, 0xe5, 0x62, 0xf6, 0x2d,
0x4e, 0x37, 0x92, 0xe1, 0x62, 0x71, 0x4d, 0xce, 0xc8, 0x17, 0x12, 0x81, 0xd2, 0x2c, 0x7a, 0xbe,
0xc5, 0xe9, 0x52, 0x60, 0x52, 0x89, 0xc1, 0x49, 0x3a, 0x4a, 0x52, 0x1f, 0x97, 0x39, 0x49, 0x6c,
0x60, 0x83, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x97, 0x74, 0x2e, 0x74, 0x6a, 0x00, 0x00,
0x00,
}
@@ -0,0 +1,20 @@
// Copyright 2019 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package snake_case_names
import "testing"
func TestCompilation(t *testing.T) {
// Test passes if this package compiles
}
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2019 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package snake_case_names
//go:generate protoc --go_out=paths=source_relative:. --psrpc_out=paths=source_relative:. snake_case_names.proto
@@ -0,0 +1,292 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: snake_case_names.proto
// Test that protoc-gen-psrpc follows the same behavior as protoc-gen-go
// for converting RPCs and message names from snake case to camel case.
package snake_case_names
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 MakeHatArgsV1 struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *MakeHatArgsV1) Reset() {
*x = MakeHatArgsV1{}
if protoimpl.UnsafeEnabled {
mi := &file_snake_case_names_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MakeHatArgsV1) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MakeHatArgsV1) ProtoMessage() {}
func (x *MakeHatArgsV1) ProtoReflect() protoreflect.Message {
mi := &file_snake_case_names_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 MakeHatArgsV1.ProtoReflect.Descriptor instead.
func (*MakeHatArgsV1) Descriptor() ([]byte, []int) {
return file_snake_case_names_proto_rawDescGZIP(), []int{0}
}
type MakeHatArgsV1_HatV1 struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Size int32 `protobuf:"varint,1,opt,name=size,proto3" json:"size,omitempty"`
Color string `protobuf:"bytes,2,opt,name=color,proto3" json:"color,omitempty"`
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
}
func (x *MakeHatArgsV1_HatV1) Reset() {
*x = MakeHatArgsV1_HatV1{}
if protoimpl.UnsafeEnabled {
mi := &file_snake_case_names_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MakeHatArgsV1_HatV1) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MakeHatArgsV1_HatV1) ProtoMessage() {}
func (x *MakeHatArgsV1_HatV1) ProtoReflect() protoreflect.Message {
mi := &file_snake_case_names_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 MakeHatArgsV1_HatV1.ProtoReflect.Descriptor instead.
func (*MakeHatArgsV1_HatV1) Descriptor() ([]byte, []int) {
return file_snake_case_names_proto_rawDescGZIP(), []int{0, 0}
}
func (x *MakeHatArgsV1_HatV1) GetSize() int32 {
if x != nil {
return x.Size
}
return 0
}
func (x *MakeHatArgsV1_HatV1) GetColor() string {
if x != nil {
return x.Color
}
return ""
}
func (x *MakeHatArgsV1_HatV1) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type MakeHatArgsV1_SizeV1 struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Inches int32 `protobuf:"varint,1,opt,name=inches,proto3" json:"inches,omitempty"`
}
func (x *MakeHatArgsV1_SizeV1) Reset() {
*x = MakeHatArgsV1_SizeV1{}
if protoimpl.UnsafeEnabled {
mi := &file_snake_case_names_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MakeHatArgsV1_SizeV1) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MakeHatArgsV1_SizeV1) ProtoMessage() {}
func (x *MakeHatArgsV1_SizeV1) ProtoReflect() protoreflect.Message {
mi := &file_snake_case_names_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 MakeHatArgsV1_SizeV1.ProtoReflect.Descriptor instead.
func (*MakeHatArgsV1_SizeV1) Descriptor() ([]byte, []int) {
return file_snake_case_names_proto_rawDescGZIP(), []int{0, 1}
}
func (x *MakeHatArgsV1_SizeV1) GetInches() int32 {
if x != nil {
return x.Inches
}
return 0
}
var File_snake_case_names_proto protoreflect.FileDescriptor
var file_snake_case_names_proto_rawDesc = []byte{
0x0a, 0x16, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d,
0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x24, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2e,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x73, 0x6e,
0x61, 0x6b, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x7b,
0x0a, 0x0e, 0x4d, 0x61, 0x6b, 0x65, 0x48, 0x61, 0x74, 0x41, 0x72, 0x67, 0x73, 0x5f, 0x76, 0x31,
0x1a, 0x46, 0x0a, 0x06, 0x48, 0x61, 0x74, 0x5f, 0x76, 0x31, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69,
0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x14,
0x0a, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63,
0x6f, 0x6c, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x1a, 0x21, 0x0a, 0x07, 0x53, 0x69, 0x7a, 0x65,
0x5f, 0x76, 0x31, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20,
0x01, 0x28, 0x05, 0x52, 0x06, 0x69, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x32, 0x9a, 0x01, 0x0a, 0x0e,
0x48, 0x61, 0x62, 0x65, 0x72, 0x64, 0x61, 0x73, 0x68, 0x65, 0x72, 0x5f, 0x76, 0x31, 0x12, 0x87,
0x01, 0x0a, 0x0a, 0x4d, 0x61, 0x6b, 0x65, 0x48, 0x61, 0x74, 0x5f, 0x76, 0x31, 0x12, 0x3c, 0x2e,
0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74,
0x65, 0x73, 0x74, 0x2e, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x5f, 0x6e,
0x61, 0x6d, 0x65, 0x73, 0x2e, 0x4d, 0x61, 0x6b, 0x65, 0x48, 0x61, 0x74, 0x41, 0x72, 0x67, 0x73,
0x5f, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x7a, 0x65, 0x5f, 0x76, 0x31, 0x1a, 0x3b, 0x2e, 0x70, 0x73,
0x72, 0x70, 0x63, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x65, 0x73,
0x74, 0x2e, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d,
0x65, 0x73, 0x2e, 0x4d, 0x61, 0x6b, 0x65, 0x48, 0x61, 0x74, 0x41, 0x72, 0x67, 0x73, 0x5f, 0x76,
0x31, 0x2e, 0x48, 0x61, 0x74, 0x5f, 0x76, 0x31, 0x42, 0x14, 0x5a, 0x12, 0x2f, 0x3b, 0x73, 0x6e,
0x61, 0x6b, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_snake_case_names_proto_rawDescOnce sync.Once
file_snake_case_names_proto_rawDescData = file_snake_case_names_proto_rawDesc
)
func file_snake_case_names_proto_rawDescGZIP() []byte {
file_snake_case_names_proto_rawDescOnce.Do(func() {
file_snake_case_names_proto_rawDescData = protoimpl.X.CompressGZIP(file_snake_case_names_proto_rawDescData)
})
return file_snake_case_names_proto_rawDescData
}
var file_snake_case_names_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_snake_case_names_proto_goTypes = []interface{}{
(*MakeHatArgsV1)(nil), // 0: psrpc.internal.test.snake_case_names.MakeHatArgs_v1
(*MakeHatArgsV1_HatV1)(nil), // 1: psrpc.internal.test.snake_case_names.MakeHatArgs_v1.Hat_v1
(*MakeHatArgsV1_SizeV1)(nil), // 2: psrpc.internal.test.snake_case_names.MakeHatArgs_v1.Size_v1
}
var file_snake_case_names_proto_depIdxs = []int32{
2, // 0: psrpc.internal.test.snake_case_names.Haberdasher_v1.MakeHat_v1:input_type -> psrpc.internal.test.snake_case_names.MakeHatArgs_v1.Size_v1
1, // 1: psrpc.internal.test.snake_case_names.Haberdasher_v1.MakeHat_v1:output_type -> psrpc.internal.test.snake_case_names.MakeHatArgs_v1.Hat_v1
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_snake_case_names_proto_init() }
func file_snake_case_names_proto_init() {
if File_snake_case_names_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_snake_case_names_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MakeHatArgsV1); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_snake_case_names_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MakeHatArgsV1_HatV1); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_snake_case_names_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MakeHatArgsV1_SizeV1); 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_snake_case_names_proto_rawDesc,
NumEnums: 0,
NumMessages: 3,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_snake_case_names_proto_goTypes,
DependencyIndexes: file_snake_case_names_proto_depIdxs,
MessageInfos: file_snake_case_names_proto_msgTypes,
}.Build()
File_snake_case_names_proto = out.File
file_snake_case_names_proto_rawDesc = nil
file_snake_case_names_proto_goTypes = nil
file_snake_case_names_proto_depIdxs = nil
}
@@ -0,0 +1,23 @@
syntax = "proto3";
// Test that protoc-gen-psrpc follows the same behavior as protoc-gen-go
// for converting RPCs and message names from snake case to camel case.
package psrpc.internal.test.snake_case_names;
option go_package = "/;snake_case_names";
message MakeHatArgs_v1 {
message Hat_v1 {
int32 size = 1;
string color = 2;
string name = 3;
}
message Size_v1 {
int32 inches = 1;
}
}
// A Haberdasher makes hats for clients.
service Haberdasher_v1 {
rpc MakeHat_v1 (MakeHatArgs_v1.Size_v1) returns (MakeHatArgs_v1.Hat_v1);
}
@@ -0,0 +1,107 @@
// Code generated by protoc-gen-psrpc v0.0.1, DO NOT EDIT.
// source: snake_case_names.proto
// Test that protoc-gen-psrpc follows the same behavior as protoc-gen-go
// for converting RPCs and message names from snake case to camel case.
package snake_case_names
import context "context"
import psrpc "github.com/livekit/psrpc"
// ==============================
// HaberdasherV1 Client Interface
// ==============================
// A Haberdasher makes hats for clients.
type HaberdasherV1Client interface {
MakeHatV1(context.Context, *MakeHatArgsV1_SizeV1, ...psrpc.RequestOpt) (*MakeHatArgsV1_HatV1, error)
}
// ==================================
// HaberdasherV1 ServerImpl Interface
// ==================================
// A Haberdasher makes hats for clients.
type HaberdasherV1ServerImpl interface {
MakeHatV1(context.Context, *MakeHatArgsV1_SizeV1) (*MakeHatArgsV1_HatV1, error)
}
// ==============================
// HaberdasherV1 Server Interface
// ==============================
// A Haberdasher makes hats for clients.
type HaberdasherV1Server interface {
}
// ====================
// HaberdasherV1 Client
// ====================
type haberdasherV1Client struct {
client psrpc.RPCClient
}
// NewHaberdasherV1Client creates a psrpc client that implements the HaberdasherV1Client interface.
func NewHaberdasherV1Client(clientID string, bus psrpc.MessageBus, opts ...psrpc.ClientOpt) (HaberdasherV1Client, error) {
rpcClient, err := psrpc.NewRPCClient("HaberdasherV1", clientID, bus, opts...)
if err != nil {
return nil, err
}
return &haberdasherV1Client{
client: rpcClient,
}, nil
}
func (c *haberdasherV1Client) MakeHatV1(ctx context.Context, req *MakeHatArgsV1_SizeV1, opts ...psrpc.RequestOpt) (*MakeHatArgsV1_HatV1, error) {
return psrpc.RequestTopicSingle[*MakeHatArgsV1_HatV1](ctx, c.client, "MakeHatV1", "", req, opts...)
}
// ====================
// HaberdasherV1 Server
// ====================
type haberdasherV1Server struct {
svc HaberdasherV1ServerImpl
rpc psrpc.RPCServer
}
// NewHaberdasherV1Server builds a RPCServer that can be used to handle
// requests that are routed to the right method in the provided svc implementation.
func NewHaberdasherV1Server(serverID string, svc HaberdasherV1ServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOpt) (HaberdasherV1Server, error) {
rpcServer := psrpc.NewRPCServer("HaberdasherV1", serverID, bus, opts...)
var err error
err = rpcServer.RegisterHandler(psrpc.NewHandler("MakeHatV1", svc.MakeHatV1))
if err != nil {
rpcServer.Close()
return nil, err
}
return &haberdasherV1Server{
svc: svc,
rpc: rpcServer,
}, nil
}
var psrpcFileDescriptor0 = []byte{
// 225 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2b, 0xce, 0x4b, 0xcc,
0x4e, 0x8d, 0x4f, 0x4e, 0x2c, 0x4e, 0x8d, 0xcf, 0x4b, 0xcc, 0x4d, 0x2d, 0xd6, 0x2b, 0x28, 0xca,
0x2f, 0xc9, 0x17, 0x52, 0x29, 0x28, 0x2e, 0x2a, 0x48, 0xd6, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca,
0x4b, 0xcc, 0xd1, 0x2b, 0x49, 0x2d, 0x2e, 0xd1, 0x43, 0x57, 0xab, 0x54, 0xcd, 0xc5, 0xe7, 0x9b,
0x98, 0x9d, 0xea, 0x91, 0x58, 0xe2, 0x58, 0x94, 0x5e, 0x1c, 0x5f, 0x66, 0x28, 0xe5, 0xc6, 0xc5,
0xe6, 0x91, 0x58, 0x12, 0x5f, 0x66, 0x28, 0x24, 0xc4, 0xc5, 0x52, 0x9c, 0x59, 0x95, 0x2a, 0xc1,
0xa8, 0xc0, 0xa8, 0xc1, 0x1a, 0x04, 0x66, 0x0b, 0x89, 0x70, 0xb1, 0x26, 0xe7, 0xe7, 0xe4, 0x17,
0x49, 0x30, 0x29, 0x30, 0x6a, 0x70, 0x06, 0x41, 0x38, 0x20, 0x95, 0x20, 0xe3, 0x24, 0x98, 0xc1,
0x82, 0x60, 0xb6, 0x94, 0x22, 0x17, 0x7b, 0x70, 0x66, 0x55, 0x2a, 0xc8, 0x20, 0x31, 0x2e, 0xb6,
0xcc, 0xbc, 0xe4, 0x8c, 0xd4, 0x62, 0xa8, 0x51, 0x50, 0x9e, 0xd1, 0x2c, 0x46, 0x2e, 0x3e, 0x8f,
0xc4, 0xa4, 0xd4, 0xa2, 0x94, 0xc4, 0xe2, 0x8c, 0xd4, 0x22, 0x90, 0xd2, 0x76, 0x46, 0x2e, 0x2e,
0xa8, 0x83, 0x40, 0x5c, 0x1b, 0x3d, 0x62, 0x7c, 0xa1, 0x87, 0xea, 0x05, 0x3d, 0xa8, 0xbd, 0x52,
0xd6, 0x64, 0xe9, 0x86, 0x58, 0xed, 0x24, 0x12, 0x25, 0xa4, 0x6f, 0x8d, 0xae, 0x36, 0x89, 0x0d,
0x1c, 0xb8, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9b, 0x4f, 0x4c, 0xcd, 0x76, 0x01, 0x00,
0x00,
}
+55 -11
View File
@@ -14,13 +14,12 @@ import (
var Default = Test
// regenerate protobuf
func Install() error {
return mageutil.Run(context.Background(), "go install ./protoc-gen-psrpc")
}
func Proto() error {
fmt.Println("generating protobuf")
target := "internal"
if err := os.MkdirAll(target, 0755); err != nil {
return err
}
protoc, err := mageutil.GetToolPath("protoc")
if err != nil {
@@ -32,18 +31,63 @@ func Proto() error {
}
cmd := exec.Command(protoc,
"--go_out", target,
"--go-grpc_out", target,
"--go_out", "internal",
"--go_opt=paths=source_relative",
"--go-grpc_opt=paths=source_relative",
"--plugin=go="+protocGoPath,
"-I=.",
"-I=./internal",
"internal.proto",
)
mageutil.ConnectStd(cmd)
return cmd.Run()
if err = cmd.Run(); err != nil {
return err
}
cmd = exec.Command(protoc,
"--go_out", "protoc-gen-psrpc/options",
"--go_opt=paths=source_relative",
"--plugin=go="+protocGoPath,
"-I=./protoc-gen-psrpc/options",
"options.proto",
)
mageutil.ConnectStd(cmd)
if err = cmd.Run(); err != nil {
return err
}
return nil
}
func Generate() error {
ctx := context.Background()
err := mageutil.Run(ctx, "go install ./protoc-gen-psrpc")
if err != nil {
return err
}
base := "./internal/test"
dirs, err := os.ReadDir(base)
if err != nil {
return err
}
for _, dir := range dirs {
if dir.IsDir() {
err = mageutil.RunDir(ctx, fmt.Sprintf("%s/%s", base, dir.Name()), "go generate .")
if err != nil {
return err
}
}
}
return nil
}
func Test() error {
return mageutil.Run(context.Background(), "go test -v ./...")
return mageutil.Run(context.Background(), "go test -v .")
}
func TestAll() error {
if err := Generate(); err != nil {
return err
}
return mageutil.Run(context.Background(), "go test ./...")
}
+84
View File
@@ -0,0 +1,84 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package main
import (
"fmt"
"strings"
)
type commandLineParams struct {
importMap map[string]string // Mapping from .proto file name to import path.
paths string // paths flag, used to control file output directory.
module string // module flag, Go import path prefix that is removed from the output filename.
importPrefix string // prefix added to imported package file names.
}
// parseCommandLineParams breaks the comma-separated list of key=value pairs
// in the parameter (a member of the request protobuf) into a key/value map.
// It then sets command line parameter mappings defined by those entries.
func parseCommandLineParams(parameter string) (*commandLineParams, error) {
ps := make(map[string]string)
for _, p := range strings.Split(parameter, ",") {
if p == "" {
continue
}
i := strings.Index(p, "=")
if i < 0 {
return nil, fmt.Errorf("invalid parameter %q: expected format of parameter to be k=v", p)
}
k := p[0:i]
v := p[i+1:]
if v == "" {
return nil, fmt.Errorf("invalid parameter %q: expected format of parameter to be k=v", k)
}
ps[k] = v
}
clp := &commandLineParams{
importMap: make(map[string]string),
}
for k, v := range ps {
switch {
// Support import map 'M' prefix: https://developers.google.com/protocol-buffers/docs/reference/go-generated
case len(k) > 0 && k[0] == 'M':
clp.importMap[k[1:]] = v // 1 is the length of 'M'.
case len(k) > 0 && strings.HasPrefix(k, "go_import_mapping@"): // twirp specific version of M parameters
clp.importMap[k[18:]] = v // 18 is the length of 'go_import_mapping@'.
case k == "paths":
switch v {
case "import":
// this is the default behavior; the output file is placed in a directory named after the option go_package
case "source_relative":
// the directory prefix on the option go_package is removed from the output filename (only the last part is used)
clp.paths = "source_relative"
default:
return nil, fmt.Errorf("invalid command line flag %s=%s", k, v)
}
// If the module={PREFIX} flag is specified, the prefix is removed from the option go_package on the output filename
case k == "module":
clp.module = v
// Deprecated, but may still be useful when working with old versions of protoc-gen-go
case k == "import_prefix":
clp.importPrefix = v
default:
return nil, fmt.Errorf("invalid command line flag %s=%s", k, v)
}
}
return clp, nil
}
+160
View File
@@ -0,0 +1,160 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package main
import (
"errors"
"reflect"
"testing"
)
func TestParseCommandLineParams(t *testing.T) {
tests := []struct {
name string
parameter string
params *commandLineParams
err error
}{
{
"no parameters",
"",
&commandLineParams{
importMap: map[string]string{},
},
nil,
},
{
"unknown parameter",
"kkk=vvv",
nil,
errors.New(`invalid command line flag kkk=vvv`),
},
{
"empty parameter value - no equals sign",
"import_prefix",
nil,
errors.New(`invalid parameter "import_prefix": expected format of parameter to be k=v`),
},
{
"empty parameter value - no value",
"import_prefix=",
nil,
errors.New(`invalid parameter "import_prefix": expected format of parameter to be k=v`),
},
{
"import_prefix parameter",
"import_prefix=github.com/example/repo",
&commandLineParams{
importMap: map[string]string{},
importPrefix: "github.com/example/repo",
},
nil,
},
{
"single import parameter starting with 'M'",
"Mrpcutil/empty.proto=github.com/example/rpcutil",
&commandLineParams{
importMap: map[string]string{
"rpcutil/empty.proto": "github.com/example/rpcutil",
},
},
nil,
},
{
"multiple import parameters starting with 'M'",
"Mrpcutil/empty.proto=github.com/example/rpcutil,Mrpc/haberdasher/service.proto=github.com/example/rpc/haberdasher",
&commandLineParams{
importMap: map[string]string{
"rpcutil/empty.proto": "github.com/example/rpcutil",
"rpc/haberdasher/service.proto": "github.com/example/rpc/haberdasher",
},
},
nil,
},
{
"single import parameter starting with 'go_import_mapping@'",
"go_import_mapping@rpcutil/empty.proto=github.com/example/rpcutil",
&commandLineParams{
importMap: map[string]string{
"rpcutil/empty.proto": "github.com/example/rpcutil",
},
},
nil,
},
{
"multiple import parameters starting with 'go_import_mapping@'",
"go_import_mapping@rpcutil/empty.proto=github.com/example/rpcutil,go_import_mapping@rpc/haberdasher/service.proto=github.com/example/rpc/haberdasher",
&commandLineParams{
importMap: map[string]string{
"rpcutil/empty.proto": "github.com/example/rpcutil",
"rpc/haberdasher/service.proto": "github.com/example/rpc/haberdasher",
},
},
nil,
},
{
"paths import",
"paths=import",
&commandLineParams{
importMap: map[string]string{},
},
nil,
},
{
"paths source_relative",
"paths=source_relative",
&commandLineParams{
importMap: map[string]string{},
paths: "source_relative",
},
nil,
},
{
"paths invalidstuff",
"paths=invalidstuff",
nil,
errors.New(`invalid command line flag paths=invalidstuff`),
},
{
"module parameter",
"module=foo/bar/fizz",
&commandLineParams{
importMap: map[string]string{},
module: "foo/bar/fizz",
},
nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
params, err := parseCommandLineParams(tt.parameter)
switch {
case err != nil:
if tt.err == nil {
t.Fatal(err)
}
if err.Error() != tt.err.Error() {
t.Errorf("got error = %v, want %v", err, tt.err)
}
case err == nil:
if tt.err != nil {
t.Errorf("got error = %v, want %v", err, tt.err)
}
}
if !reflect.DeepEqual(params, tt.params) {
t.Errorf("got params = %+v, want %+v", params, tt.params)
}
})
}
}
+753
View File
@@ -0,0 +1,753 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package main
import (
"bufio"
"bytes"
"compress/gzip"
"fmt"
"go/parser"
"go/printer"
"go/token"
"path"
"sort"
"strconv"
"strings"
"google.golang.org/protobuf/proto"
descriptor "google.golang.org/protobuf/types/descriptorpb"
plugin "google.golang.org/protobuf/types/pluginpb"
"github.com/pkg/errors"
"github.com/livekit/psrpc/internal/gen"
"github.com/livekit/psrpc/internal/gen/stringutils"
"github.com/livekit/psrpc/internal/gen/typemap"
"github.com/livekit/psrpc/protoc-gen-psrpc/options"
)
type psrpc struct {
filesHandled int
reg *typemap.Registry
// Map to record whether we've built each package
pkgs map[string]string
pkgNamesInUse map[string]bool
importPrefix string // String to prefix to imported package file names.
importMap map[string]string // Mapping from .proto file name to import path.
// Package output:
sourceRelativePaths bool // instruction on where to write output files
modulePrefix string
// Package naming:
genPkgName string // Name of the package that we're generating
fileToGoPackageName map[*descriptor.FileDescriptorProto]string
// List of files that were inputs to the generator. We need to hold this in
// the struct, so we can write a header for the file that lists its inputs.
genFiles []*descriptor.FileDescriptorProto
// Output buffer that holds the bytes we want to write out for a single file.
// Gets reset after working on a file.
output *bytes.Buffer
}
func newGenerator() *psrpc {
t := &psrpc{
pkgs: make(map[string]string),
pkgNamesInUse: make(map[string]bool),
importMap: make(map[string]string),
fileToGoPackageName: make(map[*descriptor.FileDescriptorProto]string),
output: bytes.NewBuffer(nil),
}
return t
}
func (t *psrpc) Generate(in *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse {
params, err := parseCommandLineParams(in.GetParameter())
if err != nil {
gen.Fail("could not parse parameters passed to --psrpc_out", err.Error())
}
t.importPrefix = params.importPrefix
t.importMap = params.importMap
t.sourceRelativePaths = params.paths == "source_relative"
t.modulePrefix = params.module
t.genFiles = gen.FilesToGenerate(in)
// Collect information on types.
t.reg = typemap.New(in.ProtoFile)
// Register names of packages that we import.
t.registerPackageName("context")
t.registerPackageName("psrpc")
// Time to figure out package names of objects defined in protobuf. First,
// we'll figure out the name for the package we're generating.
genPkgName, err := deduceGenPkgName(t.genFiles)
if err != nil {
gen.Fail(err.Error())
}
t.genPkgName = genPkgName
// We also need to figure out the full import path of the package we're
// generating. It's possible to import proto definitions from different .proto
// files which will be generated into the same Go package, which we need to
// detect (and can only detect if files use fully-specified go_package
// options).
genPkgImportPath, _, _ := goPackageOption(t.genFiles[0])
// Next, we need to pick names for all the files that are dependencies.
for _, f := range in.ProtoFile {
// Is this is a file we are generating? If yes, it gets the shared package name.
if fileDescSliceContains(t.genFiles, f) {
t.fileToGoPackageName[f] = t.genPkgName
continue
}
// Is this is an imported .proto file which has the same fully-specified
// go_package as the targeted file for generation? If yes, it gets the
// shared package name too.
if genPkgImportPath != "" {
importPath, _, _ := goPackageOption(f)
if importPath == genPkgImportPath {
t.fileToGoPackageName[f] = t.genPkgName
continue
}
}
// This is a dependency from a different go_package. Use its package name.
name := f.GetPackage()
if name == "" {
name = stringutils.BaseName(f.GetName())
}
name = stringutils.CleanIdentifier(name)
alias := t.registerPackageName(name)
t.fileToGoPackageName[f] = alias
}
// Showtime! Generate the response.
resp := new(plugin.CodeGeneratorResponse)
resp.SupportedFeatures = proto.Uint64(uint64(plugin.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL))
for _, f := range t.genFiles {
respFile := t.generate(f)
if respFile != nil {
resp.File = append(resp.File, respFile)
}
}
return resp
}
func (t *psrpc) registerPackageName(name string) (alias string) {
alias = name
i := 1
for t.pkgNamesInUse[alias] {
alias = name + strconv.Itoa(i)
i++
}
t.pkgNamesInUse[alias] = true
t.pkgs[name] = alias
return alias
}
// deduceGenPkgName figures out the go package name to use for generated code.
// Will try to use the explicit go_package setting in a file (if set, must be
// consistent in all files). If no files have go_package set, then use the
// protobuf package name (must be consistent in all files)
func deduceGenPkgName(genFiles []*descriptor.FileDescriptorProto) (string, error) {
var genPkgName string
for _, f := range genFiles {
name, explicit := goPackageName(f)
if explicit {
name = stringutils.CleanIdentifier(name)
if genPkgName != "" && genPkgName != name {
// Make sure they're all set consistently.
return "", errors.Errorf("files have conflicting go_package settings, must be the same: %q and %q", genPkgName, name)
}
genPkgName = name
}
}
if genPkgName != "" {
return genPkgName, nil
}
// If there is no explicit setting, then check the implicit package name
// (derived from the protobuf package name) of the files and make sure it's
// consistent.
for _, f := range genFiles {
name, _ := goPackageName(f)
name = stringutils.CleanIdentifier(name)
if genPkgName != "" && genPkgName != name {
return "", errors.Errorf("files have conflicting package names, must be the same or overridden with go_package: %q and %q", genPkgName, name)
}
genPkgName = name
}
// All the files have the same name, so we're good.
return genPkgName, nil
}
func (t *psrpc) generate(file *descriptor.FileDescriptorProto) *plugin.CodeGeneratorResponse_File {
resp := new(plugin.CodeGeneratorResponse_File)
if len(file.Service) == 0 {
return nil
}
t.generateFileHeader(file)
t.generateImports(file)
// For each service, generate client stubs and server
for _, service := range file.Service {
t.generateService(file, service)
}
t.generateFileDescriptor(file)
resp.Name = proto.String(t.goFileName(file))
resp.Content = proto.String(t.formattedOutput())
t.output.Reset()
t.filesHandled++
return resp
}
func (t *psrpc) generateFileHeader(file *descriptor.FileDescriptorProto) {
t.P("// Code generated by protoc-gen-psrpc ", gen.Version, ", DO NOT EDIT.")
t.P("// source: ", file.GetName())
t.P()
comment, err := t.reg.FileComments(file)
if err == nil && comment.Leading != "" {
for _, line := range strings.Split(comment.Leading, "\n") {
if line != "" {
t.P("// " + strings.TrimPrefix(line, " "))
}
}
t.P()
}
t.P(`package `, t.genPkgName)
t.P()
}
func (t *psrpc) generateImports(file *descriptor.FileDescriptorProto) {
if len(file.Service) == 0 {
return
}
// stdlib imports
for _, service := range file.Service {
if len(service.Method) > 0 {
t.P(`import `, t.pkgs["context"], ` "context"`)
t.P()
break
}
}
// dependency imports
t.P(`import `, t.pkgs["psrpc"], ` "github.com/livekit/psrpc"`)
// It's legal to import a message and use it as an input or output for a
// method. Make sure to import the package of any such message. First, dedupe
// them.
deps := make(map[string]string) // Map of package name to quoted import path.
ourImportPath := path.Dir(t.goFileName(file))
for _, s := range file.Service {
for _, m := range s.Method {
defs := []*typemap.MessageDefinition{
t.reg.MethodInputDefinition(m),
t.reg.MethodOutputDefinition(m),
}
for _, def := range defs {
importPath, _ := parseGoPackageOption(def.File.GetOptions().GetGoPackage())
if importPath == "" { // no option go_package
importPath := path.Dir(t.goFileName(def.File)) // use the dirname of the Go filename as import path
if importPath == ourImportPath {
continue
}
}
if substitution, ok := t.importMap[def.File.GetName()]; ok {
importPath = substitution
}
importPath = t.importPrefix + importPath
pkg := t.goPackageName(def.File)
if pkg != t.genPkgName {
deps[pkg] = strconv.Quote(importPath)
}
}
}
}
pkgs := make([]string, 0, len(deps))
for pkg := range deps {
pkgs = append(pkgs, pkg)
}
sort.Strings(pkgs)
for _, pkg := range pkgs {
t.P(`import `, pkg, ` `, deps[pkg])
}
if len(deps) > 0 {
t.P()
}
}
// W forwards to g.gen.P, which prints output.
func (t *psrpc) W(args ...string) {
for _, v := range args {
t.output.WriteString(v)
}
}
// P forwards to g.gen.P, which prints output.
func (t *psrpc) P(args ...string) {
for _, v := range args {
t.output.WriteString(v)
}
t.output.WriteByte('\n')
}
// Big header comments to makes it easier to visually parse a generated file.
func (t *psrpc) sectionComment(sectionTitle string) {
t.P()
t.P(`// `, strings.Repeat("=", len(sectionTitle)))
t.P(`// `, sectionTitle)
t.P(`// `, strings.Repeat("=", len(sectionTitle)))
t.P()
}
const (
client = "Client"
ServerImpl = "ServerImpl"
server = "Server"
)
func (t *psrpc) generateService(file *descriptor.FileDescriptorProto, service *descriptor.ServiceDescriptorProto) {
servName := serviceNameCamelCased(service)
t.sectionComment(servName + ` Client Interface`)
t.generateInterface(file, service, client)
t.sectionComment(servName + ` ServerImpl Interface`)
t.generateInterface(file, service, ServerImpl)
t.sectionComment(servName + ` Server Interface`)
t.generateInterface(file, service, server)
t.sectionComment(servName + ` Client`)
t.generateClient(service)
t.sectionComment(servName + ` Server`)
t.generateServer(service)
}
func (t *psrpc) generateInterface(file *descriptor.FileDescriptorProto, service *descriptor.ServiceDescriptorProto, iface string) {
servName := serviceNameCamelCased(service)
comments, err := t.reg.ServiceComments(file, service)
if err == nil {
t.printComments(comments)
}
t.P(`type `, servName, iface, ` interface {`)
for _, method := range service.Method {
opts := t.getOptions(method)
if (iface == ServerImpl && opts.Subscription) || (iface == server && !opts.Subscription && !opts.Topics) {
continue
}
comments, err = t.reg.MethodComments(file, service, method)
if err == nil {
t.printComments(comments)
}
switch iface {
case client:
t.generateClientSignature(method, opts)
case ServerImpl:
t.generateServerImplSignature(method, opts)
case server:
t.generateServerSignature(method, opts)
}
}
t.P(`}`)
}
func (t *psrpc) generateClientSignature(method *descriptor.MethodDescriptorProto, opts *options.Options) {
methName := methodNameCamelCased(method)
inputType := t.goTypeName(method.GetInputType())
outputType := t.goTypeName(method.GetOutputType())
if opts.Subscription {
t.W(` Subscribe`)
} else {
t.W(` `)
}
t.W(methName, `(`, t.pkgs["context"], `.Context`)
if opts.Topics {
t.W(`, string`)
}
if opts.Subscription {
t.P(`) (`, t.pkgs["psrpc"], `.Subscription[*`, outputType, `], error)`)
} else if opts.Multi {
t.P(`, *`, inputType, `, ...`, t.pkgs["psrpc"], `.RequestOpt) (<-chan *`, t.pkgs["psrpc"], `.Response[*`, outputType, `], error)`)
} else {
t.P(`, *`, inputType, `, ...`, t.pkgs["psrpc"], `.RequestOpt) (*`, outputType, `, error)`)
}
t.P()
}
func (t *psrpc) generateClient(service *descriptor.ServiceDescriptorProto) {
servName := serviceNameCamelCased(service)
structName := unexported(servName) + "Client"
newClientFunc := "New" + servName + "Client"
t.P(`type `, structName, ` struct {`)
t.P(` client `, t.pkgs["psrpc"], `.RPCClient`)
t.P(`}`)
t.P()
t.P(`// `, newClientFunc, ` creates a psrpc client that implements the `, servName, `Client interface.`)
t.P(`func `, newClientFunc, `(clientID string, bus `, t.pkgs["psrpc"], `.MessageBus, opts ...`, t.pkgs["psrpc"], `.ClientOpt) (`, servName, `Client, error) {`)
t.P(` rpcClient, err := `, t.pkgs["psrpc"], `.NewRPCClient("`, servName, `", clientID, bus, opts...)`)
t.P(` if err != nil {`)
t.P(` return nil, err`)
t.P(` }`)
t.P()
t.P(` return &`, structName, `{`)
t.P(` client: rpcClient,`)
t.P(` }, nil`)
t.P(`}`)
t.P()
for _, method := range service.Method {
methName := methodNameCamelCased(method)
inputType := t.goTypeName(method.GetInputType())
outputType := t.goTypeName(method.GetOutputType())
opts := t.getOptions(method)
topicParam := `""`
t.W(`func (c *`, structName)
if opts.Subscription {
t.W(`) Subscribe`)
} else {
t.W(`) `)
}
t.W(methName, `(ctx `, t.pkgs["context"], `.Context`)
if opts.Topics {
topicParam = "topic"
t.W(`, topic string`)
}
if opts.Subscription {
t.P(`) (`, t.pkgs["psrpc"], `.Subscription[*`, outputType, `], error)`, ` {`)
} else {
t.W(`, req *`, inputType, `, opts ...`, t.pkgs["psrpc"], `.RequestOpt`)
if opts.Multi {
t.P(`) (<-chan *`, t.pkgs["psrpc"], `.Response[*`, outputType, `], error)`, ` {`)
} else {
t.P(`) (*`, outputType, `, error)`, ` {`)
}
}
t.W(` return `, t.pkgs["psrpc"])
if opts.Subscription {
if opts.Multi {
t.W(`.SubscribeTopic[*`)
} else {
t.W(`.SubscribeTopicQueue[*`)
}
t.P(outputType, `](ctx, c.client, "`, methName, `", `, topicParam, `)`)
} else {
if opts.Multi {
t.W(`.RequestTopicAll[*`)
} else {
t.W(`.RequestTopicSingle[*`)
}
t.P(outputType, `](ctx, c.client, "`, methName, `", `, topicParam, `, req, opts...)`)
}
t.P(`}`)
t.P()
}
}
func (t *psrpc) generateServerImplSignature(method *descriptor.MethodDescriptorProto, opts *options.Options) {
methName := methodNameCamelCased(method)
inputType := t.goTypeName(method.GetInputType())
outputType := t.goTypeName(method.GetOutputType())
t.P(` `, methName, `(`, t.pkgs["context"], `.Context, *`, inputType, `) (*`, outputType, `, error)`)
if opts.AffinityFunc {
t.P(` `, methName, `Affinity(*`, inputType, `) float32`)
}
t.P()
}
func (t *psrpc) generateServerSignature(method *descriptor.MethodDescriptorProto, opts *options.Options) {
methName := methodNameCamelCased(method)
outputType := t.goTypeName(method.GetOutputType())
if opts.Subscription {
t.W(` Publish`, methName, `(`, t.pkgs["context"], `.Context`)
if opts.Topics {
t.W(`, string`)
}
t.P(`, *`, outputType, `) error`)
t.P()
} else {
t.P(` Register`, methName, `Topic(string) error`)
t.P(` Deregister`, methName, `Topic(string) error`)
t.P()
}
}
func (t *psrpc) generateServer(service *descriptor.ServiceDescriptorProto) {
servName := serviceNameCamelCased(service)
// Server implementation.
servStruct := serviceStruct(service)
t.P(`type `, servStruct, ` struct {`)
t.P(` svc `, servName, `ServerImpl`)
t.P(` rpc `, t.pkgs["psrpc"], `.RPCServer`)
t.P(`}`)
t.P()
// Constructor for server implementation
t.P(`// New`, servName, `Server builds a RPCServer that can be used to handle`)
t.P(`// requests that are routed to the right method in the provided svc implementation.`)
t.P(`func New`, servName, `Server(serverID string, svc `, servName, `ServerImpl, bus `, t.pkgs["psrpc"], `.MessageBus, opts ...`, t.pkgs["psrpc"], `.ServerOpt) (`, servName, `Server, error) {`)
t.P(` rpcServer := `, t.pkgs["psrpc"], `.NewRPCServer("`, servName, `", serverID, bus, opts...)`)
t.P()
errVar := false
for _, method := range service.Method {
opts := t.getOptions(method)
if opts.Subscription || opts.Topics {
continue
}
if !errVar {
t.P(` var err error`)
errVar = true
}
methName := methodNameCamelCased(method)
t.W(` err = rpcServer.RegisterHandler(`, t.pkgs["psrpc"])
if t.getOptions(method).AffinityFunc {
t.P(`.NewHandlerWithAffinity("`, methName, `", svc.`, methName, `, svc.`, methName, `Affinity))`)
} else {
t.P(`.NewHandler("`, methName, `", svc.`, methName, `))`)
}
t.P(` if err != nil {`)
t.P(` rpcServer.Close()`)
t.P(` return nil, err`)
t.P(` }`)
t.P()
}
t.P(` return &`, servStruct, `{`)
t.P(` svc: svc,`)
t.P(` rpc: rpcServer,`)
t.P(` }, nil`)
t.P(`}`)
t.P()
for _, method := range service.Method {
opts := t.getOptions(method)
if !opts.Subscription && !opts.Topics {
continue
}
methName := methodNameCamelCased(method)
outputType := t.goTypeName(method.GetOutputType())
if opts.Subscription {
topicParam := `""`
t.W(`func (s *`, servStruct, `) Publish`, methName, `(ctx `, t.pkgs["context"], `.Context`)
if opts.Topics {
topicParam = `topic`
t.W(`, topic string`)
}
t.P(`, msg *`, outputType, `) error {`)
t.P(` return s.rpc.PublishTopic(ctx, "`, methName, `", `, topicParam, `, msg)`)
t.P(`}`)
t.P()
} else {
t.P(`func (s *`, servStruct, `) Register`, methName, `Topic(topic string) error {`)
t.W(` return s.rpc.RegisterHandler(`, t.pkgs["psrpc"])
if t.getOptions(method).AffinityFunc {
t.P(`.NewTopicHandlerWithAffinity("`, methName, `", topic, s.svc.`, methName, `, s.svc.`, methName, `Affinity))`)
} else {
t.P(`.NewTopicHandler("`, methName, `", topic, s.svc.`, methName, `))`)
}
t.P(`}`)
t.P()
t.P(`func (s *`, servStruct, `) Deregister`, methName, `Topic(topic string) error {`)
t.P(` return s.rpc.DeregisterTopic("`, methName, `", topic)`)
t.P(`}`)
t.P()
}
}
}
func (t *psrpc) getOptions(method *descriptor.MethodDescriptorProto) *options.Options {
if method.Options == nil {
return &options.Options{}
}
if proto.HasExtension(method.Options, options.E_Options) {
ext := proto.GetExtension(method.Options, options.E_Options)
return ext.(*options.Options)
}
return &options.Options{}
}
// serviceMetadataVarName is the variable name used in generated code to refer
// to the compressed bytes of this descriptor. It is not exported, so it is only
// valid inside the generated package.
//
// protoc-gen-go writes its own version of this file, but so does
// protoc-gen-gogo - with a different name! PSRPC aims to be compatible with
// both; the simplest way forward is to write the file descriptor again as
// another variable that we control.
func (t *psrpc) serviceMetadataVarName() string {
return fmt.Sprintf("psrpcFileDescriptor%d", t.filesHandled)
}
func (t *psrpc) generateFileDescriptor(file *descriptor.FileDescriptorProto) {
// Copied straight off of protoc-gen-go, which trims out comments.
pb := proto.Clone(file).(*descriptor.FileDescriptorProto)
pb.SourceCodeInfo = nil
b, err := proto.Marshal(pb)
if err != nil {
gen.Fail(err.Error())
}
var buf bytes.Buffer
w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression)
_, _ = w.Write(b)
_ = w.Close()
b = buf.Bytes()
v := t.serviceMetadataVarName()
t.P()
t.P("var ", v, " = []byte{")
t.P(" // ", fmt.Sprintf("%d", len(b)), " bytes of a gzipped FileDescriptorProto")
for len(b) > 0 {
n := 16
if n > len(b) {
n = len(b)
}
s := ""
for _, c := range b[:n] {
s += fmt.Sprintf("0x%02x,", c)
}
t.P(` `, s)
b = b[n:]
}
t.P("}")
}
func (t *psrpc) printComments(comments typemap.DefinitionComments) bool {
text := strings.TrimSuffix(comments.Leading, "\n")
if len(strings.TrimSpace(text)) == 0 {
return false
}
split := strings.Split(text, "\n")
for _, line := range split {
t.P("// ", strings.TrimPrefix(line, " "))
}
return len(split) > 0
}
// Given a protobuf name for a Message, return the Go name we will use for that
// type, including its package prefix.
func (t *psrpc) goTypeName(protoName string) string {
def := t.reg.MessageDefinition(protoName)
if def == nil {
gen.Fail("could not find message for", protoName)
}
var prefix string
if pkg := t.goPackageName(def.File); pkg != t.genPkgName {
prefix = pkg + "."
}
var name string
for _, parent := range def.Lineage() {
name += stringutils.CamelCase(parent.Descriptor.GetName()) + "_"
}
name += stringutils.CamelCase(def.Descriptor.GetName())
return prefix + name
}
func (t *psrpc) goPackageName(file *descriptor.FileDescriptorProto) string {
return t.fileToGoPackageName[file]
}
func (t *psrpc) formattedOutput() string {
// Reformat generated code.
fset := token.NewFileSet()
raw := t.output.Bytes()
ast, err := parser.ParseFile(fset, "", raw, parser.ParseComments)
if err != nil {
// Print out the bad code with line numbers.
// This should never happen in practice, but it can while changing generated code,
// so consider this a debugging aid.
var src bytes.Buffer
s := bufio.NewScanner(bytes.NewReader(raw))
for line := 1; s.Scan(); line++ {
_, _ = fmt.Fprintf(&src, "%5d\t%s\n", line, s.Bytes())
}
gen.Fail("bad Go source code was generated:", err.Error(), "\n"+src.String())
}
out := bytes.NewBuffer(nil)
err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(out, fset, ast)
if err != nil {
gen.Fail("generated Go source code could not be reformatted:", err.Error())
}
return out.String()
}
func unexported(s string) string { return strings.ToLower(s[:1]) + s[1:] }
func serviceNameCamelCased(service *descriptor.ServiceDescriptorProto) string {
return stringutils.CamelCase(service.GetName())
}
func serviceStruct(service *descriptor.ServiceDescriptorProto) string {
return unexported(serviceNameCamelCased(service)) + "Server"
}
func methodNameCamelCased(method *descriptor.MethodDescriptorProto) string {
return stringutils.CamelCase(method.GetName())
}
func fileDescSliceContains(slice []*descriptor.FileDescriptorProto, f *descriptor.FileDescriptorProto) bool {
for _, sf := range slice {
if f == sf {
return true
}
}
return false
}
+40
View File
@@ -0,0 +1,40 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package main
import (
"os"
"os/exec"
"testing"
"google.golang.org/protobuf/proto"
plugin "google.golang.org/protobuf/types/pluginpb"
)
func TestGenerateParseCommandLineParamsError(t *testing.T) {
if os.Getenv("BE_CRASHER") == "1" {
g := &psrpc{}
g.Generate(&plugin.CodeGeneratorRequest{
Parameter: proto.String("invalid"),
})
return
}
cmd := exec.Command(os.Args[0], "-test.run=TestGenerateParseCommandLineParamsError")
cmd.Env = append(os.Environ(), "BE_CRASHER=1")
err := cmd.Run()
if e, ok := err.(*exec.ExitError); ok && !e.Success() {
return
}
t.Fatalf("process ran with err %v, want exit status 1", err)
}
+119
View File
@@ -0,0 +1,119 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package main
import (
"path"
"strings"
descriptor "google.golang.org/protobuf/types/descriptorpb"
"github.com/livekit/psrpc/internal/gen/stringutils"
)
// goPackageOption interprets the file's go_package option.
// If there is no go_package, it returns ("", "", false).
// If there's a simple name, it returns ("", pkg, true).
// If the option implies an import path, it returns (impPath, pkg, true).
func goPackageOption(f *descriptor.FileDescriptorProto) (impPath, pkg string, ok bool) {
pkg = f.GetOptions().GetGoPackage()
if pkg == "" {
return "", "", false
}
if bits := strings.Split(pkg, ";"); len(bits) == 2 {
return bits[0], bits[1], true
}
// The presence of a slash implies there's an import path.
slash := strings.LastIndex(pkg, "/")
if slash < 0 {
return "", pkg, true
}
impPath, pkg = pkg, pkg[slash+1:]
// A semicolon-delimited suffix overrides the package name.
sc := strings.IndexByte(impPath, ';')
if sc < 0 {
return impPath, pkg, true
}
impPath, pkg = impPath[:sc], impPath[sc+1:]
return impPath, pkg, true
}
// goPackageName returns the Go package name to use in the generated Go file.
// The result explicitly reports whether the name came from an option go_package
// statement. If explicit is false, the name was derived from the protocol
// buffer's package statement or the input file name.
func goPackageName(f *descriptor.FileDescriptorProto) (name string, explicit bool) {
// Does the file have a "go_package" option?
if _, pkg, ok := goPackageOption(f); ok {
return pkg, true
}
// Does the file have a package clause?
if pkg := f.GetPackage(); pkg != "" {
return pkg, false
}
// Use the file base name.
return stringutils.BaseName(f.GetName()), false
}
// goFileName returns the output name for the generated Go file.
func (t *psrpc) goFileName(f *descriptor.FileDescriptorProto) string {
name := *f.Name // proto file name
if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" {
name = name[:len(name)-len(ext)] // remove extension
}
name += ".psrpc.go" // add psrpc extension
// with paths=source_relative, the directory is the same as the proto file
if t.sourceRelativePaths {
return name
}
// otherwise, the directory is taken from the option go_package
if impPath, _, ok := goPackageOption(f); ok && impPath != "" {
if t.modulePrefix != "" {
impPath = strings.TrimPrefix(strings.TrimPrefix(impPath, t.modulePrefix), "/")
}
// Replace the existing dirname with the import path from go_package
_, name = path.Split(name)
name = path.Join(impPath, name)
return name
}
return name
}
func parseGoPackageOption(v string) (importPath, packageName string) {
// Allowed formats:
// option go_package = "foo";
// option go_package = "github.com/example/foo";
// option go_package = "github.com/example/foo;bar";
semicolonPos := strings.Index(v, ";")
if semicolonPos > -1 {
importPath = v[:semicolonPos]
packageName = v[semicolonPos+1:]
return
}
if strings.Contains(v, "/") {
importPath = v
_, packageName = path.Split(v)
return
}
importPath = ""
packageName = v
return
}
+106
View File
@@ -0,0 +1,106 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package main
import (
"testing"
descriptor "google.golang.org/protobuf/types/descriptorpb"
)
func TestParseGoPackageOption(t *testing.T) {
testcase := func(in, wantImport, wantPkg string) func(*testing.T) {
return func(t *testing.T) {
haveImport, havePkg := parseGoPackageOption(in)
if haveImport != wantImport {
t.Errorf("wrong importPath, have=%q want=%q", haveImport, wantImport)
}
if havePkg != wantPkg {
t.Errorf("wrong packageName, have=%q want=%q", havePkg, wantPkg)
}
}
}
t.Run("empty string", testcase("", "", ""))
t.Run("bare package", testcase("foo", "", "foo"))
t.Run("full import", testcase("github.com/example/foo", "github.com/example/foo", "foo"))
t.Run("full import with override",
testcase("github.com/example/foo;bar", "github.com/example/foo", "bar"))
t.Run("non dotted import with package", testcase("foo;bar", "foo", "bar"))
}
func TestGoPackageOption(t *testing.T) {
testcase := func(in, wantImport, wantPkg string, wantOK bool) func(*testing.T) {
return func(t *testing.T) {
haveImport, havePkg, haveOK := goPackageOption(&descriptor.FileDescriptorProto{
Options: &descriptor.FileOptions{
GoPackage: &in,
},
})
if wantOK != haveOK {
t.Errorf("wrong ok, have=%t want=%t", haveOK, wantOK)
}
if haveImport != wantImport {
t.Errorf("wrong importPath, have=%q want=%q", haveImport, wantImport)
}
if havePkg != wantPkg {
t.Errorf("wrong packageName, have=%q want=%q", havePkg, wantPkg)
}
}
}
t.Run("empty string", testcase("", "", "", false))
t.Run("bare package", testcase("foo", "", "foo", true))
t.Run("full import", testcase("github.com/example/foo", "github.com/example/foo", "foo", true))
t.Run("full import with override",
testcase("github.com/example/foo;bar", "github.com/example/foo", "bar", true))
t.Run("non dotted import with package", testcase("foo;bar", "foo", "bar", true))
}
func TestGoFileName(t *testing.T) {
testcase := func(srcrelpaths bool, modprefix, fname, gopkg, wantName string) func(t2 *testing.T) {
return func(t *testing.T) {
f := &descriptor.FileDescriptorProto{
Name: &fname,
Options: &descriptor.FileOptions{
GoPackage: &gopkg,
},
}
tw := &psrpc{
sourceRelativePaths: srcrelpaths,
modulePrefix: modprefix,
}
if name := tw.goFileName(f); name != wantName {
t.Errorf("wrong goFileName, have=%q want=%q", name, wantName)
}
}
}
t.Run("paths=source_relative",
testcase(true, "",
"rpc/v1/service.proto", "example.com/module/package/rpc/v1",
"rpc/v1/service.psrpc.go"))
t.Run("paths=import,module=example.com/module/package",
testcase(false, "example.com/module/package",
"rpc/v1/service.proto", "example.com/module/package/rpc/v1",
"rpc/v1/service.psrpc.go"))
t.Run("paths=import,module=example.com/module/package/",
testcase(false, "example.com/module/package/",
"rpc/v1/service.proto", "example.com/module/package/rpc/v1",
"rpc/v1/service.psrpc.go"))
}
+34
View File
@@ -0,0 +1,34 @@
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
// use this file except in compliance with the License. A copy of the License is
// located at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// or in the "license" file accompanying this file. This file is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package main
import (
"flag"
"fmt"
"os"
"github.com/livekit/psrpc/internal/gen"
)
func main() {
versionFlag := flag.Bool("version", false, "print version and exit")
flag.Parse()
if *versionFlag {
fmt.Println(gen.Version)
os.Exit(0)
}
g := newGenerator()
gen.Main(g)
}
+208
View File
@@ -0,0 +1,208 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.21.5
// source: options.proto
package options
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
descriptorpb "google.golang.org/protobuf/types/descriptorpb"
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 Options struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// For RPCs, each client request will receive a response from every server.
// For subscriptions, every client will receive every update.
Multi bool `protobuf:"varint,1,opt,name=multi,proto3" json:"multi,omitempty"`
// This method is a pub/sub.
Subscription bool `protobuf:"varint,2,opt,name=subscription,proto3" json:"subscription,omitempty"`
// This method uses topics.
Topics bool `protobuf:"varint,3,opt,name=topics,proto3" json:"topics,omitempty"`
// Your service will supply an affinity function for handler selection.
AffinityFunc bool `protobuf:"varint,4,opt,name=affinity_func,json=affinityFunc,proto3" json:"affinity_func,omitempty"`
}
func (x *Options) Reset() {
*x = Options{}
if protoimpl.UnsafeEnabled {
mi := &file_options_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Options) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Options) ProtoMessage() {}
func (x *Options) ProtoReflect() protoreflect.Message {
mi := &file_options_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 Options.ProtoReflect.Descriptor instead.
func (*Options) Descriptor() ([]byte, []int) {
return file_options_proto_rawDescGZIP(), []int{0}
}
func (x *Options) GetMulti() bool {
if x != nil {
return x.Multi
}
return false
}
func (x *Options) GetSubscription() bool {
if x != nil {
return x.Subscription
}
return false
}
func (x *Options) GetTopics() bool {
if x != nil {
return x.Topics
}
return false
}
func (x *Options) GetAffinityFunc() bool {
if x != nil {
return x.AffinityFunc
}
return false
}
var file_options_proto_extTypes = []protoimpl.ExtensionInfo{
{
ExtendedType: (*descriptorpb.MethodOptions)(nil),
ExtensionType: (*Options)(nil),
Field: 2198,
Name: "psrpc.options",
Tag: "bytes,2198,opt,name=options",
Filename: "options.proto",
},
}
// Extension fields to descriptorpb.MethodOptions.
var (
// optional psrpc.Options options = 2198;
E_Options = &file_options_proto_extTypes[0]
)
var File_options_proto protoreflect.FileDescriptor
var file_options_proto_rawDesc = []byte{
0x0a, 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x05, 0x70, 0x73, 0x72, 0x70, 0x63, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x80, 0x01, 0x0a, 0x07, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x18, 0x01, 0x20,
0x01, 0x28, 0x08, 0x52, 0x05, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x75,
0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16,
0x0a, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06,
0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x66, 0x66, 0x69, 0x6e, 0x69,
0x74, 0x79, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61,
0x66, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x46, 0x75, 0x6e, 0x63, 0x3a, 0x4c, 0x0a, 0x07, 0x6f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x96, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e,
0x70, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x88, 0x01, 0x01, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74,
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2f,
0x70, 0x73, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e,
0x2d, 0x70, 0x73, 0x72, 0x70, 0x63, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_options_proto_rawDescOnce sync.Once
file_options_proto_rawDescData = file_options_proto_rawDesc
)
func file_options_proto_rawDescGZIP() []byte {
file_options_proto_rawDescOnce.Do(func() {
file_options_proto_rawDescData = protoimpl.X.CompressGZIP(file_options_proto_rawDescData)
})
return file_options_proto_rawDescData
}
var file_options_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_options_proto_goTypes = []interface{}{
(*Options)(nil), // 0: psrpc.Options
(*descriptorpb.MethodOptions)(nil), // 1: google.protobuf.MethodOptions
}
var file_options_proto_depIdxs = []int32{
1, // 0: psrpc.options:extendee -> google.protobuf.MethodOptions
0, // 1: psrpc.options:type_name -> psrpc.Options
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
1, // [1:2] is the sub-list for extension type_name
0, // [0:1] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_options_proto_init() }
func file_options_proto_init() {
if File_options_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_options_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Options); 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_options_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 1,
NumServices: 0,
},
GoTypes: file_options_proto_goTypes,
DependencyIndexes: file_options_proto_depIdxs,
MessageInfos: file_options_proto_msgTypes,
ExtensionInfos: file_options_proto_extTypes,
}.Build()
File_options_proto = out.File
file_options_proto_rawDesc = nil
file_options_proto_goTypes = nil
file_options_proto_depIdxs = nil
}
+25
View File
@@ -0,0 +1,25 @@
syntax = "proto3";
package psrpc;
option go_package = "github.com/livekit/psrpc/protoc-gen-psrpc/options";
import "google/protobuf/descriptor.proto";
extend google.protobuf.MethodOptions {
optional Options options = 2198;
}
message Options {
// For RPCs, each client request will receive a response from every server.
// For subscriptions, every client will receive every update.
bool multi = 1;
// This method is a pub/sub.
bool subscription = 2;
// This method uses topics.
bool topics = 3;
// Your service will supply an affinity function for handler selection.
bool affinity_func = 4;
}

Some files were not shown because too many files have changed in this diff Show More