Merge pull request #1296 from ktock/monitor-list
monitor: Enable to run build and invoke in backgroundpull/1577/head
						commit
						cb94298a02
					
				@ -0,0 +1,262 @@
 | 
				
			|||||||
 | 
					package controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/containerd/console"
 | 
				
			||||||
 | 
						"github.com/containerd/containerd/defaults"
 | 
				
			||||||
 | 
						"github.com/containerd/containerd/pkg/dialer"
 | 
				
			||||||
 | 
						"github.com/docker/buildx/commands/controller/pb"
 | 
				
			||||||
 | 
						"github.com/docker/buildx/util/progress"
 | 
				
			||||||
 | 
						"github.com/moby/buildkit/client"
 | 
				
			||||||
 | 
						"github.com/moby/buildkit/identity"
 | 
				
			||||||
 | 
						"github.com/pkg/errors"
 | 
				
			||||||
 | 
						"golang.org/x/sync/errgroup"
 | 
				
			||||||
 | 
						"google.golang.org/grpc"
 | 
				
			||||||
 | 
						"google.golang.org/grpc/backoff"
 | 
				
			||||||
 | 
						"google.golang.org/grpc/credentials/insecure"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewClient(addr string) (*Client, error) {
 | 
				
			||||||
 | 
						backoffConfig := backoff.DefaultConfig
 | 
				
			||||||
 | 
						backoffConfig.MaxDelay = 3 * time.Second
 | 
				
			||||||
 | 
						connParams := grpc.ConnectParams{
 | 
				
			||||||
 | 
							Backoff: backoffConfig,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						gopts := []grpc.DialOption{
 | 
				
			||||||
 | 
							grpc.WithTransportCredentials(insecure.NewCredentials()),
 | 
				
			||||||
 | 
							grpc.WithConnectParams(connParams),
 | 
				
			||||||
 | 
							grpc.WithContextDialer(dialer.ContextDialer),
 | 
				
			||||||
 | 
							grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)),
 | 
				
			||||||
 | 
							grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize)),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						conn, err := grpc.Dial(dialer.DialAddress(addr), gopts...)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &Client{conn: conn}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Client struct {
 | 
				
			||||||
 | 
						conn      *grpc.ClientConn
 | 
				
			||||||
 | 
						closeOnce sync.Once
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) Close() (err error) {
 | 
				
			||||||
 | 
						c.closeOnce.Do(func() {
 | 
				
			||||||
 | 
							err = c.conn.Close()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) Version(ctx context.Context) (string, string, string, error) {
 | 
				
			||||||
 | 
						res, err := c.client().Info(ctx, &pb.InfoRequest{})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", "", "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						v := res.BuildxVersion
 | 
				
			||||||
 | 
						return v.Package, v.Version, v.Revision, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) List(ctx context.Context) (keys []string, retErr error) {
 | 
				
			||||||
 | 
						res, err := c.client().List(ctx, &pb.ListRequest{})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return res.Keys, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) Disconnect(ctx context.Context, key string) error {
 | 
				
			||||||
 | 
						_, err := c.client().Disconnect(ctx, &pb.DisconnectRequest{Ref: key})
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) Invoke(ctx context.Context, ref string, containerConfig pb.ContainerConfig, in io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {
 | 
				
			||||||
 | 
						if ref == "" {
 | 
				
			||||||
 | 
							return fmt.Errorf("build reference must be specified")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						stream, err := c.client().Invoke(ctx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return attachIO(ctx, stream, &pb.InitMessage{Ref: ref, ContainerConfig: &containerConfig}, ioAttachConfig{
 | 
				
			||||||
 | 
							stdin:  in,
 | 
				
			||||||
 | 
							stdout: stdout,
 | 
				
			||||||
 | 
							stderr: stderr,
 | 
				
			||||||
 | 
							// TODO: Signal, Resize
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) Build(ctx context.Context, options pb.BuildOptions, in io.ReadCloser, w io.Writer, out console.File, progressMode string) (string, error) {
 | 
				
			||||||
 | 
						ref := identity.NewID()
 | 
				
			||||||
 | 
						pw, err := progress.NewPrinter(context.TODO(), w, out, progressMode)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						statusChan := make(chan *client.SolveStatus)
 | 
				
			||||||
 | 
						statusDone := make(chan struct{})
 | 
				
			||||||
 | 
						eg, egCtx := errgroup.WithContext(ctx)
 | 
				
			||||||
 | 
						eg.Go(func() error {
 | 
				
			||||||
 | 
							defer close(statusChan)
 | 
				
			||||||
 | 
							return c.build(egCtx, ref, options, in, statusChan)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						eg.Go(func() error {
 | 
				
			||||||
 | 
							defer close(statusDone)
 | 
				
			||||||
 | 
							for s := range statusChan {
 | 
				
			||||||
 | 
								st := s
 | 
				
			||||||
 | 
								pw.Write(st)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						eg.Go(func() error {
 | 
				
			||||||
 | 
							<-statusDone
 | 
				
			||||||
 | 
							return pw.Wait()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return ref, eg.Wait()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) build(ctx context.Context, ref string, options pb.BuildOptions, in io.ReadCloser, statusChan chan *client.SolveStatus) error {
 | 
				
			||||||
 | 
						eg, egCtx := errgroup.WithContext(ctx)
 | 
				
			||||||
 | 
						done := make(chan struct{})
 | 
				
			||||||
 | 
						eg.Go(func() error {
 | 
				
			||||||
 | 
							defer close(done)
 | 
				
			||||||
 | 
							if _, err := c.client().Build(egCtx, &pb.BuildRequest{
 | 
				
			||||||
 | 
								Ref:     ref,
 | 
				
			||||||
 | 
								Options: &options,
 | 
				
			||||||
 | 
							}); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						eg.Go(func() error {
 | 
				
			||||||
 | 
							stream, err := c.client().Status(egCtx, &pb.StatusRequest{
 | 
				
			||||||
 | 
								Ref: ref,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								resp, err := stream.Recv()
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									if err == io.EOF {
 | 
				
			||||||
 | 
										return nil
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return errors.Wrap(err, "failed to receive status")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								s := client.SolveStatus{}
 | 
				
			||||||
 | 
								for _, v := range resp.Vertexes {
 | 
				
			||||||
 | 
									s.Vertexes = append(s.Vertexes, &client.Vertex{
 | 
				
			||||||
 | 
										Digest:        v.Digest,
 | 
				
			||||||
 | 
										Inputs:        v.Inputs,
 | 
				
			||||||
 | 
										Name:          v.Name,
 | 
				
			||||||
 | 
										Started:       v.Started,
 | 
				
			||||||
 | 
										Completed:     v.Completed,
 | 
				
			||||||
 | 
										Error:         v.Error,
 | 
				
			||||||
 | 
										Cached:        v.Cached,
 | 
				
			||||||
 | 
										ProgressGroup: v.ProgressGroup,
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								for _, v := range resp.Statuses {
 | 
				
			||||||
 | 
									s.Statuses = append(s.Statuses, &client.VertexStatus{
 | 
				
			||||||
 | 
										ID:        v.ID,
 | 
				
			||||||
 | 
										Vertex:    v.Vertex,
 | 
				
			||||||
 | 
										Name:      v.Name,
 | 
				
			||||||
 | 
										Total:     v.Total,
 | 
				
			||||||
 | 
										Current:   v.Current,
 | 
				
			||||||
 | 
										Timestamp: v.Timestamp,
 | 
				
			||||||
 | 
										Started:   v.Started,
 | 
				
			||||||
 | 
										Completed: v.Completed,
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								for _, v := range resp.Logs {
 | 
				
			||||||
 | 
									s.Logs = append(s.Logs, &client.VertexLog{
 | 
				
			||||||
 | 
										Vertex:    v.Vertex,
 | 
				
			||||||
 | 
										Stream:    int(v.Stream),
 | 
				
			||||||
 | 
										Data:      v.Msg,
 | 
				
			||||||
 | 
										Timestamp: v.Timestamp,
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								for _, v := range resp.Warnings {
 | 
				
			||||||
 | 
									s.Warnings = append(s.Warnings, &client.VertexWarning{
 | 
				
			||||||
 | 
										Vertex:     v.Vertex,
 | 
				
			||||||
 | 
										Level:      int(v.Level),
 | 
				
			||||||
 | 
										Short:      v.Short,
 | 
				
			||||||
 | 
										Detail:     v.Detail,
 | 
				
			||||||
 | 
										URL:        v.Url,
 | 
				
			||||||
 | 
										SourceInfo: v.Info,
 | 
				
			||||||
 | 
										Range:      v.Ranges,
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								statusChan <- &s
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if in != nil {
 | 
				
			||||||
 | 
							eg.Go(func() error {
 | 
				
			||||||
 | 
								stream, err := c.client().Input(egCtx)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err := stream.Send(&pb.InputMessage{
 | 
				
			||||||
 | 
									Input: &pb.InputMessage_Init{
 | 
				
			||||||
 | 
										Init: &pb.InputInitMessage{
 | 
				
			||||||
 | 
											Ref: ref,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								}); err != nil {
 | 
				
			||||||
 | 
									return fmt.Errorf("failed to init input: %w", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								inReader, inWriter := io.Pipe()
 | 
				
			||||||
 | 
								eg2, _ := errgroup.WithContext(ctx)
 | 
				
			||||||
 | 
								eg2.Go(func() error {
 | 
				
			||||||
 | 
									<-done
 | 
				
			||||||
 | 
									return inWriter.Close()
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								go func() {
 | 
				
			||||||
 | 
									// do not wait for read completion but return here and let the caller send EOF
 | 
				
			||||||
 | 
									// this allows us to return on ctx.Done() without being blocked by this reader.
 | 
				
			||||||
 | 
									io.Copy(inWriter, in)
 | 
				
			||||||
 | 
									inWriter.Close()
 | 
				
			||||||
 | 
								}()
 | 
				
			||||||
 | 
								eg2.Go(func() error {
 | 
				
			||||||
 | 
									for {
 | 
				
			||||||
 | 
										buf := make([]byte, 32*1024)
 | 
				
			||||||
 | 
										n, err := inReader.Read(buf)
 | 
				
			||||||
 | 
										if err != nil {
 | 
				
			||||||
 | 
											if err == io.EOF {
 | 
				
			||||||
 | 
												break // break loop and send EOF
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											return err
 | 
				
			||||||
 | 
										} else if n > 0 {
 | 
				
			||||||
 | 
											if stream.Send(&pb.InputMessage{
 | 
				
			||||||
 | 
												Input: &pb.InputMessage_Data{
 | 
				
			||||||
 | 
													Data: &pb.DataMessage{
 | 
				
			||||||
 | 
														Data: buf[:n],
 | 
				
			||||||
 | 
													},
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											}); err != nil {
 | 
				
			||||||
 | 
												return err
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return stream.Send(&pb.InputMessage{
 | 
				
			||||||
 | 
										Input: &pb.InputMessage_Data{
 | 
				
			||||||
 | 
											Data: &pb.DataMessage{
 | 
				
			||||||
 | 
												EOF: true,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								return eg2.Wait()
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return eg.Wait()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) client() pb.ControllerClient {
 | 
				
			||||||
 | 
						return pb.NewControllerClient(c.conn)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,440 @@
 | 
				
			|||||||
 | 
					package controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/docker/buildx/build"
 | 
				
			||||||
 | 
						"github.com/docker/buildx/commands/controller/pb"
 | 
				
			||||||
 | 
						"github.com/docker/buildx/util/ioset"
 | 
				
			||||||
 | 
						"github.com/docker/buildx/version"
 | 
				
			||||||
 | 
						controlapi "github.com/moby/buildkit/api/services/control"
 | 
				
			||||||
 | 
						"github.com/moby/buildkit/client"
 | 
				
			||||||
 | 
						"github.com/sirupsen/logrus"
 | 
				
			||||||
 | 
						"golang.org/x/sync/errgroup"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type BuildFunc func(ctx context.Context, options *pb.BuildOptions, stdin io.Reader, statusChan chan *client.SolveStatus) (res *build.ResultContext, err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func New(buildFunc BuildFunc) *Controller {
 | 
				
			||||||
 | 
						return &Controller{
 | 
				
			||||||
 | 
							buildFunc: buildFunc,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Controller struct {
 | 
				
			||||||
 | 
						buildFunc BuildFunc
 | 
				
			||||||
 | 
						session   map[string]session
 | 
				
			||||||
 | 
						sessionMu sync.Mutex
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type session struct {
 | 
				
			||||||
 | 
						statusChan      chan *client.SolveStatus
 | 
				
			||||||
 | 
						result          *build.ResultContext
 | 
				
			||||||
 | 
						inputPipe       *io.PipeWriter
 | 
				
			||||||
 | 
						curInvokeCancel func()
 | 
				
			||||||
 | 
						curBuildCancel  func()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Controller) Info(ctx context.Context, req *pb.InfoRequest) (res *pb.InfoResponse, err error) {
 | 
				
			||||||
 | 
						return &pb.InfoResponse{
 | 
				
			||||||
 | 
							BuildxVersion: &pb.BuildxVersion{
 | 
				
			||||||
 | 
								Package:  version.Package,
 | 
				
			||||||
 | 
								Version:  version.Version,
 | 
				
			||||||
 | 
								Revision: version.Revision,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Controller) List(ctx context.Context, req *pb.ListRequest) (res *pb.ListResponse, err error) {
 | 
				
			||||||
 | 
						keys := make(map[string]struct{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m.sessionMu.Lock()
 | 
				
			||||||
 | 
						for k := range m.session {
 | 
				
			||||||
 | 
							keys[k] = struct{}{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m.sessionMu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var keysL []string
 | 
				
			||||||
 | 
						for k := range keys {
 | 
				
			||||||
 | 
							keysL = append(keysL, k)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &pb.ListResponse{
 | 
				
			||||||
 | 
							Keys: keysL,
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Controller) Disconnect(ctx context.Context, req *pb.DisconnectRequest) (res *pb.DisconnectResponse, err error) {
 | 
				
			||||||
 | 
						key := req.Ref
 | 
				
			||||||
 | 
						if key == "" {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("disconnect: empty key")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m.sessionMu.Lock()
 | 
				
			||||||
 | 
						if s, ok := m.session[key]; ok {
 | 
				
			||||||
 | 
							if s.curBuildCancel != nil {
 | 
				
			||||||
 | 
								s.curBuildCancel()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if s.curInvokeCancel != nil {
 | 
				
			||||||
 | 
								s.curInvokeCancel()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						delete(m.session, key)
 | 
				
			||||||
 | 
						m.sessionMu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &pb.DisconnectResponse{}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Controller) Close() error {
 | 
				
			||||||
 | 
						m.sessionMu.Lock()
 | 
				
			||||||
 | 
						for k := range m.session {
 | 
				
			||||||
 | 
							if s, ok := m.session[k]; ok {
 | 
				
			||||||
 | 
								if s.curBuildCancel != nil {
 | 
				
			||||||
 | 
									s.curBuildCancel()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if s.curInvokeCancel != nil {
 | 
				
			||||||
 | 
									s.curInvokeCancel()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m.sessionMu.Unlock()
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Controller) Build(ctx context.Context, req *pb.BuildRequest) (*pb.BuildResponse, error) {
 | 
				
			||||||
 | 
						ref := req.Ref
 | 
				
			||||||
 | 
						if ref == "" {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("build: empty key")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Prepare status channel and session if not exists
 | 
				
			||||||
 | 
						m.sessionMu.Lock()
 | 
				
			||||||
 | 
						if m.session == nil {
 | 
				
			||||||
 | 
							m.session = make(map[string]session)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s, ok := m.session[ref]
 | 
				
			||||||
 | 
						if ok && m.session[ref].statusChan != nil {
 | 
				
			||||||
 | 
							m.sessionMu.Unlock()
 | 
				
			||||||
 | 
							return &pb.BuildResponse{}, fmt.Errorf("build or status ongoing or status didn't called")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						statusChan := make(chan *client.SolveStatus)
 | 
				
			||||||
 | 
						s.statusChan = statusChan
 | 
				
			||||||
 | 
						m.session[ref] = session{statusChan: statusChan}
 | 
				
			||||||
 | 
						m.sessionMu.Unlock()
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							close(statusChan)
 | 
				
			||||||
 | 
							m.sessionMu.Lock()
 | 
				
			||||||
 | 
							s, ok := m.session[ref]
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								s.statusChan = nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							m.sessionMu.Unlock()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Prepare input stream pipe
 | 
				
			||||||
 | 
						inR, inW := io.Pipe()
 | 
				
			||||||
 | 
						m.sessionMu.Lock()
 | 
				
			||||||
 | 
						if s, ok := m.session[ref]; ok {
 | 
				
			||||||
 | 
							s.inputPipe = inW
 | 
				
			||||||
 | 
							m.session[ref] = s
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							m.sessionMu.Unlock()
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("build: unknown key %v", ref)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m.sessionMu.Unlock()
 | 
				
			||||||
 | 
						defer inR.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Build the specified request
 | 
				
			||||||
 | 
						ctx, cancel := context.WithCancel(ctx)
 | 
				
			||||||
 | 
						defer cancel()
 | 
				
			||||||
 | 
						res, err := m.buildFunc(ctx, req.Options, inR, statusChan)
 | 
				
			||||||
 | 
						m.sessionMu.Lock()
 | 
				
			||||||
 | 
						if s, ok := m.session[ref]; ok {
 | 
				
			||||||
 | 
							s.result = res
 | 
				
			||||||
 | 
							s.curBuildCancel = cancel
 | 
				
			||||||
 | 
							m.session[ref] = s
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							m.sessionMu.Unlock()
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("build: unknown key %v", ref)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m.sessionMu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &pb.BuildResponse{}, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Controller) Status(req *pb.StatusRequest, stream pb.Controller_StatusServer) error {
 | 
				
			||||||
 | 
						ref := req.Ref
 | 
				
			||||||
 | 
						if ref == "" {
 | 
				
			||||||
 | 
							return fmt.Errorf("status: empty key")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Wait and get status channel prepared by Build()
 | 
				
			||||||
 | 
						var statusChan <-chan *client.SolveStatus
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							// TODO: timeout?
 | 
				
			||||||
 | 
							m.sessionMu.Lock()
 | 
				
			||||||
 | 
							if _, ok := m.session[ref]; !ok || m.session[ref].statusChan == nil {
 | 
				
			||||||
 | 
								m.sessionMu.Unlock()
 | 
				
			||||||
 | 
								time.Sleep(time.Millisecond) // TODO: wait Build without busy loop and make it cancellable
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							statusChan = m.session[ref].statusChan
 | 
				
			||||||
 | 
							m.sessionMu.Unlock()
 | 
				
			||||||
 | 
							break
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// forward status
 | 
				
			||||||
 | 
						for ss := range statusChan {
 | 
				
			||||||
 | 
							if ss == nil {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							cs := toControlStatus(ss)
 | 
				
			||||||
 | 
							if err := stream.Send(cs); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Controller) Input(stream pb.Controller_InputServer) (err error) {
 | 
				
			||||||
 | 
						// Get the target ref from init message
 | 
				
			||||||
 | 
						msg, err := stream.Recv()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if !errors.Is(err, io.EOF) {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						init := msg.GetInit()
 | 
				
			||||||
 | 
						if init == nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("unexpected message: %T; wanted init", msg.GetInit())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ref := init.Ref
 | 
				
			||||||
 | 
						if ref == "" {
 | 
				
			||||||
 | 
							return fmt.Errorf("input: no ref is provided")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Wait and get input stream pipe prepared by Build()
 | 
				
			||||||
 | 
						var inputPipeW *io.PipeWriter
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							// TODO: timeout?
 | 
				
			||||||
 | 
							m.sessionMu.Lock()
 | 
				
			||||||
 | 
							if _, ok := m.session[ref]; !ok || m.session[ref].inputPipe == nil {
 | 
				
			||||||
 | 
								m.sessionMu.Unlock()
 | 
				
			||||||
 | 
								time.Sleep(time.Millisecond) // TODO: wait Build without busy loop and make it cancellable
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							inputPipeW = m.session[ref].inputPipe
 | 
				
			||||||
 | 
							m.sessionMu.Unlock()
 | 
				
			||||||
 | 
							break
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Forward input stream
 | 
				
			||||||
 | 
						eg, ctx := errgroup.WithContext(context.TODO())
 | 
				
			||||||
 | 
						done := make(chan struct{})
 | 
				
			||||||
 | 
						msgCh := make(chan *pb.InputMessage)
 | 
				
			||||||
 | 
						eg.Go(func() error {
 | 
				
			||||||
 | 
							defer close(msgCh)
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								msg, err := stream.Recv()
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									if !errors.Is(err, io.EOF) {
 | 
				
			||||||
 | 
										return err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								select {
 | 
				
			||||||
 | 
								case msgCh <- msg:
 | 
				
			||||||
 | 
								case <-done:
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								case <-ctx.Done():
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						eg.Go(func() (retErr error) {
 | 
				
			||||||
 | 
							defer close(done)
 | 
				
			||||||
 | 
							defer func() {
 | 
				
			||||||
 | 
								if retErr != nil {
 | 
				
			||||||
 | 
									inputPipeW.CloseWithError(retErr)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								inputPipeW.Close()
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								var msg *pb.InputMessage
 | 
				
			||||||
 | 
								select {
 | 
				
			||||||
 | 
								case msg = <-msgCh:
 | 
				
			||||||
 | 
								case <-ctx.Done():
 | 
				
			||||||
 | 
									return fmt.Errorf("canceled: %w", ctx.Err())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if msg == nil {
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if data := msg.GetData(); data != nil {
 | 
				
			||||||
 | 
									if len(data.Data) > 0 {
 | 
				
			||||||
 | 
										_, err := inputPipeW.Write(data.Data)
 | 
				
			||||||
 | 
										if err != nil {
 | 
				
			||||||
 | 
											return err
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if data.EOF {
 | 
				
			||||||
 | 
										return nil
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return eg.Wait()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Controller) Invoke(srv pb.Controller_InvokeServer) error {
 | 
				
			||||||
 | 
						ctx, cancel := context.WithCancel(context.TODO())
 | 
				
			||||||
 | 
						defer cancel()
 | 
				
			||||||
 | 
						containerIn, containerOut := ioset.Pipe()
 | 
				
			||||||
 | 
						waitInvokeDoneCh := make(chan struct{})
 | 
				
			||||||
 | 
						var cancelOnce sync.Once
 | 
				
			||||||
 | 
						curInvokeCancel := func() {
 | 
				
			||||||
 | 
							cancelOnce.Do(func() { containerOut.Close(); containerIn.Close(); cancel() })
 | 
				
			||||||
 | 
							<-waitInvokeDoneCh
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer curInvokeCancel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var cfg *pb.ContainerConfig
 | 
				
			||||||
 | 
						var resultCtx *build.ResultContext
 | 
				
			||||||
 | 
						initDoneCh := make(chan struct{})
 | 
				
			||||||
 | 
						initErrCh := make(chan error)
 | 
				
			||||||
 | 
						eg, egCtx := errgroup.WithContext(ctx)
 | 
				
			||||||
 | 
						eg.Go(func() error {
 | 
				
			||||||
 | 
							return serveIO(egCtx, srv, func(initMessage *pb.InitMessage) (retErr error) {
 | 
				
			||||||
 | 
								defer func() {
 | 
				
			||||||
 | 
									if retErr != nil {
 | 
				
			||||||
 | 
										initErrCh <- retErr
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									close(initDoneCh)
 | 
				
			||||||
 | 
								}()
 | 
				
			||||||
 | 
								ref := initMessage.Ref
 | 
				
			||||||
 | 
								cfg = initMessage.ContainerConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Register cancel callback
 | 
				
			||||||
 | 
								m.sessionMu.Lock()
 | 
				
			||||||
 | 
								if s, ok := m.session[ref]; ok {
 | 
				
			||||||
 | 
									if cancel := s.curInvokeCancel; cancel != nil {
 | 
				
			||||||
 | 
										logrus.Warnf("invoke: cancelling ongoing invoke of %q", ref)
 | 
				
			||||||
 | 
										cancel()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									s.curInvokeCancel = curInvokeCancel
 | 
				
			||||||
 | 
									m.session[ref] = s
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									m.sessionMu.Unlock()
 | 
				
			||||||
 | 
									return fmt.Errorf("invoke: unknown key %v", ref)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								m.sessionMu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Get the target result to invoke a container from
 | 
				
			||||||
 | 
								m.sessionMu.Lock()
 | 
				
			||||||
 | 
								if _, ok := m.session[ref]; !ok || m.session[ref].result == nil {
 | 
				
			||||||
 | 
									m.sessionMu.Unlock()
 | 
				
			||||||
 | 
									return fmt.Errorf("unknown reference: %q", ref)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								resultCtx = m.session[ref].result
 | 
				
			||||||
 | 
								m.sessionMu.Unlock()
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}, &ioServerConfig{
 | 
				
			||||||
 | 
								stdin:  containerOut.Stdin,
 | 
				
			||||||
 | 
								stdout: containerOut.Stdout,
 | 
				
			||||||
 | 
								stderr: containerOut.Stderr,
 | 
				
			||||||
 | 
								// TODO: signal, resize
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						eg.Go(func() error {
 | 
				
			||||||
 | 
							defer containerIn.Close()
 | 
				
			||||||
 | 
							defer cancel()
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case <-initDoneCh:
 | 
				
			||||||
 | 
							case err := <-initErrCh:
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if cfg == nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("no container config is provided")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if resultCtx == nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("no result is provided")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ccfg := build.ContainerConfig{
 | 
				
			||||||
 | 
								ResultCtx:  resultCtx,
 | 
				
			||||||
 | 
								Entrypoint: cfg.Entrypoint,
 | 
				
			||||||
 | 
								Cmd:        cfg.Cmd,
 | 
				
			||||||
 | 
								Env:        cfg.Env,
 | 
				
			||||||
 | 
								Tty:        cfg.Tty,
 | 
				
			||||||
 | 
								Stdin:      containerIn.Stdin,
 | 
				
			||||||
 | 
								Stdout:     containerIn.Stdout,
 | 
				
			||||||
 | 
								Stderr:     containerIn.Stderr,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !cfg.NoUser {
 | 
				
			||||||
 | 
								ccfg.User = &cfg.User
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !cfg.NoCwd {
 | 
				
			||||||
 | 
								ccfg.Cwd = &cfg.Cwd
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return build.Invoke(egCtx, ccfg)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						err := eg.Wait()
 | 
				
			||||||
 | 
						close(waitInvokeDoneCh)
 | 
				
			||||||
 | 
						curInvokeCancel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func toControlStatus(s *client.SolveStatus) *pb.StatusResponse {
 | 
				
			||||||
 | 
						resp := pb.StatusResponse{}
 | 
				
			||||||
 | 
						for _, v := range s.Vertexes {
 | 
				
			||||||
 | 
							resp.Vertexes = append(resp.Vertexes, &controlapi.Vertex{
 | 
				
			||||||
 | 
								Digest:        v.Digest,
 | 
				
			||||||
 | 
								Inputs:        v.Inputs,
 | 
				
			||||||
 | 
								Name:          v.Name,
 | 
				
			||||||
 | 
								Started:       v.Started,
 | 
				
			||||||
 | 
								Completed:     v.Completed,
 | 
				
			||||||
 | 
								Error:         v.Error,
 | 
				
			||||||
 | 
								Cached:        v.Cached,
 | 
				
			||||||
 | 
								ProgressGroup: v.ProgressGroup,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, v := range s.Statuses {
 | 
				
			||||||
 | 
							resp.Statuses = append(resp.Statuses, &controlapi.VertexStatus{
 | 
				
			||||||
 | 
								ID:        v.ID,
 | 
				
			||||||
 | 
								Vertex:    v.Vertex,
 | 
				
			||||||
 | 
								Name:      v.Name,
 | 
				
			||||||
 | 
								Total:     v.Total,
 | 
				
			||||||
 | 
								Current:   v.Current,
 | 
				
			||||||
 | 
								Timestamp: v.Timestamp,
 | 
				
			||||||
 | 
								Started:   v.Started,
 | 
				
			||||||
 | 
								Completed: v.Completed,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, v := range s.Logs {
 | 
				
			||||||
 | 
							resp.Logs = append(resp.Logs, &controlapi.VertexLog{
 | 
				
			||||||
 | 
								Vertex:    v.Vertex,
 | 
				
			||||||
 | 
								Stream:    int64(v.Stream),
 | 
				
			||||||
 | 
								Msg:       v.Data,
 | 
				
			||||||
 | 
								Timestamp: v.Timestamp,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, v := range s.Warnings {
 | 
				
			||||||
 | 
							resp.Warnings = append(resp.Warnings, &controlapi.VertexWarning{
 | 
				
			||||||
 | 
								Vertex: v.Vertex,
 | 
				
			||||||
 | 
								Level:  int64(v.Level),
 | 
				
			||||||
 | 
								Short:  v.Short,
 | 
				
			||||||
 | 
								Detail: v.Detail,
 | 
				
			||||||
 | 
								Url:    v.URL,
 | 
				
			||||||
 | 
								Info:   v.SourceInfo,
 | 
				
			||||||
 | 
								Ranges: v.Range,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &resp
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,431 @@
 | 
				
			|||||||
 | 
					package controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/docker/buildx/commands/controller/pb"
 | 
				
			||||||
 | 
						"github.com/moby/sys/signal"
 | 
				
			||||||
 | 
						"github.com/sirupsen/logrus"
 | 
				
			||||||
 | 
						"golang.org/x/sync/errgroup"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type msgStream interface {
 | 
				
			||||||
 | 
						Send(*pb.Message) error
 | 
				
			||||||
 | 
						Recv() (*pb.Message, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ioServerConfig struct {
 | 
				
			||||||
 | 
						stdin          io.WriteCloser
 | 
				
			||||||
 | 
						stdout, stderr io.ReadCloser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// signalFn is a callback function called when a signal is reached to the client.
 | 
				
			||||||
 | 
						signalFn func(context.Context, syscall.Signal) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// resizeFn is a callback function called when a resize event is reached to the client.
 | 
				
			||||||
 | 
						resizeFn func(context.Context, winSize) error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func serveIO(attachCtx context.Context, srv msgStream, initFn func(*pb.InitMessage) error, ioConfig *ioServerConfig) (err error) {
 | 
				
			||||||
 | 
						stdin, stdout, stderr := ioConfig.stdin, ioConfig.stdout, ioConfig.stderr
 | 
				
			||||||
 | 
						stream := &debugStream{srv, "server=" + time.Now().String()}
 | 
				
			||||||
 | 
						eg, ctx := errgroup.WithContext(attachCtx)
 | 
				
			||||||
 | 
						done := make(chan struct{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg, err := receive(ctx, stream)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						init := msg.GetInit()
 | 
				
			||||||
 | 
						if init == nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("unexpected message: %T; wanted init", msg.GetInput())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ref := init.Ref
 | 
				
			||||||
 | 
						if ref == "" {
 | 
				
			||||||
 | 
							return fmt.Errorf("no ref is provided")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := initFn(init); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("failed to initialize IO server: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if stdout != nil {
 | 
				
			||||||
 | 
							stdoutReader, stdoutWriter := io.Pipe()
 | 
				
			||||||
 | 
							eg.Go(func() error {
 | 
				
			||||||
 | 
								<-done
 | 
				
			||||||
 | 
								return stdoutWriter.Close()
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							go func() {
 | 
				
			||||||
 | 
								// do not wait for read completion but return here and let the caller send EOF
 | 
				
			||||||
 | 
								// this allows us to return on ctx.Done() without being blocked by this reader.
 | 
				
			||||||
 | 
								io.Copy(stdoutWriter, stdout)
 | 
				
			||||||
 | 
								stdoutWriter.Close()
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							eg.Go(func() error {
 | 
				
			||||||
 | 
								defer stdoutReader.Close()
 | 
				
			||||||
 | 
								return copyToStream(1, stream, stdoutReader)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if stderr != nil {
 | 
				
			||||||
 | 
							stderrReader, stderrWriter := io.Pipe()
 | 
				
			||||||
 | 
							eg.Go(func() error {
 | 
				
			||||||
 | 
								<-done
 | 
				
			||||||
 | 
								return stderrWriter.Close()
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							go func() {
 | 
				
			||||||
 | 
								// do not wait for read completion but return here and let the caller send EOF
 | 
				
			||||||
 | 
								// this allows us to return on ctx.Done() without being blocked by this reader.
 | 
				
			||||||
 | 
								io.Copy(stderrWriter, stderr)
 | 
				
			||||||
 | 
								stderrWriter.Close()
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							eg.Go(func() error {
 | 
				
			||||||
 | 
								defer stderrReader.Close()
 | 
				
			||||||
 | 
								return copyToStream(2, stream, stderrReader)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msgCh := make(chan *pb.Message)
 | 
				
			||||||
 | 
						eg.Go(func() error {
 | 
				
			||||||
 | 
							defer close(msgCh)
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								msg, err := receive(ctx, stream)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								select {
 | 
				
			||||||
 | 
								case msgCh <- msg:
 | 
				
			||||||
 | 
								case <-done:
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								case <-ctx.Done():
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						eg.Go(func() error {
 | 
				
			||||||
 | 
							defer close(done)
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								var msg *pb.Message
 | 
				
			||||||
 | 
								select {
 | 
				
			||||||
 | 
								case msg = <-msgCh:
 | 
				
			||||||
 | 
								case <-ctx.Done():
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if msg == nil {
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if file := msg.GetFile(); file != nil {
 | 
				
			||||||
 | 
									if file.Fd != 0 {
 | 
				
			||||||
 | 
										return fmt.Errorf("unexpected fd: %v", file.Fd)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if stdin == nil {
 | 
				
			||||||
 | 
										continue // no stdin destination is specified so ignore the data
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if len(file.Data) > 0 {
 | 
				
			||||||
 | 
										_, err := stdin.Write(file.Data)
 | 
				
			||||||
 | 
										if err != nil {
 | 
				
			||||||
 | 
											return err
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if file.EOF {
 | 
				
			||||||
 | 
										stdin.Close()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if resize := msg.GetResize(); resize != nil {
 | 
				
			||||||
 | 
									if ioConfig.resizeFn != nil {
 | 
				
			||||||
 | 
										ioConfig.resizeFn(ctx, winSize{
 | 
				
			||||||
 | 
											cols: resize.Cols,
 | 
				
			||||||
 | 
											rows: resize.Rows,
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if sig := msg.GetSignal(); sig != nil {
 | 
				
			||||||
 | 
									if ioConfig.signalFn != nil {
 | 
				
			||||||
 | 
										syscallSignal, ok := signal.SignalMap[sig.Name]
 | 
				
			||||||
 | 
										if !ok {
 | 
				
			||||||
 | 
											continue
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										ioConfig.signalFn(ctx, syscallSignal)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									return fmt.Errorf("unexpected message: %T", msg.GetInput())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return eg.Wait()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ioAttachConfig struct {
 | 
				
			||||||
 | 
						stdin          io.ReadCloser
 | 
				
			||||||
 | 
						stdout, stderr io.WriteCloser
 | 
				
			||||||
 | 
						signal         <-chan syscall.Signal
 | 
				
			||||||
 | 
						resize         <-chan winSize
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type winSize struct {
 | 
				
			||||||
 | 
						rows uint32
 | 
				
			||||||
 | 
						cols uint32
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func attachIO(ctx context.Context, stream msgStream, initMessage *pb.InitMessage, cfg ioAttachConfig) (retErr error) {
 | 
				
			||||||
 | 
						eg, ctx := errgroup.WithContext(ctx)
 | 
				
			||||||
 | 
						done := make(chan struct{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := stream.Send(&pb.Message{
 | 
				
			||||||
 | 
							Input: &pb.Message_Init{
 | 
				
			||||||
 | 
								Init: initMessage,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("failed to init: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if cfg.stdin != nil {
 | 
				
			||||||
 | 
							stdinReader, stdinWriter := io.Pipe()
 | 
				
			||||||
 | 
							eg.Go(func() error {
 | 
				
			||||||
 | 
								<-done
 | 
				
			||||||
 | 
								return stdinWriter.Close()
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							go func() {
 | 
				
			||||||
 | 
								// do not wait for read completion but return here and let the caller send EOF
 | 
				
			||||||
 | 
								// this allows us to return on ctx.Done() without being blocked by this reader.
 | 
				
			||||||
 | 
								io.Copy(stdinWriter, cfg.stdin)
 | 
				
			||||||
 | 
								stdinWriter.Close()
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							eg.Go(func() error {
 | 
				
			||||||
 | 
								defer stdinReader.Close()
 | 
				
			||||||
 | 
								return copyToStream(0, stream, stdinReader)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if cfg.signal != nil {
 | 
				
			||||||
 | 
							eg.Go(func() error {
 | 
				
			||||||
 | 
								for {
 | 
				
			||||||
 | 
									var sig syscall.Signal
 | 
				
			||||||
 | 
									select {
 | 
				
			||||||
 | 
									case sig = <-cfg.signal:
 | 
				
			||||||
 | 
									case <-done:
 | 
				
			||||||
 | 
										return nil
 | 
				
			||||||
 | 
									case <-ctx.Done():
 | 
				
			||||||
 | 
										return nil
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									name := sigToName[sig]
 | 
				
			||||||
 | 
									if name == "" {
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if err := stream.Send(&pb.Message{
 | 
				
			||||||
 | 
										Input: &pb.Message_Signal{
 | 
				
			||||||
 | 
											Signal: &pb.SignalMessage{
 | 
				
			||||||
 | 
												Name: name,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									}); err != nil {
 | 
				
			||||||
 | 
										return fmt.Errorf("failed to send signal: %w", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if cfg.resize != nil {
 | 
				
			||||||
 | 
							eg.Go(func() error {
 | 
				
			||||||
 | 
								for {
 | 
				
			||||||
 | 
									var win winSize
 | 
				
			||||||
 | 
									select {
 | 
				
			||||||
 | 
									case win = <-cfg.resize:
 | 
				
			||||||
 | 
									case <-done:
 | 
				
			||||||
 | 
										return nil
 | 
				
			||||||
 | 
									case <-ctx.Done():
 | 
				
			||||||
 | 
										return nil
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if err := stream.Send(&pb.Message{
 | 
				
			||||||
 | 
										Input: &pb.Message_Resize{
 | 
				
			||||||
 | 
											Resize: &pb.ResizeMessage{
 | 
				
			||||||
 | 
												Rows: win.rows,
 | 
				
			||||||
 | 
												Cols: win.cols,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									}); err != nil {
 | 
				
			||||||
 | 
										return fmt.Errorf("failed to send resize: %w", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msgCh := make(chan *pb.Message)
 | 
				
			||||||
 | 
						eg.Go(func() error {
 | 
				
			||||||
 | 
							defer close(msgCh)
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								msg, err := receive(ctx, stream)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								select {
 | 
				
			||||||
 | 
								case msgCh <- msg:
 | 
				
			||||||
 | 
								case <-done:
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								case <-ctx.Done():
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						eg.Go(func() error {
 | 
				
			||||||
 | 
							eofs := make(map[uint32]struct{})
 | 
				
			||||||
 | 
							defer close(done)
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								var msg *pb.Message
 | 
				
			||||||
 | 
								select {
 | 
				
			||||||
 | 
								case msg = <-msgCh:
 | 
				
			||||||
 | 
								case <-ctx.Done():
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if msg == nil {
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if file := msg.GetFile(); file != nil {
 | 
				
			||||||
 | 
									if _, ok := eofs[file.Fd]; ok {
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									var out io.WriteCloser
 | 
				
			||||||
 | 
									switch file.Fd {
 | 
				
			||||||
 | 
									case 1:
 | 
				
			||||||
 | 
										out = cfg.stdout
 | 
				
			||||||
 | 
									case 2:
 | 
				
			||||||
 | 
										out = cfg.stderr
 | 
				
			||||||
 | 
									default:
 | 
				
			||||||
 | 
										return fmt.Errorf("unsupported fd %d", file.Fd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if out == nil {
 | 
				
			||||||
 | 
										logrus.Warnf("attachIO: no writer for fd %d", file.Fd)
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if len(file.Data) > 0 {
 | 
				
			||||||
 | 
										if _, err := out.Write(file.Data); err != nil {
 | 
				
			||||||
 | 
											return err
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if file.EOF {
 | 
				
			||||||
 | 
										eofs[file.Fd] = struct{}{}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									return fmt.Errorf("unexpected message: %T", msg.GetInput())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return eg.Wait()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func receive(ctx context.Context, stream msgStream) (*pb.Message, error) {
 | 
				
			||||||
 | 
						msgCh := make(chan *pb.Message)
 | 
				
			||||||
 | 
						errCh := make(chan error)
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							msg, err := stream.Recv()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								if errors.Is(err, io.EOF) {
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								errCh <- err
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							msgCh <- msg
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						select {
 | 
				
			||||||
 | 
						case msg := <-msgCh:
 | 
				
			||||||
 | 
							return msg, nil
 | 
				
			||||||
 | 
						case err := <-errCh:
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						case <-ctx.Done():
 | 
				
			||||||
 | 
							return nil, ctx.Err()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func copyToStream(fd uint32, snd msgStream, r io.Reader) error {
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							buf := make([]byte, 32*1024)
 | 
				
			||||||
 | 
							n, err := r.Read(buf)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								if err == io.EOF {
 | 
				
			||||||
 | 
									break // break loop and send EOF
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							} else if n > 0 {
 | 
				
			||||||
 | 
								if snd.Send(&pb.Message{
 | 
				
			||||||
 | 
									Input: &pb.Message_File{
 | 
				
			||||||
 | 
										File: &pb.FdMessage{
 | 
				
			||||||
 | 
											Fd:   fd,
 | 
				
			||||||
 | 
											Data: buf[:n],
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								}); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return snd.Send(&pb.Message{
 | 
				
			||||||
 | 
							Input: &pb.Message_File{
 | 
				
			||||||
 | 
								File: &pb.FdMessage{
 | 
				
			||||||
 | 
									Fd:  fd,
 | 
				
			||||||
 | 
									EOF: true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var sigToName = map[syscall.Signal]string{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						for name, value := range signal.SignalMap {
 | 
				
			||||||
 | 
							sigToName[value] = name
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type debugStream struct {
 | 
				
			||||||
 | 
						msgStream
 | 
				
			||||||
 | 
						prefix string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *debugStream) Send(msg *pb.Message) error {
 | 
				
			||||||
 | 
						switch m := msg.GetInput().(type) {
 | 
				
			||||||
 | 
						case *pb.Message_File:
 | 
				
			||||||
 | 
							if m.File.EOF {
 | 
				
			||||||
 | 
								logrus.Debugf("|---> File Message (sender:%v) fd=%d, EOF", s.prefix, m.File.Fd)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								logrus.Debugf("|---> File Message (sender:%v) fd=%d, %d bytes", s.prefix, m.File.Fd, len(m.File.Data))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case *pb.Message_Resize:
 | 
				
			||||||
 | 
							logrus.Debugf("|---> Resize Message (sender:%v): %+v", s.prefix, m.Resize)
 | 
				
			||||||
 | 
						case *pb.Message_Signal:
 | 
				
			||||||
 | 
							logrus.Debugf("|---> Signal Message (sender:%v): %s", s.prefix, m.Signal.Name)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return s.msgStream.Send(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *debugStream) Recv() (*pb.Message, error) {
 | 
				
			||||||
 | 
						msg, err := s.msgStream.Recv()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						switch m := msg.GetInput().(type) {
 | 
				
			||||||
 | 
						case *pb.Message_File:
 | 
				
			||||||
 | 
							if m.File.EOF {
 | 
				
			||||||
 | 
								logrus.Debugf("|<--- File Message (receiver:%v) fd=%d, EOF", s.prefix, m.File.Fd)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								logrus.Debugf("|<--- File Message (receiver:%v) fd=%d, %d bytes", s.prefix, m.File.Fd, len(m.File.Data))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case *pb.Message_Resize:
 | 
				
			||||||
 | 
							logrus.Debugf("|<--- Resize Message (receiver:%v): %+v", s.prefix, m.Resize)
 | 
				
			||||||
 | 
						case *pb.Message_Signal:
 | 
				
			||||||
 | 
							logrus.Debugf("|<--- Signal Message (receiver:%v): %s", s.prefix, m.Signal.Name)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return msg, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								@ -0,0 +1,179 @@
 | 
				
			|||||||
 | 
					syntax = "proto3";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package buildx.controller.v1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/moby/buildkit/api/services/control/control.proto";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option go_package = "pb";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					service Controller {
 | 
				
			||||||
 | 
					  rpc Build(BuildRequest) returns (BuildResponse);
 | 
				
			||||||
 | 
					  rpc Status(StatusRequest) returns (stream StatusResponse);
 | 
				
			||||||
 | 
					  rpc Input(stream InputMessage) returns (InputResponse);
 | 
				
			||||||
 | 
					  rpc Invoke(stream Message) returns (stream Message);
 | 
				
			||||||
 | 
					  rpc List(ListRequest) returns (ListResponse);
 | 
				
			||||||
 | 
					  rpc Disconnect(DisconnectRequest) returns (DisconnectResponse);
 | 
				
			||||||
 | 
					  rpc Info(InfoRequest) returns (InfoResponse);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BuildRequest {
 | 
				
			||||||
 | 
					  string Ref = 1;
 | 
				
			||||||
 | 
					  BuildOptions Options = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BuildOptions {
 | 
				
			||||||
 | 
					  string ContextPath = 1;
 | 
				
			||||||
 | 
					  string DockerfileName = 2;
 | 
				
			||||||
 | 
					  string PrintFunc = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  repeated string Allow = 4;
 | 
				
			||||||
 | 
					  repeated string Attests = 5; // TODO
 | 
				
			||||||
 | 
					  repeated string BuildArgs = 6;
 | 
				
			||||||
 | 
					  repeated string CacheFrom = 7;
 | 
				
			||||||
 | 
					  repeated string CacheTo = 8;
 | 
				
			||||||
 | 
					  string CgroupParent = 9;
 | 
				
			||||||
 | 
					  repeated string Contexts = 10;
 | 
				
			||||||
 | 
					  repeated string ExtraHosts = 11;
 | 
				
			||||||
 | 
					  string ImageIDFile = 12;
 | 
				
			||||||
 | 
					  repeated string Labels = 13;
 | 
				
			||||||
 | 
					  string NetworkMode = 14;
 | 
				
			||||||
 | 
					  repeated string NoCacheFilter = 15;
 | 
				
			||||||
 | 
					  repeated string Outputs = 16;
 | 
				
			||||||
 | 
					  repeated string Platforms = 17;
 | 
				
			||||||
 | 
					  bool Quiet = 18;
 | 
				
			||||||
 | 
					  repeated string Secrets = 19;
 | 
				
			||||||
 | 
					  int64 ShmSize = 20;
 | 
				
			||||||
 | 
					  repeated string SSH = 21;
 | 
				
			||||||
 | 
					  repeated string Tags = 22;
 | 
				
			||||||
 | 
					  string Target = 23;
 | 
				
			||||||
 | 
					  UlimitOpt Ulimits = 24;
 | 
				
			||||||
 | 
					  // string Invoke: provided via Invoke API
 | 
				
			||||||
 | 
					  CommonOptions Opts = 25;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message UlimitOpt {
 | 
				
			||||||
 | 
					  map<string, Ulimit> values = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message Ulimit {
 | 
				
			||||||
 | 
					  string Name = 1;
 | 
				
			||||||
 | 
					  int64 Hard = 2;
 | 
				
			||||||
 | 
					  int64 Soft = 3;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message CommonOptions {
 | 
				
			||||||
 | 
					  string Builder = 1;
 | 
				
			||||||
 | 
					  string MetadataFile = 2;
 | 
				
			||||||
 | 
					  bool NoCache = 3;
 | 
				
			||||||
 | 
					  // string Progress: no progress view on server side
 | 
				
			||||||
 | 
					  bool Pull = 4;
 | 
				
			||||||
 | 
					  bool ExportPush = 5;
 | 
				
			||||||
 | 
					  bool ExportLoad = 6;
 | 
				
			||||||
 | 
					  string SBOM       = 7; // TODO
 | 
				
			||||||
 | 
					  string Provenance = 8; // TODO
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BuildResponse {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message DisconnectRequest {
 | 
				
			||||||
 | 
					  string Ref = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message DisconnectResponse {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message ListRequest {
 | 
				
			||||||
 | 
					  string Ref = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message ListResponse {
 | 
				
			||||||
 | 
					  repeated string keys = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message InputMessage {
 | 
				
			||||||
 | 
					  oneof Input {
 | 
				
			||||||
 | 
					    InputInitMessage Init = 1;
 | 
				
			||||||
 | 
					    DataMessage Data = 2;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message InputInitMessage {
 | 
				
			||||||
 | 
					  string Ref = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message DataMessage {
 | 
				
			||||||
 | 
					  bool EOF = 1;    // true if eof was reached
 | 
				
			||||||
 | 
					  bytes Data = 2;  // should be chunked smaller than 4MB:
 | 
				
			||||||
 | 
					                   // https://pkg.go.dev/google.golang.org/grpc#MaxRecvMsgSize
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message InputResponse {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message Message {
 | 
				
			||||||
 | 
					  oneof Input {
 | 
				
			||||||
 | 
					    InitMessage Init = 1;
 | 
				
			||||||
 | 
					    // FdMessage used from client to server for input (stdin) and
 | 
				
			||||||
 | 
					    // from server to client for output (stdout, stderr)
 | 
				
			||||||
 | 
					    FdMessage File = 2;
 | 
				
			||||||
 | 
					    // ResizeMessage used from client to server for terminal resize events
 | 
				
			||||||
 | 
					    ResizeMessage Resize = 3;
 | 
				
			||||||
 | 
					    // SignalMessage is used from client to server to send signal events
 | 
				
			||||||
 | 
					    SignalMessage Signal = 4;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message InitMessage {
 | 
				
			||||||
 | 
					  string Ref = 1;
 | 
				
			||||||
 | 
					  ContainerConfig ContainerConfig = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message ContainerConfig {
 | 
				
			||||||
 | 
					  repeated string Entrypoint = 1;
 | 
				
			||||||
 | 
					  repeated string Cmd = 2;
 | 
				
			||||||
 | 
					  repeated string Env = 3;
 | 
				
			||||||
 | 
					  string User = 4;
 | 
				
			||||||
 | 
					  bool NoUser = 5; // Do not set user but use the image's default
 | 
				
			||||||
 | 
					  string Cwd = 6;
 | 
				
			||||||
 | 
					  bool NoCwd = 7; // Do not set cwd but use the image's default
 | 
				
			||||||
 | 
					  bool Tty = 8;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message FdMessage {
 | 
				
			||||||
 | 
					  uint32 Fd = 1;   // what fd the data was from
 | 
				
			||||||
 | 
					  bool EOF = 2;    // true if eof was reached
 | 
				
			||||||
 | 
					  bytes Data = 3;  // should be chunked smaller than 4MB:
 | 
				
			||||||
 | 
					                   // https://pkg.go.dev/google.golang.org/grpc#MaxRecvMsgSize
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message ResizeMessage {
 | 
				
			||||||
 | 
					  uint32 Rows = 1;
 | 
				
			||||||
 | 
					  uint32 Cols = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message SignalMessage {
 | 
				
			||||||
 | 
					  // we only send name (ie HUP, INT) because the int values
 | 
				
			||||||
 | 
					  // are platform dependent.
 | 
				
			||||||
 | 
					  string Name = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message StatusRequest {
 | 
				
			||||||
 | 
					  string Ref = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message StatusResponse {
 | 
				
			||||||
 | 
					  repeated moby.buildkit.v1.Vertex vertexes = 1;
 | 
				
			||||||
 | 
					  repeated moby.buildkit.v1.VertexStatus statuses = 2;
 | 
				
			||||||
 | 
					  repeated moby.buildkit.v1.VertexLog logs = 3;
 | 
				
			||||||
 | 
					  repeated moby.buildkit.v1.VertexWarning warnings = 4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message InfoRequest {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message InfoResponse {
 | 
				
			||||||
 | 
					  BuildxVersion buildxVersion = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BuildxVersion {
 | 
				
			||||||
 | 
					  string package = 1;
 | 
				
			||||||
 | 
					  string version = 2;
 | 
				
			||||||
 | 
					  string revision = 3;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					package pb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//go:generate protoc -I=. -I=../../../vendor/ --gogo_out=plugins=grpc:. controller.proto
 | 
				
			||||||
@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					package commands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/containerd/console"
 | 
				
			||||||
 | 
						"github.com/docker/buildx/build"
 | 
				
			||||||
 | 
						controllerapi "github.com/docker/buildx/commands/controller/pb"
 | 
				
			||||||
 | 
						"github.com/docker/buildx/monitor"
 | 
				
			||||||
 | 
						"github.com/docker/cli/cli/command"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newLocalBuildxController(ctx context.Context, dockerCli command.Cli) monitor.BuildxController {
 | 
				
			||||||
 | 
						return &localController{
 | 
				
			||||||
 | 
							dockerCli: dockerCli,
 | 
				
			||||||
 | 
							ref:       "local",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type localController struct {
 | 
				
			||||||
 | 
						dockerCli command.Cli
 | 
				
			||||||
 | 
						ref       string
 | 
				
			||||||
 | 
						resultCtx *build.ResultContext
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *localController) Invoke(ctx context.Context, ref string, cfg controllerapi.ContainerConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error {
 | 
				
			||||||
 | 
						if ref != b.ref {
 | 
				
			||||||
 | 
							return fmt.Errorf("unknown ref %q", ref)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if b.resultCtx == nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("no build result is registered")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ccfg := build.ContainerConfig{
 | 
				
			||||||
 | 
							ResultCtx:  b.resultCtx,
 | 
				
			||||||
 | 
							Entrypoint: cfg.Entrypoint,
 | 
				
			||||||
 | 
							Cmd:        cfg.Cmd,
 | 
				
			||||||
 | 
							Env:        cfg.Env,
 | 
				
			||||||
 | 
							Tty:        cfg.Tty,
 | 
				
			||||||
 | 
							Stdin:      ioIn,
 | 
				
			||||||
 | 
							Stdout:     ioOut,
 | 
				
			||||||
 | 
							Stderr:     ioErr,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !cfg.NoUser {
 | 
				
			||||||
 | 
							ccfg.User = &cfg.User
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !cfg.NoCwd {
 | 
				
			||||||
 | 
							ccfg.Cwd = &cfg.Cwd
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return build.Invoke(ctx, ccfg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *localController) Build(ctx context.Context, options controllerapi.BuildOptions, in io.ReadCloser, w io.Writer, out console.File, progressMode string) (string, error) {
 | 
				
			||||||
 | 
						res, err := runBuildWithContext(ctx, b.dockerCli, options, in, progressMode, nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						b.resultCtx = res
 | 
				
			||||||
 | 
						return b.ref, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *localController) Kill(context.Context) error {
 | 
				
			||||||
 | 
						return nil // nop
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *localController) Close() error {
 | 
				
			||||||
 | 
						// TODO: cancel current build and invoke
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *localController) List(ctx context.Context) (res []string, _ error) {
 | 
				
			||||||
 | 
						return []string{b.ref}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *localController) Disconnect(ctx context.Context, key string) error {
 | 
				
			||||||
 | 
						return nil // nop
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,311 @@
 | 
				
			|||||||
 | 
					//go:build linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package commands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"os/exec"
 | 
				
			||||||
 | 
						"os/signal"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/containerd/containerd/log"
 | 
				
			||||||
 | 
						"github.com/docker/buildx/build"
 | 
				
			||||||
 | 
						"github.com/docker/buildx/commands/controller"
 | 
				
			||||||
 | 
						controllerapi "github.com/docker/buildx/commands/controller/pb"
 | 
				
			||||||
 | 
						"github.com/docker/buildx/monitor"
 | 
				
			||||||
 | 
						"github.com/docker/buildx/util/confutil"
 | 
				
			||||||
 | 
						"github.com/docker/buildx/version"
 | 
				
			||||||
 | 
						"github.com/docker/cli/cli/command"
 | 
				
			||||||
 | 
						"github.com/moby/buildkit/client"
 | 
				
			||||||
 | 
						"github.com/pelletier/go-toml"
 | 
				
			||||||
 | 
						"github.com/sirupsen/logrus"
 | 
				
			||||||
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
 | 
						"google.golang.org/grpc"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						serveCommandName = "_INTERNAL_SERVE"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type serverConfig struct {
 | 
				
			||||||
 | 
						// Specify buildx server root
 | 
				
			||||||
 | 
						Root string `toml:"root"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// LogLevel sets the logging level [trace, debug, info, warn, error, fatal, panic]
 | 
				
			||||||
 | 
						LogLevel string `toml:"log_level"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Specify file to output buildx server log
 | 
				
			||||||
 | 
						LogFile string `toml:"log_file"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newRemoteBuildxController(ctx context.Context, dockerCli command.Cli, opts buildOptions) (monitor.BuildxController, error) {
 | 
				
			||||||
 | 
						rootDir := opts.root
 | 
				
			||||||
 | 
						if rootDir == "" {
 | 
				
			||||||
 | 
							rootDir = rootDataDir(dockerCli)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						serverRoot := filepath.Join(rootDir, "shared")
 | 
				
			||||||
 | 
						c, err := newBuildxClientAndCheck(filepath.Join(serverRoot, "buildx.sock"), 1, 0)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							logrus.Info("no buildx server found; launching...")
 | 
				
			||||||
 | 
							// start buildx server via subcommand
 | 
				
			||||||
 | 
							launchFlags := []string{}
 | 
				
			||||||
 | 
							if opts.serverConfig != "" {
 | 
				
			||||||
 | 
								launchFlags = append(launchFlags, "--config", opts.serverConfig)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							logFile, err := getLogFilePath(dockerCli, opts.serverConfig)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							wait, err := launch(ctx, logFile, append([]string{serveCommandName}, launchFlags...)...)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							go wait()
 | 
				
			||||||
 | 
							c, err = newBuildxClientAndCheck(filepath.Join(serverRoot, "buildx.sock"), 10, time.Second)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, fmt.Errorf("cannot connect to the buildx server: %w", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &buildxController{c, serverRoot}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func addControllerCommands(cmd *cobra.Command, dockerCli command.Cli, rootOpts *rootOptions) {
 | 
				
			||||||
 | 
						cmd.AddCommand(
 | 
				
			||||||
 | 
							serveCmd(dockerCli, rootOpts),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func serveCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
 | 
				
			||||||
 | 
						var serverConfigPath string
 | 
				
			||||||
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
 | 
							Use:    fmt.Sprintf("%s [OPTIONS]", serveCommandName),
 | 
				
			||||||
 | 
							Hidden: true,
 | 
				
			||||||
 | 
							RunE: func(cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
								// Parse config
 | 
				
			||||||
 | 
								config, err := getConfig(dockerCli, serverConfigPath)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return fmt.Errorf("failed to get config")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if config.LogLevel == "" {
 | 
				
			||||||
 | 
									logrus.SetLevel(logrus.InfoLevel)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									lvl, err := logrus.ParseLevel(config.LogLevel)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return fmt.Errorf("failed to prepare logger: %w", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									logrus.SetLevel(lvl)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								logrus.SetFormatter(&logrus.JSONFormatter{
 | 
				
			||||||
 | 
									TimestampFormat: log.RFC3339NanoFixed,
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								root, err := prepareRootDir(dockerCli, config)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								pidF := filepath.Join(root, "pid")
 | 
				
			||||||
 | 
								if err := os.WriteFile(pidF, []byte(fmt.Sprintf("%d", os.Getpid())), 0600); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								defer func() {
 | 
				
			||||||
 | 
									if err := os.Remove(pidF); err != nil {
 | 
				
			||||||
 | 
										logrus.Errorf("failed to clean up info file %q: %v", pidF, err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// prepare server
 | 
				
			||||||
 | 
								b := controller.New(func(ctx context.Context, options *controllerapi.BuildOptions, stdin io.Reader, statusChan chan *client.SolveStatus) (res *build.ResultContext, err error) {
 | 
				
			||||||
 | 
									return runBuildWithContext(ctx, dockerCli, *options, stdin, "quiet", statusChan)
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								defer b.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// serve server
 | 
				
			||||||
 | 
								addr := filepath.Join(root, "buildx.sock")
 | 
				
			||||||
 | 
								if err := os.Remove(addr); err != nil && !os.IsNotExist(err) { // avoid EADDRINUSE
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								defer func() {
 | 
				
			||||||
 | 
									if err := os.Remove(addr); err != nil {
 | 
				
			||||||
 | 
										logrus.Errorf("failed to clean up socket %q: %v", addr, err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}()
 | 
				
			||||||
 | 
								logrus.Infof("starting server at %q", addr)
 | 
				
			||||||
 | 
								l, err := net.Listen("unix", addr)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								rpc := grpc.NewServer()
 | 
				
			||||||
 | 
								controllerapi.RegisterControllerServer(rpc, b)
 | 
				
			||||||
 | 
								doneCh := make(chan struct{})
 | 
				
			||||||
 | 
								errCh := make(chan error, 1)
 | 
				
			||||||
 | 
								go func() {
 | 
				
			||||||
 | 
									defer close(doneCh)
 | 
				
			||||||
 | 
									if err := rpc.Serve(l); err != nil {
 | 
				
			||||||
 | 
										errCh <- fmt.Errorf("error on serving via socket %q: %w", addr, err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}()
 | 
				
			||||||
 | 
								var s os.Signal
 | 
				
			||||||
 | 
								sigCh := make(chan os.Signal, 1)
 | 
				
			||||||
 | 
								signal.Notify(sigCh, os.Interrupt)
 | 
				
			||||||
 | 
								select {
 | 
				
			||||||
 | 
								case s = <-sigCh:
 | 
				
			||||||
 | 
									logrus.Debugf("got signal %v", s)
 | 
				
			||||||
 | 
								case err := <-errCh:
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								case <-doneCh:
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						flags := cmd.Flags()
 | 
				
			||||||
 | 
						flags.StringVar(&serverConfigPath, "config", "", "Specify buildx server config file")
 | 
				
			||||||
 | 
						return cmd
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getLogFilePath(dockerCli command.Cli, configPath string) (string, error) {
 | 
				
			||||||
 | 
						config, err := getConfig(dockerCli, configPath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", fmt.Errorf("failed to get config")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						logFile := config.LogFile
 | 
				
			||||||
 | 
						if logFile == "" {
 | 
				
			||||||
 | 
							root, err := prepareRootDir(dockerCli, config)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return "", err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							logFile = filepath.Join(root, "log")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return logFile, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getConfig(dockerCli command.Cli, configPath string) (*serverConfig, error) {
 | 
				
			||||||
 | 
						var defaultConfigPath bool
 | 
				
			||||||
 | 
						if configPath == "" {
 | 
				
			||||||
 | 
							defaultRoot := rootDataDir(dockerCli)
 | 
				
			||||||
 | 
							configPath = filepath.Join(defaultRoot, "config.toml")
 | 
				
			||||||
 | 
							defaultConfigPath = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var config serverConfig
 | 
				
			||||||
 | 
						tree, err := toml.LoadFile(configPath)
 | 
				
			||||||
 | 
						if err != nil && !(os.IsNotExist(err) && defaultConfigPath) {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("failed to load config file %q", configPath)
 | 
				
			||||||
 | 
						} else if err == nil {
 | 
				
			||||||
 | 
							if err := tree.Unmarshal(&config); err != nil {
 | 
				
			||||||
 | 
								return nil, fmt.Errorf("failed to unmarshal config file %q", configPath)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &config, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func prepareRootDir(dockerCli command.Cli, config *serverConfig) (string, error) {
 | 
				
			||||||
 | 
						rootDir := config.Root
 | 
				
			||||||
 | 
						if rootDir == "" {
 | 
				
			||||||
 | 
							rootDir = rootDataDir(dockerCli)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if rootDir == "" {
 | 
				
			||||||
 | 
							return "", fmt.Errorf("buildx root dir must be determined")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := os.MkdirAll(rootDir, 0700); err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						serverRoot := filepath.Join(rootDir, "shared")
 | 
				
			||||||
 | 
						if err := os.MkdirAll(serverRoot, 0700); err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return serverRoot, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func rootDataDir(dockerCli command.Cli) string {
 | 
				
			||||||
 | 
						return filepath.Join(confutil.ConfigDir(dockerCli), "controller")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newBuildxClientAndCheck(addr string, checkNum int, duration time.Duration) (*controller.Client, error) {
 | 
				
			||||||
 | 
						c, err := controller.NewClient(addr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var lastErr error
 | 
				
			||||||
 | 
						for i := 0; i < checkNum; i++ {
 | 
				
			||||||
 | 
							_, err := c.List(context.TODO())
 | 
				
			||||||
 | 
							if err == nil {
 | 
				
			||||||
 | 
								lastErr = nil
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							err = fmt.Errorf("failed to access server (tried %d times): %w", i, err)
 | 
				
			||||||
 | 
							logrus.Debugf("connection failure: %v", err)
 | 
				
			||||||
 | 
							lastErr = err
 | 
				
			||||||
 | 
							time.Sleep(duration)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if lastErr != nil {
 | 
				
			||||||
 | 
							return nil, lastErr
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p, v, r, err := c.Version(context.TODO())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						logrus.Debugf("connected to server (\"%v %v %v\")", p, v, r)
 | 
				
			||||||
 | 
						if !(p == version.Package && v == version.Version && r == version.Revision) {
 | 
				
			||||||
 | 
							logrus.Warnf("version mismatch (server: \"%v %v %v\", client: \"%v %v %v\"); please kill and restart buildx server",
 | 
				
			||||||
 | 
								p, v, r, version.Package, version.Version, version.Revision)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return c, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type buildxController struct {
 | 
				
			||||||
 | 
						*controller.Client
 | 
				
			||||||
 | 
						serverRoot string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *buildxController) Kill(ctx context.Context) error {
 | 
				
			||||||
 | 
						pidB, err := os.ReadFile(filepath.Join(c.serverRoot, "pid"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pid, err := strconv.ParseInt(string(pidB), 10, 64)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if pid <= 0 {
 | 
				
			||||||
 | 
							return fmt.Errorf("no PID is recorded for buildx server")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p, err := os.FindProcess(int(pid))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := p.Signal(syscall.SIGINT); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// TODO: Should we send SIGKILL if process doesn't finish?
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func launch(ctx context.Context, logFile string, args ...string) (func() error, error) {
 | 
				
			||||||
 | 
						bCmd := exec.CommandContext(ctx, os.Args[0], args...)
 | 
				
			||||||
 | 
						if logFile != "" {
 | 
				
			||||||
 | 
							f, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							defer f.Close()
 | 
				
			||||||
 | 
							bCmd.Stdout = f
 | 
				
			||||||
 | 
							bCmd.Stderr = f
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						bCmd.Stdin = nil
 | 
				
			||||||
 | 
						bCmd.Dir = "/"
 | 
				
			||||||
 | 
						bCmd.SysProcAttr = &syscall.SysProcAttr{
 | 
				
			||||||
 | 
							Setsid: true,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := bCmd.Start(); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return bCmd.Wait, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					//go:build !linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package commands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/docker/buildx/monitor"
 | 
				
			||||||
 | 
						"github.com/docker/cli/cli/command"
 | 
				
			||||||
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newRemoteBuildxController(ctx context.Context, dockerCli command.Cli, opts buildOptions) (monitor.BuildxController, error) {
 | 
				
			||||||
 | 
						return nil, fmt.Errorf("remote buildx unsupported")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func addControllerCommands(cmd *cobra.Command, dockerCli command.Cli, rootOpts *rootOptions) {}
 | 
				
			||||||
@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					# docker buildx _INTERNAL_SERVE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!---MARKER_GEN_START-->
 | 
				
			||||||
 | 
					### Options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| Name        | Type     | Default | Description                              |
 | 
				
			||||||
 | 
					|:------------|:---------|:--------|:-----------------------------------------|
 | 
				
			||||||
 | 
					| `--builder` | `string` |         | Override the configured builder instance |
 | 
				
			||||||
 | 
					| `--config`  | `string` |         | Specify buildx server config file        |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!---MARKER_GEN_END-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					# Forked from https://github.com/moby/buildkit/blob/e1b3b6c4abf7684f13e6391e5f7bc9210752687a/hack/dockerfiles/generated-files.Dockerfile
 | 
				
			||||||
 | 
					# Copyright The BuildKit Authors.
 | 
				
			||||||
 | 
					# Copyright The Buildx Authors.
 | 
				
			||||||
 | 
					# Licensed under the Apache License, Version 2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# syntax=docker/dockerfile-upstream:master
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ARG GO_VERSION="1.19"
 | 
				
			||||||
 | 
					ARG PROTOC_VERSION="3.11.4"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# protoc is dynamically linked to glibc so can't use alpine base
 | 
				
			||||||
 | 
					FROM golang:${GO_VERSION}-buster AS base
 | 
				
			||||||
 | 
					RUN apt-get update && apt-get --no-install-recommends install -y git unzip
 | 
				
			||||||
 | 
					ARG PROTOC_VERSION
 | 
				
			||||||
 | 
					ARG TARGETOS
 | 
				
			||||||
 | 
					ARG TARGETARCH
 | 
				
			||||||
 | 
					RUN <<EOT
 | 
				
			||||||
 | 
					  set -e
 | 
				
			||||||
 | 
					  arch=$(echo $TARGETARCH | sed -e s/amd64/x86_64/ -e s/arm64/aarch_64/)
 | 
				
			||||||
 | 
					  wget -q https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-${TARGETOS}-${arch}.zip
 | 
				
			||||||
 | 
					  unzip protoc-${PROTOC_VERSION}-${TARGETOS}-${arch}.zip -d /usr/local
 | 
				
			||||||
 | 
					EOT
 | 
				
			||||||
 | 
					WORKDIR /go/src/github.com/docker/buildx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM base AS tools
 | 
				
			||||||
 | 
					RUN --mount=type=bind,target=.,rw \
 | 
				
			||||||
 | 
					    --mount=type=cache,target=/root/.cache \
 | 
				
			||||||
 | 
					    --mount=type=cache,target=/go/pkg/mod \
 | 
				
			||||||
 | 
					    go install \
 | 
				
			||||||
 | 
					      github.com/gogo/protobuf/protoc-gen-gogo \
 | 
				
			||||||
 | 
					      github.com/gogo/protobuf/protoc-gen-gogofaster \
 | 
				
			||||||
 | 
					      github.com/gogo/protobuf/protoc-gen-gogoslick \
 | 
				
			||||||
 | 
					      github.com/golang/protobuf/protoc-gen-go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM tools AS generated
 | 
				
			||||||
 | 
					RUN --mount=type=bind,target=.,rw <<EOT
 | 
				
			||||||
 | 
					  set -ex
 | 
				
			||||||
 | 
					  go generate -mod=vendor -v ./...
 | 
				
			||||||
 | 
					  mkdir /out
 | 
				
			||||||
 | 
					  git ls-files -m --others -- ':!vendor' '**/*.pb.go' | tar -cf - --files-from - | tar -C /out -xf -
 | 
				
			||||||
 | 
					EOT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM scratch AS update
 | 
				
			||||||
 | 
					COPY --from=generated /out /
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM base AS validate
 | 
				
			||||||
 | 
					RUN --mount=type=bind,target=.,rw \
 | 
				
			||||||
 | 
					    --mount=type=bind,from=generated,source=/out,target=/generated-files <<EOT
 | 
				
			||||||
 | 
					  set -e
 | 
				
			||||||
 | 
					  git add -A
 | 
				
			||||||
 | 
					  if [ "$(ls -A /generated-files)" ]; then
 | 
				
			||||||
 | 
					    cp -rf /generated-files/* .
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					  diff=$(git status --porcelain -- ':!vendor' '**/*.pb.go')
 | 
				
			||||||
 | 
					  if [ -n "$diff" ]; then
 | 
				
			||||||
 | 
					    echo >&2 'ERROR: The result of "go generate" differs. Please update with "make generated-files"'
 | 
				
			||||||
 | 
					    echo "$diff"
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					EOT
 | 
				
			||||||
@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					// Forked from https://github.com/moby/buildkit/blob/e1b3b6c4abf7684f13e6391e5f7bc9210752687a/tools/tools.go
 | 
				
			||||||
 | 
					//go:build tools
 | 
				
			||||||
 | 
					// +build tools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Package tools tracks dependencies on binaries not referenced in this codebase.
 | 
				
			||||||
 | 
					// https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module
 | 
				
			||||||
 | 
					// Disclaimer: Avoid adding tools that don't need to be inferred from go.mod
 | 
				
			||||||
 | 
					// like golangci-lint and check they don't import too many dependencies.
 | 
				
			||||||
 | 
					package tools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/protoc-gen-gogo"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/protoc-gen-gogofaster"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/protoc-gen-gogoslick"
 | 
				
			||||||
 | 
						_ "github.com/golang/protobuf/protoc-gen-go"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -0,0 +1,256 @@
 | 
				
			|||||||
 | 
					package ioset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/pkg/errors"
 | 
				
			||||||
 | 
						"github.com/sirupsen/logrus"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Pipe returns a pair of piped readers and writers collection.
 | 
				
			||||||
 | 
					// They are useful for controlling stdio stream using Forwarder function.
 | 
				
			||||||
 | 
					func Pipe() (In, Out) {
 | 
				
			||||||
 | 
						r1, w1 := io.Pipe()
 | 
				
			||||||
 | 
						r2, w2 := io.Pipe()
 | 
				
			||||||
 | 
						r3, w3 := io.Pipe()
 | 
				
			||||||
 | 
						return In{r1, w2, w3}, Out{w1, r2, r3}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type In struct {
 | 
				
			||||||
 | 
						Stdin  io.ReadCloser
 | 
				
			||||||
 | 
						Stdout io.WriteCloser
 | 
				
			||||||
 | 
						Stderr io.WriteCloser
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s In) Close() (retErr error) {
 | 
				
			||||||
 | 
						if err := s.Stdin.Close(); err != nil {
 | 
				
			||||||
 | 
							retErr = err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.Stdout.Close(); err != nil {
 | 
				
			||||||
 | 
							retErr = err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.Stderr.Close(); err != nil {
 | 
				
			||||||
 | 
							retErr = err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Out struct {
 | 
				
			||||||
 | 
						Stdin  io.WriteCloser
 | 
				
			||||||
 | 
						Stdout io.ReadCloser
 | 
				
			||||||
 | 
						Stderr io.ReadCloser
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s Out) Close() (retErr error) {
 | 
				
			||||||
 | 
						if err := s.Stdin.Close(); err != nil {
 | 
				
			||||||
 | 
							retErr = err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.Stdout.Close(); err != nil {
 | 
				
			||||||
 | 
							retErr = err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.Stderr.Close(); err != nil {
 | 
				
			||||||
 | 
							retErr = err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Forwarder forwards IO between readers and writers contained
 | 
				
			||||||
 | 
					// in In and Out structs.
 | 
				
			||||||
 | 
					// In and Out can be changed during forwarding using SetIn and SetOut methods.
 | 
				
			||||||
 | 
					type Forwarder struct {
 | 
				
			||||||
 | 
						stdin  *SingleForwarder
 | 
				
			||||||
 | 
						stdout *SingleForwarder
 | 
				
			||||||
 | 
						stderr *SingleForwarder
 | 
				
			||||||
 | 
						mu     sync.Mutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// PropagateStdinClose indicates whether EOF from Stdin of Out should be propagated.
 | 
				
			||||||
 | 
						// If this is true, EOF from Stdin (reader) of Out closes Stdin (writer) of In.
 | 
				
			||||||
 | 
						PropagateStdinClose bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewForwarder() *Forwarder {
 | 
				
			||||||
 | 
						return &Forwarder{
 | 
				
			||||||
 | 
							stdin:               NewSingleForwarder(),
 | 
				
			||||||
 | 
							stdout:              NewSingleForwarder(),
 | 
				
			||||||
 | 
							stderr:              NewSingleForwarder(),
 | 
				
			||||||
 | 
							PropagateStdinClose: true,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *Forwarder) Close() (retErr error) {
 | 
				
			||||||
 | 
						if err := f.stdin.Close(); err != nil {
 | 
				
			||||||
 | 
							retErr = err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := f.stdout.Close(); err != nil {
 | 
				
			||||||
 | 
							retErr = err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := f.stderr.Close(); err != nil {
 | 
				
			||||||
 | 
							retErr = err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return retErr
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *Forwarder) SetOut(out *Out) {
 | 
				
			||||||
 | 
						f.mu.Lock()
 | 
				
			||||||
 | 
						if out == nil {
 | 
				
			||||||
 | 
							f.stdin.SetWriter(nil, func() io.WriteCloser { return nil })
 | 
				
			||||||
 | 
							f.stdout.SetReader(nil)
 | 
				
			||||||
 | 
							f.stderr.SetReader(nil)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							f.stdin.SetWriter(out.Stdin, func() io.WriteCloser {
 | 
				
			||||||
 | 
								if f.PropagateStdinClose {
 | 
				
			||||||
 | 
									out.Stdin.Close() // propagate EOF
 | 
				
			||||||
 | 
									logrus.Debug("forwarder: propagating stdin close")
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return out.Stdin
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							f.stdout.SetReader(out.Stdout)
 | 
				
			||||||
 | 
							f.stderr.SetReader(out.Stderr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						f.mu.Unlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *Forwarder) SetIn(in *In) {
 | 
				
			||||||
 | 
						f.mu.Lock()
 | 
				
			||||||
 | 
						if in == nil {
 | 
				
			||||||
 | 
							f.stdin.SetReader(nil)
 | 
				
			||||||
 | 
							f.stdout.SetWriter(nil, func() io.WriteCloser { return nil })
 | 
				
			||||||
 | 
							f.stderr.SetWriter(nil, func() io.WriteCloser { return nil })
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							f.stdin.SetReader(in.Stdin)
 | 
				
			||||||
 | 
							f.stdout.SetWriter(in.Stdout, func() io.WriteCloser {
 | 
				
			||||||
 | 
								return in.Stdout // continue write; TODO: make it configurable if needed
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							f.stderr.SetWriter(in.Stderr, func() io.WriteCloser {
 | 
				
			||||||
 | 
								return in.Stderr // continue write; TODO: make it configurable if needed
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						f.mu.Unlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SingleForwarder forwards IO from a reader to a writer.
 | 
				
			||||||
 | 
					// The reader and writer can be changed during forwarding
 | 
				
			||||||
 | 
					// using SetReader and SetWriter methods.
 | 
				
			||||||
 | 
					type SingleForwarder struct {
 | 
				
			||||||
 | 
						curR           io.ReadCloser // closed when set another reader
 | 
				
			||||||
 | 
						curRMu         sync.Mutex
 | 
				
			||||||
 | 
						curW           io.WriteCloser // closed when set another writer
 | 
				
			||||||
 | 
						curWEOFHandler func() io.WriteCloser
 | 
				
			||||||
 | 
						curWMu         sync.Mutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						updateRCh chan io.ReadCloser
 | 
				
			||||||
 | 
						doneCh    chan struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						closeOnce sync.Once
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewSingleForwarder() *SingleForwarder {
 | 
				
			||||||
 | 
						f := &SingleForwarder{
 | 
				
			||||||
 | 
							updateRCh: make(chan io.ReadCloser),
 | 
				
			||||||
 | 
							doneCh:    make(chan struct{}),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						go f.doForward()
 | 
				
			||||||
 | 
						return f
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *SingleForwarder) doForward() {
 | 
				
			||||||
 | 
						var r io.ReadCloser
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							readerInvalid := false
 | 
				
			||||||
 | 
							if r != nil {
 | 
				
			||||||
 | 
								go func() {
 | 
				
			||||||
 | 
									buf := make([]byte, 4096)
 | 
				
			||||||
 | 
									for {
 | 
				
			||||||
 | 
										n, readErr := r.Read(buf)
 | 
				
			||||||
 | 
										if readErr != nil && !errors.Is(readErr, io.EOF) && !errors.Is(readErr, io.ErrClosedPipe) {
 | 
				
			||||||
 | 
											logrus.Debugf("single forwarder: reader error: %v", readErr)
 | 
				
			||||||
 | 
											return
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										f.curWMu.Lock()
 | 
				
			||||||
 | 
										w := f.curW
 | 
				
			||||||
 | 
										f.curWMu.Unlock()
 | 
				
			||||||
 | 
										if w != nil {
 | 
				
			||||||
 | 
											if _, err := w.Write(buf[:n]); err != nil && !errors.Is(err, io.ErrClosedPipe) {
 | 
				
			||||||
 | 
												logrus.Debugf("single forwarder: writer error: %v", err)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										if readerInvalid {
 | 
				
			||||||
 | 
											return
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										if readErr != io.EOF {
 | 
				
			||||||
 | 
											continue
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										f.curWMu.Lock()
 | 
				
			||||||
 | 
										var newW io.WriteCloser
 | 
				
			||||||
 | 
										if f.curWEOFHandler != nil {
 | 
				
			||||||
 | 
											newW = f.curWEOFHandler()
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										f.curW = newW
 | 
				
			||||||
 | 
										f.curWMu.Unlock()
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case newR := <-f.updateRCh:
 | 
				
			||||||
 | 
								f.curRMu.Lock()
 | 
				
			||||||
 | 
								if f.curR != nil {
 | 
				
			||||||
 | 
									f.curR.Close()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								f.curR = newR
 | 
				
			||||||
 | 
								r = newR
 | 
				
			||||||
 | 
								readerInvalid = true
 | 
				
			||||||
 | 
								f.curRMu.Unlock()
 | 
				
			||||||
 | 
							case <-f.doneCh:
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Close closes the both of registered reader and writer and finishes the forwarder.
 | 
				
			||||||
 | 
					func (f *SingleForwarder) Close() (retErr error) {
 | 
				
			||||||
 | 
						f.closeOnce.Do(func() {
 | 
				
			||||||
 | 
							f.curRMu.Lock()
 | 
				
			||||||
 | 
							r := f.curR
 | 
				
			||||||
 | 
							f.curR = nil
 | 
				
			||||||
 | 
							f.curRMu.Unlock()
 | 
				
			||||||
 | 
							if r != nil {
 | 
				
			||||||
 | 
								if err := r.Close(); err != nil {
 | 
				
			||||||
 | 
									retErr = err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// TODO: Wait until read data fully written to the current writer if needed.
 | 
				
			||||||
 | 
							f.curWMu.Lock()
 | 
				
			||||||
 | 
							w := f.curW
 | 
				
			||||||
 | 
							f.curW = nil
 | 
				
			||||||
 | 
							f.curWMu.Unlock()
 | 
				
			||||||
 | 
							if w != nil {
 | 
				
			||||||
 | 
								if err := w.Close(); err != nil {
 | 
				
			||||||
 | 
									retErr = err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							close(f.doneCh)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return retErr
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetWriter sets the specified writer as the forward destination.
 | 
				
			||||||
 | 
					// If curWEOFHandler isn't nil, this will be called when the current reader returns EOF.
 | 
				
			||||||
 | 
					func (f *SingleForwarder) SetWriter(w io.WriteCloser, curWEOFHandler func() io.WriteCloser) {
 | 
				
			||||||
 | 
						f.curWMu.Lock()
 | 
				
			||||||
 | 
						if f.curW != nil {
 | 
				
			||||||
 | 
							// close all stream on the current IO no to mix with the new IO
 | 
				
			||||||
 | 
							f.curW.Close()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						f.curW = w
 | 
				
			||||||
 | 
						f.curWEOFHandler = curWEOFHandler
 | 
				
			||||||
 | 
						f.curWMu.Unlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetWriter sets the specified reader as the forward source.
 | 
				
			||||||
 | 
					func (f *SingleForwarder) SetReader(r io.ReadCloser) {
 | 
				
			||||||
 | 
						f.updateRCh <- r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,236 @@
 | 
				
			|||||||
 | 
					package ioset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bufio"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/pkg/errors"
 | 
				
			||||||
 | 
						"github.com/sirupsen/logrus"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type MuxOut struct {
 | 
				
			||||||
 | 
						Out
 | 
				
			||||||
 | 
						EnableHook  func()
 | 
				
			||||||
 | 
						DisableHook func()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewMuxIO forwards IO stream to/from "in" and "outs".
 | 
				
			||||||
 | 
					// It toggles IO when it detects "C-a-c" key.
 | 
				
			||||||
 | 
					// "outs" are closed automatically when "in" reaches EOF.
 | 
				
			||||||
 | 
					// "in" doesn't closed automatically so the caller needs to explicitly close it.
 | 
				
			||||||
 | 
					func NewMuxIO(in In, outs []MuxOut, initIdx int, toggleMessage func(prev int, res int) string) *MuxIO {
 | 
				
			||||||
 | 
						m := &MuxIO{
 | 
				
			||||||
 | 
							enabled:       make(map[int]struct{}),
 | 
				
			||||||
 | 
							in:            in,
 | 
				
			||||||
 | 
							outs:          outs,
 | 
				
			||||||
 | 
							closedCh:      make(chan struct{}),
 | 
				
			||||||
 | 
							toggleMessage: toggleMessage,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i := range outs {
 | 
				
			||||||
 | 
							m.enabled[i] = struct{}{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m.maxCur = len(outs)
 | 
				
			||||||
 | 
						m.cur = initIdx
 | 
				
			||||||
 | 
						var wg sync.WaitGroup
 | 
				
			||||||
 | 
						var mu sync.Mutex
 | 
				
			||||||
 | 
						for i, o := range outs {
 | 
				
			||||||
 | 
							i, o := i, o
 | 
				
			||||||
 | 
							wg.Add(1)
 | 
				
			||||||
 | 
							go func() {
 | 
				
			||||||
 | 
								defer wg.Done()
 | 
				
			||||||
 | 
								if err := copyToFunc(o.Stdout, func() (io.Writer, error) {
 | 
				
			||||||
 | 
									if m.cur == i {
 | 
				
			||||||
 | 
										return in.Stdout, nil
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return nil, nil
 | 
				
			||||||
 | 
								}); err != nil {
 | 
				
			||||||
 | 
									logrus.WithField("output index", i).WithError(err).Warnf("failed to write stdout")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err := o.Stdout.Close(); err != nil {
 | 
				
			||||||
 | 
									logrus.WithField("output index", i).WithError(err).Warnf("failed to close stdout")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
							wg.Add(1)
 | 
				
			||||||
 | 
							go func() {
 | 
				
			||||||
 | 
								defer wg.Done()
 | 
				
			||||||
 | 
								if err := copyToFunc(o.Stderr, func() (io.Writer, error) {
 | 
				
			||||||
 | 
									if m.cur == i {
 | 
				
			||||||
 | 
										return in.Stderr, nil
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return nil, nil
 | 
				
			||||||
 | 
								}); err != nil {
 | 
				
			||||||
 | 
									logrus.WithField("output index", i).WithError(err).Warnf("failed to write stderr")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err := o.Stderr.Close(); err != nil {
 | 
				
			||||||
 | 
									logrus.WithField("output index", i).WithError(err).Warnf("failed to close stderr")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							errToggle := errors.Errorf("toggle IO")
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								prevIsControlSequence := false
 | 
				
			||||||
 | 
								if err := copyToFunc(traceReader(in.Stdin, func(r rune) (bool, error) {
 | 
				
			||||||
 | 
									// Toggle IO when it detects C-a-c
 | 
				
			||||||
 | 
									// TODO: make it configurable if needed
 | 
				
			||||||
 | 
									if int(r) == 1 {
 | 
				
			||||||
 | 
										prevIsControlSequence = true
 | 
				
			||||||
 | 
										return false, nil
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									defer func() { prevIsControlSequence = false }()
 | 
				
			||||||
 | 
									if prevIsControlSequence {
 | 
				
			||||||
 | 
										if string(r) == "c" {
 | 
				
			||||||
 | 
											return false, errToggle
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return true, nil
 | 
				
			||||||
 | 
								}), func() (io.Writer, error) {
 | 
				
			||||||
 | 
									mu.Lock()
 | 
				
			||||||
 | 
									o := outs[m.cur]
 | 
				
			||||||
 | 
									mu.Unlock()
 | 
				
			||||||
 | 
									return o.Stdin, nil
 | 
				
			||||||
 | 
								}); !errors.Is(err, errToggle) {
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										logrus.WithError(err).Warnf("failed to read stdin")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								m.toggleIO()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// propagate stdin EOF
 | 
				
			||||||
 | 
							for i, o := range outs {
 | 
				
			||||||
 | 
								if err := o.Stdin.Close(); err != nil {
 | 
				
			||||||
 | 
									logrus.WithError(err).Warnf("failed to close stdin of %d", i)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							wg.Wait()
 | 
				
			||||||
 | 
							close(m.closedCh)
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						return m
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type MuxIO struct {
 | 
				
			||||||
 | 
						cur           int
 | 
				
			||||||
 | 
						maxCur        int
 | 
				
			||||||
 | 
						enabled       map[int]struct{}
 | 
				
			||||||
 | 
						mu            sync.Mutex
 | 
				
			||||||
 | 
						in            In
 | 
				
			||||||
 | 
						outs          []MuxOut
 | 
				
			||||||
 | 
						closedCh      chan struct{}
 | 
				
			||||||
 | 
						toggleMessage func(prev int, res int) string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *MuxIO) waitClosed() {
 | 
				
			||||||
 | 
						<-m.closedCh
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *MuxIO) Enable(i int) {
 | 
				
			||||||
 | 
						m.mu.Lock()
 | 
				
			||||||
 | 
						defer m.mu.Unlock()
 | 
				
			||||||
 | 
						m.enabled[i] = struct{}{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *MuxIO) Disable(i int) error {
 | 
				
			||||||
 | 
						m.mu.Lock()
 | 
				
			||||||
 | 
						defer m.mu.Unlock()
 | 
				
			||||||
 | 
						if i == 0 {
 | 
				
			||||||
 | 
							return errors.Errorf("disabling 0th io is prohibited")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						delete(m.enabled, i)
 | 
				
			||||||
 | 
						if m.cur == i {
 | 
				
			||||||
 | 
							m.toggleIO()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *MuxIO) toggleIO() {
 | 
				
			||||||
 | 
						if m.outs[m.cur].DisableHook != nil {
 | 
				
			||||||
 | 
							m.outs[m.cur].DisableHook()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						prev := m.cur
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							if m.cur+1 >= m.maxCur {
 | 
				
			||||||
 | 
								m.cur = 0
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								m.cur++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if _, ok := m.enabled[m.cur]; !ok {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						res := m.cur
 | 
				
			||||||
 | 
						if m.outs[m.cur].EnableHook != nil {
 | 
				
			||||||
 | 
							m.outs[m.cur].EnableHook()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fmt.Fprint(m.in.Stdout, m.toggleMessage(prev, res))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func traceReader(r io.ReadCloser, f func(rune) (bool, error)) io.ReadCloser {
 | 
				
			||||||
 | 
						pr, pw := io.Pipe()
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							br := bufio.NewReader(r)
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								rn, _, err := br.ReadRune()
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									if err == io.EOF {
 | 
				
			||||||
 | 
										pw.Close()
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									pw.CloseWithError(err)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if isWrite, err := f(rn); err != nil {
 | 
				
			||||||
 | 
									pw.CloseWithError(err)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								} else if !isWrite {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if _, err := pw.Write([]byte(string(rn))); err != nil {
 | 
				
			||||||
 | 
									pw.CloseWithError(err)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						return &readerWithClose{
 | 
				
			||||||
 | 
							Reader: pr,
 | 
				
			||||||
 | 
							closeFunc: func() error {
 | 
				
			||||||
 | 
								pr.Close()
 | 
				
			||||||
 | 
								return r.Close()
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func copyToFunc(r io.Reader, wFunc func() (io.Writer, error)) error {
 | 
				
			||||||
 | 
						buf := make([]byte, 4096)
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							n, readErr := r.Read(buf)
 | 
				
			||||||
 | 
							if readErr != nil && readErr != io.EOF {
 | 
				
			||||||
 | 
								return readErr
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							w, err := wFunc()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if w != nil {
 | 
				
			||||||
 | 
								if _, err := w.Write(buf[:n]); err != nil {
 | 
				
			||||||
 | 
									logrus.WithError(err).Debugf("failed to copy")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if readErr == io.EOF {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type readerWithClose struct {
 | 
				
			||||||
 | 
						io.Reader
 | 
				
			||||||
 | 
						closeFunc func() error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *readerWithClose) Close() error {
 | 
				
			||||||
 | 
						return r.closeFunc()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					   Copyright The containerd Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					   you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					   You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					   distributed under the License 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 dialer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type dialResult struct {
 | 
				
			||||||
 | 
						c   net.Conn
 | 
				
			||||||
 | 
						err error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ContextDialer returns a GRPC net.Conn connected to the provided address
 | 
				
			||||||
 | 
					func ContextDialer(ctx context.Context, address string) (net.Conn, error) {
 | 
				
			||||||
 | 
						if deadline, ok := ctx.Deadline(); ok {
 | 
				
			||||||
 | 
							return timeoutDialer(address, time.Until(deadline))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return timeoutDialer(address, 0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Dialer returns a GRPC net.Conn connected to the provided address
 | 
				
			||||||
 | 
					// Deprecated: use ContextDialer and grpc.WithContextDialer.
 | 
				
			||||||
 | 
					var Dialer = timeoutDialer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func timeoutDialer(address string, timeout time.Duration) (net.Conn, error) {
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							stopC = make(chan struct{})
 | 
				
			||||||
 | 
							synC  = make(chan *dialResult)
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							defer close(synC)
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								select {
 | 
				
			||||||
 | 
								case <-stopC:
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									c, err := dialer(address, timeout)
 | 
				
			||||||
 | 
									if isNoent(err) {
 | 
				
			||||||
 | 
										<-time.After(10 * time.Millisecond)
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									synC <- &dialResult{c, err}
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						select {
 | 
				
			||||||
 | 
						case dr := <-synC:
 | 
				
			||||||
 | 
							return dr.c, dr.err
 | 
				
			||||||
 | 
						case <-time.After(timeout):
 | 
				
			||||||
 | 
							close(stopC)
 | 
				
			||||||
 | 
							go func() {
 | 
				
			||||||
 | 
								dr := <-synC
 | 
				
			||||||
 | 
								if dr != nil && dr.c != nil {
 | 
				
			||||||
 | 
									dr.c.Close()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("dial %s: timeout", address)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					//go:build !windows
 | 
				
			||||||
 | 
					// +build !windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					   Copyright The containerd Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					   you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					   You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					   distributed under the License 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 dialer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DialAddress returns the address with unix:// prepended to the
 | 
				
			||||||
 | 
					// provided address
 | 
				
			||||||
 | 
					func DialAddress(address string) string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("unix://%s", address)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func isNoent(err error) bool {
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if nerr, ok := err.(*net.OpError); ok {
 | 
				
			||||||
 | 
								if serr, ok := nerr.Err.(*os.SyscallError); ok {
 | 
				
			||||||
 | 
									if serr.Err == syscall.ENOENT {
 | 
				
			||||||
 | 
										return true
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func dialer(address string, timeout time.Duration) (net.Conn, error) {
 | 
				
			||||||
 | 
						address = strings.TrimPrefix(address, "unix://")
 | 
				
			||||||
 | 
						return net.DialTimeout("unix", address, timeout)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					   Copyright The containerd Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					   you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					   You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					   distributed under the License 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 dialer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						winio "github.com/Microsoft/go-winio"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func isNoent(err error) bool {
 | 
				
			||||||
 | 
						return os.IsNotExist(err)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func dialer(address string, timeout time.Duration) (net.Conn, error) {
 | 
				
			||||||
 | 
						return winio.DialPipe(address, &timeout)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DialAddress returns the dial address
 | 
				
			||||||
 | 
					func DialAddress(address string) string {
 | 
				
			||||||
 | 
						return address
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,580 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package compare
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/vanity"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type plugin struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
						generator.PluginImports
 | 
				
			||||||
 | 
						fmtPkg      generator.Single
 | 
				
			||||||
 | 
						bytesPkg    generator.Single
 | 
				
			||||||
 | 
						sortkeysPkg generator.Single
 | 
				
			||||||
 | 
						protoPkg    generator.Single
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewPlugin() *plugin {
 | 
				
			||||||
 | 
						return &plugin{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Name() string {
 | 
				
			||||||
 | 
						return "compare"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						p.PluginImports = generator.NewPluginImports(p.Generator)
 | 
				
			||||||
 | 
						p.fmtPkg = p.NewImport("fmt")
 | 
				
			||||||
 | 
						p.bytesPkg = p.NewImport("bytes")
 | 
				
			||||||
 | 
						p.sortkeysPkg = p.NewImport("github.com/gogo/protobuf/sortkeys")
 | 
				
			||||||
 | 
						p.protoPkg = p.NewImport("github.com/gogo/protobuf/proto")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, msg := range file.Messages() {
 | 
				
			||||||
 | 
							if msg.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if gogoproto.HasCompare(file.FileDescriptorProto, msg.DescriptorProto) {
 | 
				
			||||||
 | 
								p.generateMessage(file, msg)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) generateNullableField(fieldname string) {
 | 
				
			||||||
 | 
						p.P(`if this.`, fieldname, ` != nil && that1.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`if *this.`, fieldname, ` != *that1.`, fieldname, `{`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`if *this.`, fieldname, ` < *that1.`, fieldname, `{`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`return -1`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(`return 1`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`} else if this.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`return 1`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`} else if that1.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`return -1`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) generateMsgNullAndTypeCheck(ccTypeName string) {
 | 
				
			||||||
 | 
						p.P(`if that == nil {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`if this == nil {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`return 0`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(`return 1`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(``)
 | 
				
			||||||
 | 
						p.P(`that1, ok := that.(*`, ccTypeName, `)`)
 | 
				
			||||||
 | 
						p.P(`if !ok {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`that2, ok := that.(`, ccTypeName, `)`)
 | 
				
			||||||
 | 
						p.P(`if ok {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`that1 = &that2`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`} else {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`return 1`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(`if that1 == nil {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`if this == nil {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`return 0`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(`return 1`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`} else if this == nil {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`return -1`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) generateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
 | 
				
			||||||
 | 
						proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
 | 
				
			||||||
 | 
						fieldname := p.GetOneOfFieldName(message, field)
 | 
				
			||||||
 | 
						repeated := field.IsRepeated()
 | 
				
			||||||
 | 
						ctype := gogoproto.IsCustomType(field)
 | 
				
			||||||
 | 
						nullable := gogoproto.IsNullable(field)
 | 
				
			||||||
 | 
						// oneof := field.OneofIndex != nil
 | 
				
			||||||
 | 
						if !repeated {
 | 
				
			||||||
 | 
							if ctype {
 | 
				
			||||||
 | 
								if nullable {
 | 
				
			||||||
 | 
									p.P(`if that1.`, fieldname, ` == nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`return 1`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`} else if this.`, fieldname, ` == nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`return -1`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`} else if c := this.`, fieldname, `.Compare(*that1.`, fieldname, `); c != 0 {`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return c`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if field.IsMessage() || p.IsGroup(field) {
 | 
				
			||||||
 | 
									if nullable {
 | 
				
			||||||
 | 
										p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`if c := this.`, fieldname, `.Compare(&that1.`, fieldname, `); c != 0 {`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`return c`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else if field.IsBytes() {
 | 
				
			||||||
 | 
									p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`return c`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else if field.IsString() {
 | 
				
			||||||
 | 
									if nullable && !proto3 {
 | 
				
			||||||
 | 
										p.generateNullableField(fieldname)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, ` < that1.`, fieldname, `{`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`return -1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
										p.P(`return 1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if field.IsBool() {
 | 
				
			||||||
 | 
									if nullable && !proto3 {
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, ` != nil && that1.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`if *this.`, fieldname, ` != *that1.`, fieldname, `{`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`if !*this.`, fieldname, ` {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`return -1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
										p.P(`return 1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`} else if this.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`return 1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`} else if that1.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`return -1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`if !this.`, fieldname, ` {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`return -1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
										p.P(`return 1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									if nullable && !proto3 {
 | 
				
			||||||
 | 
										p.generateNullableField(fieldname)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, ` < that1.`, fieldname, `{`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`return -1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
										p.P(`return 1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							p.P(`if len(this.`, fieldname, `) != len(that1.`, fieldname, `) {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`if len(this.`, fieldname, `) < len(that1.`, fieldname, `) {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`return -1`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(`return 1`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(`for i := range this.`, fieldname, ` {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							if ctype {
 | 
				
			||||||
 | 
								p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return c`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if p.IsMap(field) {
 | 
				
			||||||
 | 
									m := p.GoMapType(nil, field)
 | 
				
			||||||
 | 
									valuegoTyp, _ := p.GoType(nil, m.ValueField)
 | 
				
			||||||
 | 
									valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
 | 
				
			||||||
 | 
									nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									mapValue := m.ValueAliasField
 | 
				
			||||||
 | 
									if mapValue.IsMessage() || p.IsGroup(mapValue) {
 | 
				
			||||||
 | 
										if nullable && valuegoTyp == valuegoAliasTyp {
 | 
				
			||||||
 | 
											p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											// Compare() has a pointer receiver, but map value is a value type
 | 
				
			||||||
 | 
											a := `this.` + fieldname + `[i]`
 | 
				
			||||||
 | 
											b := `that1.` + fieldname + `[i]`
 | 
				
			||||||
 | 
											if valuegoTyp != valuegoAliasTyp {
 | 
				
			||||||
 | 
												// cast back to the type that has the generated methods on it
 | 
				
			||||||
 | 
												a = `(` + valuegoTyp + `)(` + a + `)`
 | 
				
			||||||
 | 
												b = `(` + valuegoTyp + `)(` + b + `)`
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											p.P(`a := `, a)
 | 
				
			||||||
 | 
											p.P(`b := `, b)
 | 
				
			||||||
 | 
											if nullable {
 | 
				
			||||||
 | 
												p.P(`if c := a.Compare(b); c != 0 {`)
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												p.P(`if c := (&a).Compare(&b); c != 0 {`)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`return c`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									} else if mapValue.IsBytes() {
 | 
				
			||||||
 | 
										p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `[i], that1.`, fieldname, `[i]); c != 0 {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`return c`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									} else if mapValue.IsString() {
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`return -1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
										p.P(`return 1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`return -1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
										p.P(`return 1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if field.IsMessage() || p.IsGroup(field) {
 | 
				
			||||||
 | 
									if nullable {
 | 
				
			||||||
 | 
										p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`return c`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`if c := this.`, fieldname, `[i].Compare(&that1.`, fieldname, `[i]); c != 0 {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`return c`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if field.IsBytes() {
 | 
				
			||||||
 | 
									p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `[i], that1.`, fieldname, `[i]); c != 0 {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`return c`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else if field.IsString() {
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`return -1`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.P(`return 1`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else if field.IsBool() {
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`if !this.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`return -1`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.P(`return 1`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`return -1`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.P(`return 1`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) generateMessage(file *generator.FileDescriptor, message *generator.Descriptor) {
 | 
				
			||||||
 | 
						ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
						p.P(`func (this *`, ccTypeName, `) Compare(that interface{}) int {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.generateMsgNullAndTypeCheck(ccTypeName)
 | 
				
			||||||
 | 
						oneofs := make(map[string]struct{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, field := range message.Field {
 | 
				
			||||||
 | 
							oneof := field.OneofIndex != nil
 | 
				
			||||||
 | 
							if oneof {
 | 
				
			||||||
 | 
								fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
								if _, ok := oneofs[fieldname]; ok {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									oneofs[fieldname] = struct{}{}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`if that1.`, fieldname, ` == nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`if this.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return 1`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`} else if this.`, fieldname, ` == nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return -1`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`} else {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Generate two type switches in order to compare the
 | 
				
			||||||
 | 
								// types of the oneofs. If they are of the same type
 | 
				
			||||||
 | 
								// call Compare, otherwise return 1 or -1.
 | 
				
			||||||
 | 
								p.P(`thisType := -1`)
 | 
				
			||||||
 | 
								p.P(`switch this.`, fieldname, `.(type) {`)
 | 
				
			||||||
 | 
								for i, subfield := range message.Field {
 | 
				
			||||||
 | 
									if *subfield.OneofIndex == *field.OneofIndex {
 | 
				
			||||||
 | 
										ccTypeName := p.OneOfTypeName(message, subfield)
 | 
				
			||||||
 | 
										p.P(`case *`, ccTypeName, `:`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`thisType = `, i)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`default:`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`panic(fmt.Sprintf("compare: unexpected type %T in oneof", this.`, fieldname, `))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								p.P(`that1Type := -1`)
 | 
				
			||||||
 | 
								p.P(`switch that1.`, fieldname, `.(type) {`)
 | 
				
			||||||
 | 
								for i, subfield := range message.Field {
 | 
				
			||||||
 | 
									if *subfield.OneofIndex == *field.OneofIndex {
 | 
				
			||||||
 | 
										ccTypeName := p.OneOfTypeName(message, subfield)
 | 
				
			||||||
 | 
										p.P(`case *`, ccTypeName, `:`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`that1Type = `, i)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`default:`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`panic(fmt.Sprintf("compare: unexpected type %T in oneof", that1.`, fieldname, `))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								p.P(`if thisType == that1Type {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return c`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`} else if thisType < that1Type {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return -1`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`} else if thisType > that1Type {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return 1`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.generateField(file, message, field)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if message.DescriptorProto.HasExtension() {
 | 
				
			||||||
 | 
							if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								p.P(`thismap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(this)`)
 | 
				
			||||||
 | 
								p.P(`thatmap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(that1)`)
 | 
				
			||||||
 | 
								p.P(`extkeys := make([]int32, 0, len(thismap)+len(thatmap))`)
 | 
				
			||||||
 | 
								p.P(`for k, _ := range thismap {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`extkeys = append(extkeys, k)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`for k, _ := range thatmap {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`if _, ok := thismap[k]; !ok {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`extkeys = append(extkeys, k)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(p.sortkeysPkg.Use(), `.Int32s(extkeys)`)
 | 
				
			||||||
 | 
								p.P(`for _, k := range extkeys {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`if v, ok := thismap[k]; ok {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`if v2, ok := thatmap[k]; ok {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`if c := v.Compare(&v2); c != 0 {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return c`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`} else  {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return 1`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`} else {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return -1`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								fieldname := "XXX_extensions"
 | 
				
			||||||
 | 
								p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return c`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
							fieldname := "XXX_unrecognized"
 | 
				
			||||||
 | 
							p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`return c`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p.P(`return 0`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//Generate Compare methods for oneof fields
 | 
				
			||||||
 | 
						m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
 | 
				
			||||||
 | 
						for _, field := range m.Field {
 | 
				
			||||||
 | 
							oneof := field.OneofIndex != nil
 | 
				
			||||||
 | 
							if !oneof {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ccTypeName := p.OneOfTypeName(message, field)
 | 
				
			||||||
 | 
							p.P(`func (this *`, ccTypeName, `) Compare(that interface{}) int {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p.generateMsgNullAndTypeCheck(ccTypeName)
 | 
				
			||||||
 | 
							vanity.TurnOffNullableForNativeTypes(field)
 | 
				
			||||||
 | 
							p.generateField(file, message, field)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p.P(`return 0`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(NewPlugin())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,118 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package compare
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/plugin/testgen"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type test struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewTest(g *generator.Generator) testgen.TestPlugin {
 | 
				
			||||||
 | 
						return &test{g}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
 | 
				
			||||||
 | 
						used := false
 | 
				
			||||||
 | 
						randPkg := imports.NewImport("math/rand")
 | 
				
			||||||
 | 
						timePkg := imports.NewImport("time")
 | 
				
			||||||
 | 
						testingPkg := imports.NewImport("testing")
 | 
				
			||||||
 | 
						protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
 | 
				
			||||||
 | 
						unsafePkg := imports.NewImport("unsafe")
 | 
				
			||||||
 | 
						if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
 | 
				
			||||||
 | 
							protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							if !gogoproto.HasCompare(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								used = true
 | 
				
			||||||
 | 
								hasUnsafe := gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) ||
 | 
				
			||||||
 | 
									gogoproto.IsUnsafeUnmarshaler(file.FileDescriptorProto, message.DescriptorProto)
 | 
				
			||||||
 | 
								p.P(`func Test`, ccTypeName, `Compare(t *`, testingPkg.Use(), `.T) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if hasUnsafe {
 | 
				
			||||||
 | 
									p.P(`var bigendian uint32 = 0x01020304`)
 | 
				
			||||||
 | 
									p.P(`if *(*byte)(`, unsafePkg.Use(), `.Pointer(&bigendian)) == 1 {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`t.Skip("unsafe does not work on big endian architectures")`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
 | 
				
			||||||
 | 
								p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
 | 
				
			||||||
 | 
								p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
 | 
				
			||||||
 | 
								p.P(`if err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`panic(err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`msg := &`, ccTypeName, `{}`)
 | 
				
			||||||
 | 
								p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`panic(err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`if c := p.Compare(msg); c != 0 {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("%#v !Compare %#v, since %d", msg, p, c)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`p2 := NewPopulated`, ccTypeName, `(popr, false)`)
 | 
				
			||||||
 | 
								p.P(`c := p.Compare(p2)`)
 | 
				
			||||||
 | 
								p.P(`c2 := p2.Compare(p)`)
 | 
				
			||||||
 | 
								p.P(`if c != (-1 * c2) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Errorf("p.Compare(p2) = %d", c)`)
 | 
				
			||||||
 | 
								p.P(`t.Errorf("p2.Compare(p) = %d", c2)`)
 | 
				
			||||||
 | 
								p.P(`t.Errorf("p = %#v", p)`)
 | 
				
			||||||
 | 
								p.P(`t.Errorf("p2 = %#v", p2)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return used
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						testgen.RegisterTestPlugin(NewTest)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,133 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					The defaultcheck plugin is used to check whether nullable is not used incorrectly.
 | 
				
			||||||
 | 
					For instance:
 | 
				
			||||||
 | 
					An error is caused if a nullable field:
 | 
				
			||||||
 | 
					  - has a default value,
 | 
				
			||||||
 | 
					  - is an enum which does not start at zero,
 | 
				
			||||||
 | 
					  - is used for an extension,
 | 
				
			||||||
 | 
					  - is used for a native proto3 type,
 | 
				
			||||||
 | 
					  - is used for a repeated native type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					An error is also caused if a field with a default value is used in a message:
 | 
				
			||||||
 | 
					  - which is a face.
 | 
				
			||||||
 | 
					  - without getters.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is enabled by the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - nullable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For incorrect usage of nullable with tests see:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/nullableconflict
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package defaultcheck
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type plugin struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewPlugin() *plugin {
 | 
				
			||||||
 | 
						return &plugin{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Name() string {
 | 
				
			||||||
 | 
						return "defaultcheck"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
 | 
				
			||||||
 | 
						for _, msg := range file.Messages() {
 | 
				
			||||||
 | 
							getters := gogoproto.HasGoGetters(file.FileDescriptorProto, msg.DescriptorProto)
 | 
				
			||||||
 | 
							face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto)
 | 
				
			||||||
 | 
							for _, field := range msg.GetField() {
 | 
				
			||||||
 | 
								if len(field.GetDefaultValue()) > 0 {
 | 
				
			||||||
 | 
									if !getters {
 | 
				
			||||||
 | 
										fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value and not have a getter method", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
 | 
				
			||||||
 | 
										os.Exit(1)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if face {
 | 
				
			||||||
 | 
										fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value be in a face", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
 | 
				
			||||||
 | 
										os.Exit(1)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if gogoproto.IsNullable(field) {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if len(field.GetDefaultValue()) > 0 {
 | 
				
			||||||
 | 
									fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and have a default value", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
 | 
				
			||||||
 | 
									os.Exit(1)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if !field.IsMessage() && !gogoproto.IsCustomType(field) {
 | 
				
			||||||
 | 
									if field.IsRepeated() {
 | 
				
			||||||
 | 
										fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a repeated non-nullable native type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
 | 
				
			||||||
 | 
									} else if proto3 {
 | 
				
			||||||
 | 
										fmt.Fprintf(os.Stderr, "ERROR: field %v.%v is a native type and in proto3 syntax with nullable=false there exists conflicting implementations when encoding zero values", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
 | 
				
			||||||
 | 
										os.Exit(1)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if field.IsBytes() {
 | 
				
			||||||
 | 
										fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a non-nullable bytes type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if !field.IsEnum() {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								enum := p.ObjectNamed(field.GetTypeName()).(*generator.EnumDescriptor)
 | 
				
			||||||
 | 
								if len(enum.Value) == 0 || enum.Value[0].GetNumber() != 0 {
 | 
				
			||||||
 | 
									fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and be an enum type %v which does not start with zero", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name), enum.GetName())
 | 
				
			||||||
 | 
									os.Exit(1)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, e := range file.GetExtension() {
 | 
				
			||||||
 | 
							if !gogoproto.IsNullable(e) {
 | 
				
			||||||
 | 
								fmt.Fprintf(os.Stderr, "ERROR: extended field %v cannot be nullable %v", generator.CamelCase(e.GetName()), generator.CamelCase(*e.Name))
 | 
				
			||||||
 | 
								os.Exit(1)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) GenerateImports(*generator.FileDescriptor) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(NewPlugin())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,201 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					The description (experimental) plugin generates a Description method for each message.
 | 
				
			||||||
 | 
					The Description method returns a populated google_protobuf.FileDescriptorSet struct.
 | 
				
			||||||
 | 
					This contains the description of the files used to generate this message.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is enabled by the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - description
 | 
				
			||||||
 | 
					  - description_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The description plugin also generates a test given it is enabled using one of the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - testgen
 | 
				
			||||||
 | 
					  - testgen_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let us look at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/example.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Btw all the output can be seen at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following message:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  message B {
 | 
				
			||||||
 | 
						option (gogoproto.description) = true;
 | 
				
			||||||
 | 
						optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
 | 
				
			||||||
 | 
						repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					given to the description plugin, will generate the following code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  func (this *B) Description() (desc *google_protobuf.FileDescriptorSet) {
 | 
				
			||||||
 | 
						return ExampleDescription()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and the following test code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  func TestDescription(t *testing9.T) {
 | 
				
			||||||
 | 
						ExampleDescription()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The hope is to use this struct in some way instead of reflect.
 | 
				
			||||||
 | 
					This package is subject to change, since a use has not been figured out yet.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package description
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"compress/gzip"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type plugin struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
						generator.PluginImports
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewPlugin() *plugin {
 | 
				
			||||||
 | 
						return &plugin{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Name() string {
 | 
				
			||||||
 | 
						return "description"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						used := false
 | 
				
			||||||
 | 
						localName := generator.FileName(file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.PluginImports = generator.NewPluginImports(p.Generator)
 | 
				
			||||||
 | 
						descriptorPkg := p.NewImport("github.com/gogo/protobuf/protoc-gen-gogo/descriptor")
 | 
				
			||||||
 | 
						protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
 | 
				
			||||||
 | 
						gzipPkg := p.NewImport("compress/gzip")
 | 
				
			||||||
 | 
						bytesPkg := p.NewImport("bytes")
 | 
				
			||||||
 | 
						ioutilPkg := p.NewImport("io/ioutil")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							if !gogoproto.HasDescription(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							used = true
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							p.P(`func (this *`, ccTypeName, `) Description() (desc *`, descriptorPkg.Use(), `.FileDescriptorSet) {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`return `, localName, `Description()`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if used {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p.P(`func `, localName, `Description() (desc *`, descriptorPkg.Use(), `.FileDescriptorSet) {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							//Don't generate SourceCodeInfo, since it will create too much code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ss := make([]*descriptor.SourceCodeInfo, 0)
 | 
				
			||||||
 | 
							for _, f := range p.Generator.AllFiles().GetFile() {
 | 
				
			||||||
 | 
								ss = append(ss, f.SourceCodeInfo)
 | 
				
			||||||
 | 
								f.SourceCodeInfo = nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							b, err := proto.Marshal(p.Generator.AllFiles())
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for i, f := range p.Generator.AllFiles().GetFile() {
 | 
				
			||||||
 | 
								f.SourceCodeInfo = ss[i]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.P(`d := &`, descriptorPkg.Use(), `.FileDescriptorSet{}`)
 | 
				
			||||||
 | 
							var buf bytes.Buffer
 | 
				
			||||||
 | 
							w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression)
 | 
				
			||||||
 | 
							w.Write(b)
 | 
				
			||||||
 | 
							w.Close()
 | 
				
			||||||
 | 
							b = buf.Bytes()
 | 
				
			||||||
 | 
							p.P("var gzipped = []byte{")
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P("// ", len(b), " bytes of a gzipped FileDescriptorSet")
 | 
				
			||||||
 | 
							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)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								b = b[n:]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P("}")
 | 
				
			||||||
 | 
							p.P(`r := `, bytesPkg.Use(), `.NewReader(gzipped)`)
 | 
				
			||||||
 | 
							p.P(`gzipr, err := `, gzipPkg.Use(), `.NewReader(r)`)
 | 
				
			||||||
 | 
							p.P(`if err != nil {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`panic(err)`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(`ungzipped, err := `, ioutilPkg.Use(), `.ReadAll(gzipr)`)
 | 
				
			||||||
 | 
							p.P(`if err != nil {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`panic(err)`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(`if err := `, protoPkg.Use(), `.Unmarshal(ungzipped, d); err != nil {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`panic(err)`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(`return d`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(NewPlugin())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package description
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/plugin/testgen"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type test struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewTest(g *generator.Generator) testgen.TestPlugin {
 | 
				
			||||||
 | 
						return &test{g}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
 | 
				
			||||||
 | 
						used := false
 | 
				
			||||||
 | 
						testingPkg := imports.NewImport("testing")
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							if !gogoproto.HasDescription(file.FileDescriptorProto, message.DescriptorProto) ||
 | 
				
			||||||
 | 
								!gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							used = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if used {
 | 
				
			||||||
 | 
							localName := generator.FileName(file)
 | 
				
			||||||
 | 
							p.P(`func Test`, localName, `Description(t *`, testingPkg.Use(), `.T) {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(localName, `Description()`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return used
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						testgen.RegisterTestPlugin(NewTest)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,200 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					The embedcheck plugin is used to check whether embed is not used incorrectly.
 | 
				
			||||||
 | 
					For instance:
 | 
				
			||||||
 | 
					An embedded message has a generated string method, but the is a member of a message which does not.
 | 
				
			||||||
 | 
					This causes a warning.
 | 
				
			||||||
 | 
					An error is caused by a namespace conflict.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is enabled by the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - embed
 | 
				
			||||||
 | 
					  - embed_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For incorrect usage of embed with tests see:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/embedconflict
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package embedcheck
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type plugin struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewPlugin() *plugin {
 | 
				
			||||||
 | 
						return &plugin{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Name() string {
 | 
				
			||||||
 | 
						return "embedcheck"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var overwriters []map[string]gogoproto.EnableFunc = []map[string]gogoproto.EnableFunc{
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							"stringer": gogoproto.IsStringer,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							"gostring": gogoproto.HasGoString,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							"equal": gogoproto.HasEqual,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							"verboseequal": gogoproto.HasVerboseEqual,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							"size":       gogoproto.IsSizer,
 | 
				
			||||||
 | 
							"protosizer": gogoproto.IsProtoSizer,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							"unmarshaler":        gogoproto.IsUnmarshaler,
 | 
				
			||||||
 | 
							"unsafe_unmarshaler": gogoproto.IsUnsafeUnmarshaler,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							"marshaler":        gogoproto.IsMarshaler,
 | 
				
			||||||
 | 
							"unsafe_marshaler": gogoproto.IsUnsafeMarshaler,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						for _, msg := range file.Messages() {
 | 
				
			||||||
 | 
							for _, os := range overwriters {
 | 
				
			||||||
 | 
								possible := true
 | 
				
			||||||
 | 
								for _, overwriter := range os {
 | 
				
			||||||
 | 
									if overwriter(file.FileDescriptorProto, msg.DescriptorProto) {
 | 
				
			||||||
 | 
										possible = false
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if possible {
 | 
				
			||||||
 | 
									p.checkOverwrite(msg, os)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.checkNameSpace(msg)
 | 
				
			||||||
 | 
							for _, field := range msg.GetField() {
 | 
				
			||||||
 | 
								if gogoproto.IsEmbed(field) && gogoproto.IsCustomName(field) {
 | 
				
			||||||
 | 
									fmt.Fprintf(os.Stderr, "ERROR: field %v with custom name %v cannot be embedded", *field.Name, gogoproto.GetCustomName(field))
 | 
				
			||||||
 | 
									os.Exit(1)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.checkRepeated(msg)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, e := range file.GetExtension() {
 | 
				
			||||||
 | 
							if gogoproto.IsEmbed(e) {
 | 
				
			||||||
 | 
								fmt.Fprintf(os.Stderr, "ERROR: extended field %v cannot be embedded", generator.CamelCase(*e.Name))
 | 
				
			||||||
 | 
								os.Exit(1)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) checkNameSpace(message *generator.Descriptor) map[string]bool {
 | 
				
			||||||
 | 
						ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
						names := make(map[string]bool)
 | 
				
			||||||
 | 
						for _, field := range message.Field {
 | 
				
			||||||
 | 
							fieldname := generator.CamelCase(*field.Name)
 | 
				
			||||||
 | 
							if field.IsMessage() && gogoproto.IsEmbed(field) {
 | 
				
			||||||
 | 
								desc := p.ObjectNamed(field.GetTypeName())
 | 
				
			||||||
 | 
								moreNames := p.checkNameSpace(desc.(*generator.Descriptor))
 | 
				
			||||||
 | 
								for another := range moreNames {
 | 
				
			||||||
 | 
									if names[another] {
 | 
				
			||||||
 | 
										fmt.Fprintf(os.Stderr, "ERROR: duplicate embedded fieldname %v in type %v\n", fieldname, ccTypeName)
 | 
				
			||||||
 | 
										os.Exit(1)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									names[another] = true
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if names[fieldname] {
 | 
				
			||||||
 | 
									fmt.Fprintf(os.Stderr, "ERROR: duplicate embedded fieldname %v in type %v\n", fieldname, ccTypeName)
 | 
				
			||||||
 | 
									os.Exit(1)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								names[fieldname] = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return names
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) checkOverwrite(message *generator.Descriptor, enablers map[string]gogoproto.EnableFunc) {
 | 
				
			||||||
 | 
						ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
						names := []string{}
 | 
				
			||||||
 | 
						for name := range enablers {
 | 
				
			||||||
 | 
							names = append(names, name)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, field := range message.Field {
 | 
				
			||||||
 | 
							if field.IsMessage() && gogoproto.IsEmbed(field) {
 | 
				
			||||||
 | 
								fieldname := generator.CamelCase(*field.Name)
 | 
				
			||||||
 | 
								desc := p.ObjectNamed(field.GetTypeName())
 | 
				
			||||||
 | 
								msg := desc.(*generator.Descriptor)
 | 
				
			||||||
 | 
								for errStr, enabled := range enablers {
 | 
				
			||||||
 | 
									if enabled(msg.File().FileDescriptorProto, msg.DescriptorProto) {
 | 
				
			||||||
 | 
										fmt.Fprintf(os.Stderr, "WARNING: found non-%v %v with embedded %v %v\n", names, ccTypeName, errStr, fieldname)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.checkOverwrite(msg, enablers)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) checkRepeated(message *generator.Descriptor) {
 | 
				
			||||||
 | 
						ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
						for _, field := range message.Field {
 | 
				
			||||||
 | 
							if !gogoproto.IsEmbed(field) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if field.IsBytes() {
 | 
				
			||||||
 | 
								fieldname := generator.CamelCase(*field.Name)
 | 
				
			||||||
 | 
								fmt.Fprintf(os.Stderr, "ERROR: found embedded bytes field %s in message %s\n", fieldname, ccTypeName)
 | 
				
			||||||
 | 
								os.Exit(1)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !field.IsRepeated() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fieldname := generator.CamelCase(*field.Name)
 | 
				
			||||||
 | 
							fmt.Fprintf(os.Stderr, "ERROR: found repeated embedded field %s in message %s\n", fieldname, ccTypeName)
 | 
				
			||||||
 | 
							os.Exit(1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) GenerateImports(*generator.FileDescriptor) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(NewPlugin())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,104 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					The enumstringer (experimental) plugin generates a String method for each enum.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is enabled by the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - enum_stringer
 | 
				
			||||||
 | 
					  - enum_stringer_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This package is subject to change.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package enumstringer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type enumstringer struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
						generator.PluginImports
 | 
				
			||||||
 | 
						atleastOne bool
 | 
				
			||||||
 | 
						localName  string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewEnumStringer() *enumstringer {
 | 
				
			||||||
 | 
						return &enumstringer{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *enumstringer) Name() string {
 | 
				
			||||||
 | 
						return "enumstringer"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *enumstringer) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *enumstringer) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						p.PluginImports = generator.NewPluginImports(p.Generator)
 | 
				
			||||||
 | 
						p.atleastOne = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.localName = generator.FileName(file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						strconvPkg := p.NewImport("strconv")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, enum := range file.Enums() {
 | 
				
			||||||
 | 
							if !gogoproto.IsEnumStringer(file.FileDescriptorProto, enum.EnumDescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if gogoproto.IsGoEnumStringer(file.FileDescriptorProto, enum.EnumDescriptorProto) {
 | 
				
			||||||
 | 
								panic("Go enum stringer conflicts with new enumstringer plugin: please use gogoproto.goproto_enum_stringer or gogoproto.goproto_enum_string_all and set it to false")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.atleastOne = true
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(enum.TypeName())
 | 
				
			||||||
 | 
							p.P("func (x ", ccTypeName, ") String() string {")
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`s, ok := `, ccTypeName, `_name[int32(x)]`)
 | 
				
			||||||
 | 
							p.P(`if ok {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`return s`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(`return `, strconvPkg.Use(), `.Itoa(int(x))`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !p.atleastOne {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(NewEnumStringer())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,694 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					The equal plugin generates an Equal and a VerboseEqual method for each message.
 | 
				
			||||||
 | 
					These equal methods are quite obvious.
 | 
				
			||||||
 | 
					The only difference is that VerboseEqual returns a non nil error if it is not equal.
 | 
				
			||||||
 | 
					This error contains more detail on exactly which part of the message was not equal to the other message.
 | 
				
			||||||
 | 
					The idea is that this is useful for debugging.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Equal is enabled using the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - equal
 | 
				
			||||||
 | 
					  - equal_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					While VerboseEqual is enable dusing the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - verbose_equal
 | 
				
			||||||
 | 
					  - verbose_equal_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The equal plugin also generates a test given it is enabled using one of the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - testgen
 | 
				
			||||||
 | 
					  - testgen_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let us look at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/example.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Btw all the output can be seen at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following message:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  option (gogoproto.equal_all) = true;
 | 
				
			||||||
 | 
					  option (gogoproto.verbose_equal_all) = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  message B {
 | 
				
			||||||
 | 
						optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
 | 
				
			||||||
 | 
						repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					given to the equal plugin, will generate the following code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func (this *B) VerboseEqual(that interface{}) error {
 | 
				
			||||||
 | 
							if that == nil {
 | 
				
			||||||
 | 
								if this == nil {
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return fmt2.Errorf("that == nil && this != nil")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							that1, ok := that.(*B)
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								return fmt2.Errorf("that is not of type *B")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if that1 == nil {
 | 
				
			||||||
 | 
								if this == nil {
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return fmt2.Errorf("that is type *B but is nil && this != nil")
 | 
				
			||||||
 | 
							} else if this == nil {
 | 
				
			||||||
 | 
								return fmt2.Errorf("that is type *B but is not nil && this == nil")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !this.A.Equal(&that1.A) {
 | 
				
			||||||
 | 
								return fmt2.Errorf("A this(%v) Not Equal that(%v)", this.A, that1.A)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if len(this.G) != len(that1.G) {
 | 
				
			||||||
 | 
								return fmt2.Errorf("G this(%v) Not Equal that(%v)", len(this.G), len(that1.G))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for i := range this.G {
 | 
				
			||||||
 | 
								if !this.G[i].Equal(that1.G[i]) {
 | 
				
			||||||
 | 
									return fmt2.Errorf("G this[%v](%v) Not Equal that[%v](%v)", i, this.G[i], i, that1.G[i])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
 | 
				
			||||||
 | 
								return fmt2.Errorf("XXX_unrecognized this(%v) Not Equal that(%v)", this.XXX_unrecognized, that1.XXX_unrecognized)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func (this *B) Equal(that interface{}) bool {
 | 
				
			||||||
 | 
							if that == nil {
 | 
				
			||||||
 | 
								return this == nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							that1, ok := that.(*B)
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if that1 == nil {
 | 
				
			||||||
 | 
								return this == nil
 | 
				
			||||||
 | 
							} else if this == nil {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !this.A.Equal(&that1.A) {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if len(this.G) != len(that1.G) {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for i := range this.G {
 | 
				
			||||||
 | 
								if !this.G[i].Equal(that1.G[i]) {
 | 
				
			||||||
 | 
									return false
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and the following test code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func TestBVerboseEqual(t *testing8.T) {
 | 
				
			||||||
 | 
							popr := math_rand8.New(math_rand8.NewSource(time8.Now().UnixNano()))
 | 
				
			||||||
 | 
							p := NewPopulatedB(popr, false)
 | 
				
			||||||
 | 
							dAtA, err := github_com_gogo_protobuf_proto2.Marshal(p)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							msg := &B{}
 | 
				
			||||||
 | 
							if err := github_com_gogo_protobuf_proto2.Unmarshal(dAtA, msg); err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := p.VerboseEqual(msg); err != nil {
 | 
				
			||||||
 | 
								t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package equal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/vanity"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type plugin struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
						generator.PluginImports
 | 
				
			||||||
 | 
						fmtPkg   generator.Single
 | 
				
			||||||
 | 
						bytesPkg generator.Single
 | 
				
			||||||
 | 
						protoPkg generator.Single
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewPlugin() *plugin {
 | 
				
			||||||
 | 
						return &plugin{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Name() string {
 | 
				
			||||||
 | 
						return "equal"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						p.PluginImports = generator.NewPluginImports(p.Generator)
 | 
				
			||||||
 | 
						p.fmtPkg = p.NewImport("fmt")
 | 
				
			||||||
 | 
						p.bytesPkg = p.NewImport("bytes")
 | 
				
			||||||
 | 
						p.protoPkg = p.NewImport("github.com/gogo/protobuf/proto")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, msg := range file.Messages() {
 | 
				
			||||||
 | 
							if msg.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if gogoproto.HasVerboseEqual(file.FileDescriptorProto, msg.DescriptorProto) {
 | 
				
			||||||
 | 
								p.generateMessage(file, msg, true)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if gogoproto.HasEqual(file.FileDescriptorProto, msg.DescriptorProto) {
 | 
				
			||||||
 | 
								p.generateMessage(file, msg, false)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) generateNullableField(fieldname string, verbose bool) {
 | 
				
			||||||
 | 
						p.P(`if this.`, fieldname, ` != nil && that1.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`if *this.`, fieldname, ` != *that1.`, fieldname, `{`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						if verbose {
 | 
				
			||||||
 | 
							p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", *this.`, fieldname, `, *that1.`, fieldname, `)`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							p.P(`return false`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`} else if this.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						if verbose {
 | 
				
			||||||
 | 
							p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` == nil && that.`, fieldname, ` != nil")`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							p.P(`return false`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`} else if that1.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) generateMsgNullAndTypeCheck(ccTypeName string, verbose bool) {
 | 
				
			||||||
 | 
						p.P(`if that == nil {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						if verbose {
 | 
				
			||||||
 | 
							p.P(`if this == nil {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`return nil`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(`return `, p.fmtPkg.Use(), `.Errorf("that == nil && this != nil")`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							p.P(`return this == nil`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(``)
 | 
				
			||||||
 | 
						p.P(`that1, ok := that.(*`, ccTypeName, `)`)
 | 
				
			||||||
 | 
						p.P(`if !ok {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`that2, ok := that.(`, ccTypeName, `)`)
 | 
				
			||||||
 | 
						p.P(`if ok {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`that1 = &that2`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`} else {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						if verbose {
 | 
				
			||||||
 | 
							p.P(`return `, p.fmtPkg.Use(), `.Errorf("that is not of type *`, ccTypeName, `")`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							p.P(`return false`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(`if that1 == nil {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						if verbose {
 | 
				
			||||||
 | 
							p.P(`if this == nil {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`return nil`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(`return `, p.fmtPkg.Use(), `.Errorf("that is type *`, ccTypeName, ` but is nil && this != nil")`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							p.P(`return this == nil`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`} else if this == nil {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						if verbose {
 | 
				
			||||||
 | 
							p.P(`return `, p.fmtPkg.Use(), `.Errorf("that is type *`, ccTypeName, ` but is not nil && this == nil")`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							p.P(`return false`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) generateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto, verbose bool) {
 | 
				
			||||||
 | 
						proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
 | 
				
			||||||
 | 
						fieldname := p.GetOneOfFieldName(message, field)
 | 
				
			||||||
 | 
						repeated := field.IsRepeated()
 | 
				
			||||||
 | 
						ctype := gogoproto.IsCustomType(field)
 | 
				
			||||||
 | 
						nullable := gogoproto.IsNullable(field)
 | 
				
			||||||
 | 
						isNormal := (gogoproto.IsStdDuration(field) ||
 | 
				
			||||||
 | 
							gogoproto.IsStdDouble(field) ||
 | 
				
			||||||
 | 
							gogoproto.IsStdFloat(field) ||
 | 
				
			||||||
 | 
							gogoproto.IsStdInt64(field) ||
 | 
				
			||||||
 | 
							gogoproto.IsStdUInt64(field) ||
 | 
				
			||||||
 | 
							gogoproto.IsStdInt32(field) ||
 | 
				
			||||||
 | 
							gogoproto.IsStdUInt32(field) ||
 | 
				
			||||||
 | 
							gogoproto.IsStdBool(field) ||
 | 
				
			||||||
 | 
							gogoproto.IsStdString(field))
 | 
				
			||||||
 | 
						isBytes := gogoproto.IsStdBytes(field)
 | 
				
			||||||
 | 
						isTimestamp := gogoproto.IsStdTime(field)
 | 
				
			||||||
 | 
						// oneof := field.OneofIndex != nil
 | 
				
			||||||
 | 
						if !repeated {
 | 
				
			||||||
 | 
							if ctype || isTimestamp {
 | 
				
			||||||
 | 
								if nullable {
 | 
				
			||||||
 | 
									p.P(`if that1.`, fieldname, ` == nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									if verbose {
 | 
				
			||||||
 | 
										p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`return false`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`} else if !this.`, fieldname, `.Equal(*that1.`, fieldname, `) {`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if verbose {
 | 
				
			||||||
 | 
									p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`return false`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if isNormal {
 | 
				
			||||||
 | 
								if nullable {
 | 
				
			||||||
 | 
									p.generateNullableField(fieldname, verbose)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if verbose {
 | 
				
			||||||
 | 
									p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`return false`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if isBytes {
 | 
				
			||||||
 | 
								if nullable {
 | 
				
			||||||
 | 
									p.P(`if that1.`, fieldname, ` == nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									if verbose {
 | 
				
			||||||
 | 
										p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`return false`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`} else if !`, p.bytesPkg.Use(), `.Equal(*this.`, fieldname, `, *that1.`, fieldname, `) {`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if verbose {
 | 
				
			||||||
 | 
									p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`return false`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if field.IsMessage() || p.IsGroup(field) {
 | 
				
			||||||
 | 
									if nullable {
 | 
				
			||||||
 | 
										p.P(`if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`if !this.`, fieldname, `.Equal(&that1.`, fieldname, `) {`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if field.IsBytes() {
 | 
				
			||||||
 | 
									p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
 | 
				
			||||||
 | 
								} else if field.IsString() {
 | 
				
			||||||
 | 
									if nullable && !proto3 {
 | 
				
			||||||
 | 
										p.generateNullableField(fieldname, verbose)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									if nullable && !proto3 {
 | 
				
			||||||
 | 
										p.generateNullableField(fieldname, verbose)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if verbose {
 | 
				
			||||||
 | 
									p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`return false`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							p.P(`if len(this.`, fieldname, `) != len(that1.`, fieldname, `) {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							if verbose {
 | 
				
			||||||
 | 
								p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", len(this.`, fieldname, `), len(that1.`, fieldname, `))`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.P(`return false`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(`for i := range this.`, fieldname, ` {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							if ctype && !p.IsMap(field) {
 | 
				
			||||||
 | 
								p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
 | 
				
			||||||
 | 
							} else if isTimestamp {
 | 
				
			||||||
 | 
								if nullable {
 | 
				
			||||||
 | 
									p.P(`if !this.`, fieldname, `[i].Equal(*that1.`, fieldname, `[i]) {`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if isNormal {
 | 
				
			||||||
 | 
								if nullable {
 | 
				
			||||||
 | 
									p.P(`if dthis, dthat := this.`, fieldname, `[i], that1.`, fieldname, `[i]; (dthis != nil && dthat != nil && *dthis != *dthat) || (dthis != nil && dthat == nil) || (dthis == nil && dthat != nil)  {`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if isBytes {
 | 
				
			||||||
 | 
								if nullable {
 | 
				
			||||||
 | 
									p.P(`if !`, p.bytesPkg.Use(), `.Equal(*this.`, fieldname, `[i], *that1.`, fieldname, `[i]) {`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if p.IsMap(field) {
 | 
				
			||||||
 | 
									m := p.GoMapType(nil, field)
 | 
				
			||||||
 | 
									valuegoTyp, _ := p.GoType(nil, m.ValueField)
 | 
				
			||||||
 | 
									valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
 | 
				
			||||||
 | 
									nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									mapValue := m.ValueAliasField
 | 
				
			||||||
 | 
									mapValueNormal := (gogoproto.IsStdDuration(mapValue) ||
 | 
				
			||||||
 | 
										gogoproto.IsStdDouble(mapValue) ||
 | 
				
			||||||
 | 
										gogoproto.IsStdFloat(mapValue) ||
 | 
				
			||||||
 | 
										gogoproto.IsStdInt64(mapValue) ||
 | 
				
			||||||
 | 
										gogoproto.IsStdUInt64(mapValue) ||
 | 
				
			||||||
 | 
										gogoproto.IsStdInt32(mapValue) ||
 | 
				
			||||||
 | 
										gogoproto.IsStdUInt32(mapValue) ||
 | 
				
			||||||
 | 
										gogoproto.IsStdBool(mapValue) ||
 | 
				
			||||||
 | 
										gogoproto.IsStdString(mapValue))
 | 
				
			||||||
 | 
									mapValueBytes := gogoproto.IsStdBytes(mapValue)
 | 
				
			||||||
 | 
									if mapValue.IsMessage() || p.IsGroup(mapValue) {
 | 
				
			||||||
 | 
										if nullable && valuegoTyp == valuegoAliasTyp {
 | 
				
			||||||
 | 
											p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											// Equal() has a pointer receiver, but map value is a value type
 | 
				
			||||||
 | 
											a := `this.` + fieldname + `[i]`
 | 
				
			||||||
 | 
											b := `that1.` + fieldname + `[i]`
 | 
				
			||||||
 | 
											if !mapValueNormal && !mapValueBytes && valuegoTyp != valuegoAliasTyp {
 | 
				
			||||||
 | 
												// cast back to the type that has the generated methods on it
 | 
				
			||||||
 | 
												a = `(` + valuegoTyp + `)(` + a + `)`
 | 
				
			||||||
 | 
												b = `(` + valuegoTyp + `)(` + b + `)`
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											p.P(`a := `, a)
 | 
				
			||||||
 | 
											p.P(`b := `, b)
 | 
				
			||||||
 | 
											if mapValueNormal {
 | 
				
			||||||
 | 
												if nullable {
 | 
				
			||||||
 | 
													p.P(`if *a != *b {`)
 | 
				
			||||||
 | 
												} else {
 | 
				
			||||||
 | 
													p.P(`if a != b {`)
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											} else if mapValueBytes {
 | 
				
			||||||
 | 
												if nullable {
 | 
				
			||||||
 | 
													p.P(`if !`, p.bytesPkg.Use(), `.Equal(*a, *b) {`)
 | 
				
			||||||
 | 
												} else {
 | 
				
			||||||
 | 
													p.P(`if !`, p.bytesPkg.Use(), `.Equal(a, b) {`)
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											} else if nullable {
 | 
				
			||||||
 | 
												p.P(`if !a.Equal(b) {`)
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												p.P(`if !(&a).Equal(&b) {`)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else if mapValue.IsBytes() {
 | 
				
			||||||
 | 
										if ctype {
 | 
				
			||||||
 | 
											if nullable {
 | 
				
			||||||
 | 
												p.P(`if !this.`, fieldname, `[i].Equal(*that1.`, fieldname, `[i]) { //nullable`)
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) { //not nullable`)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else if mapValue.IsString() {
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if field.IsMessage() || p.IsGroup(field) {
 | 
				
			||||||
 | 
									if nullable {
 | 
				
			||||||
 | 
										p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`if !this.`, fieldname, `[i].Equal(&that1.`, fieldname, `[i]) {`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if field.IsBytes() {
 | 
				
			||||||
 | 
									p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
 | 
				
			||||||
 | 
								} else if field.IsString() {
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							if verbose {
 | 
				
			||||||
 | 
								p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this[%v](%v) Not Equal that[%v](%v)", i, this.`, fieldname, `[i], i, that1.`, fieldname, `[i])`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.P(`return false`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) generateMessage(file *generator.FileDescriptor, message *generator.Descriptor, verbose bool) {
 | 
				
			||||||
 | 
						ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
						if verbose {
 | 
				
			||||||
 | 
							p.P(`func (this *`, ccTypeName, `) VerboseEqual(that interface{}) error {`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							p.P(`func (this *`, ccTypeName, `) Equal(that interface{}) bool {`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.generateMsgNullAndTypeCheck(ccTypeName, verbose)
 | 
				
			||||||
 | 
						oneofs := make(map[string]struct{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, field := range message.Field {
 | 
				
			||||||
 | 
							oneof := field.OneofIndex != nil
 | 
				
			||||||
 | 
							if oneof {
 | 
				
			||||||
 | 
								fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
								if _, ok := oneofs[fieldname]; ok {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									oneofs[fieldname] = struct{}{}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`if that1.`, fieldname, ` == nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`if this.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if verbose {
 | 
				
			||||||
 | 
									p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`return false`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`} else if this.`, fieldname, ` == nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if verbose {
 | 
				
			||||||
 | 
									p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` == nil && that1.`, fieldname, ` != nil")`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`return false`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								if verbose {
 | 
				
			||||||
 | 
									p.P(`} else if err := this.`, fieldname, `.VerboseEqual(that1.`, fieldname, `); err != nil {`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`} else if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if verbose {
 | 
				
			||||||
 | 
									p.P(`return err`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`return false`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.generateField(file, message, field, verbose)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if message.DescriptorProto.HasExtension() {
 | 
				
			||||||
 | 
							if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								fieldname := "XXX_InternalExtensions"
 | 
				
			||||||
 | 
								p.P(`thismap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(this)`)
 | 
				
			||||||
 | 
								p.P(`thatmap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(that1)`)
 | 
				
			||||||
 | 
								p.P(`for k, v := range thismap {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`if v2, ok := thatmap[k]; ok {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`if !v.Equal(&v2) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if verbose {
 | 
				
			||||||
 | 
									p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this[%v](%v) Not Equal that[%v](%v)", k, thismap[k], k, thatmap[k])`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`return false`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`} else  {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if verbose {
 | 
				
			||||||
 | 
									p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, `[%v] Not In that", k)`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`return false`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								p.P(`for k, _ := range thatmap {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`if _, ok := thismap[k]; !ok {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if verbose {
 | 
				
			||||||
 | 
									p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, `[%v] Not In this", k)`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`return false`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								fieldname := "XXX_extensions"
 | 
				
			||||||
 | 
								p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if verbose {
 | 
				
			||||||
 | 
									p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`return false`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
							fieldname := "XXX_unrecognized"
 | 
				
			||||||
 | 
							p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							if verbose {
 | 
				
			||||||
 | 
								p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.P(`return false`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if verbose {
 | 
				
			||||||
 | 
							p.P(`return nil`)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							p.P(`return true`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//Generate Equal methods for oneof fields
 | 
				
			||||||
 | 
						m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
 | 
				
			||||||
 | 
						for _, field := range m.Field {
 | 
				
			||||||
 | 
							oneof := field.OneofIndex != nil
 | 
				
			||||||
 | 
							if !oneof {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ccTypeName := p.OneOfTypeName(message, field)
 | 
				
			||||||
 | 
							if verbose {
 | 
				
			||||||
 | 
								p.P(`func (this *`, ccTypeName, `) VerboseEqual(that interface{}) error {`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.P(`func (this *`, ccTypeName, `) Equal(that interface{}) bool {`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p.generateMsgNullAndTypeCheck(ccTypeName, verbose)
 | 
				
			||||||
 | 
							vanity.TurnOffNullableForNativeTypes(field)
 | 
				
			||||||
 | 
							p.generateField(file, message, field, verbose)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if verbose {
 | 
				
			||||||
 | 
								p.P(`return nil`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.P(`return true`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(NewPlugin())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,109 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package equal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/plugin/testgen"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type test struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewTest(g *generator.Generator) testgen.TestPlugin {
 | 
				
			||||||
 | 
						return &test{g}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
 | 
				
			||||||
 | 
						used := false
 | 
				
			||||||
 | 
						randPkg := imports.NewImport("math/rand")
 | 
				
			||||||
 | 
						timePkg := imports.NewImport("time")
 | 
				
			||||||
 | 
						testingPkg := imports.NewImport("testing")
 | 
				
			||||||
 | 
						protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
 | 
				
			||||||
 | 
						unsafePkg := imports.NewImport("unsafe")
 | 
				
			||||||
 | 
						if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
 | 
				
			||||||
 | 
							protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							if !gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								used = true
 | 
				
			||||||
 | 
								hasUnsafe := gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) ||
 | 
				
			||||||
 | 
									gogoproto.IsUnsafeUnmarshaler(file.FileDescriptorProto, message.DescriptorProto)
 | 
				
			||||||
 | 
								p.P(`func Test`, ccTypeName, `VerboseEqual(t *`, testingPkg.Use(), `.T) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if hasUnsafe {
 | 
				
			||||||
 | 
									if hasUnsafe {
 | 
				
			||||||
 | 
										p.P(`var bigendian uint32 = 0x01020304`)
 | 
				
			||||||
 | 
										p.P(`if *(*byte)(`, unsafePkg.Use(), `.Pointer(&bigendian)) == 1 {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`t.Skip("unsafe does not work on big endian architectures")`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
 | 
				
			||||||
 | 
								p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
 | 
				
			||||||
 | 
								p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
 | 
				
			||||||
 | 
								p.P(`if err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`panic(err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`msg := &`, ccTypeName, `{}`)
 | 
				
			||||||
 | 
								p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`panic(err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`if err := p.VerboseEqual(msg); err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return used
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						testgen.RegisterTestPlugin(NewTest)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,233 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					The face plugin generates a function will be generated which can convert a structure which satisfies an interface (face) to the specified structure.
 | 
				
			||||||
 | 
					This interface contains getters for each of the fields in the struct.
 | 
				
			||||||
 | 
					The specified struct is also generated with the getters.
 | 
				
			||||||
 | 
					This means that getters should be turned off so as not to conflict with face getters.
 | 
				
			||||||
 | 
					This allows it to satisfy its own face.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is enabled by the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - face
 | 
				
			||||||
 | 
					  - face_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Turn off getters by using the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - getters
 | 
				
			||||||
 | 
					  - getters_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The face plugin also generates a test given it is enabled using one of the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - testgen
 | 
				
			||||||
 | 
					  - testgen_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let us look at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/example.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Btw all the output can be seen at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following message:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  message A {
 | 
				
			||||||
 | 
						option (gogoproto.face) = true;
 | 
				
			||||||
 | 
						option (gogoproto.goproto_getters) = false;
 | 
				
			||||||
 | 
						optional string Description = 1 [(gogoproto.nullable) = false];
 | 
				
			||||||
 | 
						optional int64 Number = 2 [(gogoproto.nullable) = false];
 | 
				
			||||||
 | 
						optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					given to the face plugin, will generate the following code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						type AFace interface {
 | 
				
			||||||
 | 
							Proto() github_com_gogo_protobuf_proto.Message
 | 
				
			||||||
 | 
							GetDescription() string
 | 
				
			||||||
 | 
							GetNumber() int64
 | 
				
			||||||
 | 
							GetId() github_com_gogo_protobuf_test_custom.Uuid
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func (this *A) Proto() github_com_gogo_protobuf_proto.Message {
 | 
				
			||||||
 | 
							return this
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func (this *A) TestProto() github_com_gogo_protobuf_proto.Message {
 | 
				
			||||||
 | 
							return NewAFromFace(this)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func (this *A) GetDescription() string {
 | 
				
			||||||
 | 
							return this.Description
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func (this *A) GetNumber() int64 {
 | 
				
			||||||
 | 
							return this.Number
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func (this *A) GetId() github_com_gogo_protobuf_test_custom.Uuid {
 | 
				
			||||||
 | 
							return this.Id
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func NewAFromFace(that AFace) *A {
 | 
				
			||||||
 | 
							this := &A{}
 | 
				
			||||||
 | 
							this.Description = that.GetDescription()
 | 
				
			||||||
 | 
							this.Number = that.GetNumber()
 | 
				
			||||||
 | 
							this.Id = that.GetId()
 | 
				
			||||||
 | 
							return this
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and the following test code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func TestAFace(t *testing7.T) {
 | 
				
			||||||
 | 
							popr := math_rand7.New(math_rand7.NewSource(time7.Now().UnixNano()))
 | 
				
			||||||
 | 
							p := NewPopulatedA(popr, true)
 | 
				
			||||||
 | 
							msg := p.TestProto()
 | 
				
			||||||
 | 
							if !p.Equal(msg) {
 | 
				
			||||||
 | 
								t.Fatalf("%#v !Face Equal %#v", msg, p)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The struct A, representing the message, will also be generated just like always.
 | 
				
			||||||
 | 
					As you can see A satisfies its own Face, AFace.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Creating another struct which satisfies AFace is very easy.
 | 
				
			||||||
 | 
					Simply create all these methods specified in AFace.
 | 
				
			||||||
 | 
					Implementing The Proto method is done with the helper function NewAFromFace:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func (this *MyStruct) Proto() proto.Message {
 | 
				
			||||||
 | 
						  return NewAFromFace(this)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					just the like TestProto method which is used to test the NewAFromFace function.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package face
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type plugin struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
						generator.PluginImports
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewPlugin() *plugin {
 | 
				
			||||||
 | 
						return &plugin{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Name() string {
 | 
				
			||||||
 | 
						return "face"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						p.PluginImports = generator.NewPluginImports(p.Generator)
 | 
				
			||||||
 | 
						protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
 | 
				
			||||||
 | 
						if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
 | 
				
			||||||
 | 
							protoPkg = p.NewImport("github.com/golang/protobuf/proto")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							if !gogoproto.IsFace(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.HasExtension() {
 | 
				
			||||||
 | 
								panic("face does not support message with extensions")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if gogoproto.HasGoGetters(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								panic("face requires getters to be disabled please use gogoproto.getters or gogoproto.getters_all and set it to false")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							p.P(`type `, ccTypeName, `Face interface{`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`Proto() `, protoPkg.Use(), `.Message`)
 | 
				
			||||||
 | 
							for _, field := range message.Field {
 | 
				
			||||||
 | 
								fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
								goTyp, _ := p.GoType(message, field)
 | 
				
			||||||
 | 
								if p.IsMap(field) {
 | 
				
			||||||
 | 
									m := p.GoMapType(nil, field)
 | 
				
			||||||
 | 
									goTyp = m.GoType
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`Get`, fieldname, `() `, goTyp)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(``)
 | 
				
			||||||
 | 
							p.P(`func (this *`, ccTypeName, `) Proto() `, protoPkg.Use(), `.Message {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`return this`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(``)
 | 
				
			||||||
 | 
							p.P(`func (this *`, ccTypeName, `) TestProto() `, protoPkg.Use(), `.Message {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`return New`, ccTypeName, `FromFace(this)`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(``)
 | 
				
			||||||
 | 
							for _, field := range message.Field {
 | 
				
			||||||
 | 
								fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
								goTyp, _ := p.GoType(message, field)
 | 
				
			||||||
 | 
								if p.IsMap(field) {
 | 
				
			||||||
 | 
									m := p.GoMapType(nil, field)
 | 
				
			||||||
 | 
									goTyp = m.GoType
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`func (this *`, ccTypeName, `) Get`, fieldname, `() `, goTyp, `{`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(` return this.`, fieldname)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(``)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.P(``)
 | 
				
			||||||
 | 
							p.P(`func New`, ccTypeName, `FromFace(that `, ccTypeName, `Face) *`, ccTypeName, ` {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`this := &`, ccTypeName, `{}`)
 | 
				
			||||||
 | 
							for _, field := range message.Field {
 | 
				
			||||||
 | 
								fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
								p.P(`this.`, fieldname, ` = that.Get`, fieldname, `()`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.P(`return this`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(``)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(NewPlugin())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,82 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package face
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/plugin/testgen"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type test struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewTest(g *generator.Generator) testgen.TestPlugin {
 | 
				
			||||||
 | 
						return &test{g}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
 | 
				
			||||||
 | 
						used := false
 | 
				
			||||||
 | 
						randPkg := imports.NewImport("math/rand")
 | 
				
			||||||
 | 
						timePkg := imports.NewImport("time")
 | 
				
			||||||
 | 
						testingPkg := imports.NewImport("testing")
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							if !gogoproto.IsFace(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								used = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								p.P(`func Test`, ccTypeName, `Face(t *`, testingPkg.Use(), `.T) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
 | 
				
			||||||
 | 
								p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
 | 
				
			||||||
 | 
								p.P(`msg := p.TestProto()`)
 | 
				
			||||||
 | 
								p.P(`if !p.Equal(msg) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("%#v !Face Equal %#v", msg, p)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return used
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						testgen.RegisterTestPlugin(NewTest)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,386 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					The gostring plugin generates a GoString method for each message.
 | 
				
			||||||
 | 
					The GoString method is called whenever you use a fmt.Printf as such:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fmt.Printf("%#v", mymessage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					or whenever you actually call GoString()
 | 
				
			||||||
 | 
					The output produced by the GoString method can be copied from the output into code and used to set a variable.
 | 
				
			||||||
 | 
					It is totally valid Go Code and is populated exactly as the struct that was printed out.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is enabled by the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - gostring
 | 
				
			||||||
 | 
					  - gostring_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The gostring plugin also generates a test given it is enabled using one of the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - testgen
 | 
				
			||||||
 | 
					  - testgen_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let us look at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/example.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Btw all the output can be seen at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following message:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  option (gogoproto.gostring_all) = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  message A {
 | 
				
			||||||
 | 
						optional string Description = 1 [(gogoproto.nullable) = false];
 | 
				
			||||||
 | 
						optional int64 Number = 2 [(gogoproto.nullable) = false];
 | 
				
			||||||
 | 
						optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					given to the gostring plugin, will generate the following code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  func (this *A) GoString() string {
 | 
				
			||||||
 | 
						if this == nil {
 | 
				
			||||||
 | 
							return "nil"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s := strings1.Join([]string{`&test.A{` + `Description:` + fmt1.Sprintf("%#v", this.Description), `Number:` + fmt1.Sprintf("%#v", this.Number), `Id:` + fmt1.Sprintf("%#v", this.Id), `XXX_unrecognized:` + fmt1.Sprintf("%#v", this.XXX_unrecognized) + `}`}, ", ")
 | 
				
			||||||
 | 
						return s
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and the following test code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func TestAGoString(t *testing6.T) {
 | 
				
			||||||
 | 
							popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano()))
 | 
				
			||||||
 | 
							p := NewPopulatedA(popr, false)
 | 
				
			||||||
 | 
							s1 := p.GoString()
 | 
				
			||||||
 | 
							s2 := fmt2.Sprintf("%#v", p)
 | 
				
			||||||
 | 
							if s1 != s2 {
 | 
				
			||||||
 | 
								t.Fatalf("GoString want %v got %v", s1, s2)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							_, err := go_parser.ParseExpr(s1)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Typically fmt.Printf("%#v") will stop to print when it reaches a pointer and
 | 
				
			||||||
 | 
					not print their values, while the generated GoString method will always print all values, recursively.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package gostring
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type gostring struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
						generator.PluginImports
 | 
				
			||||||
 | 
						atleastOne bool
 | 
				
			||||||
 | 
						localName  string
 | 
				
			||||||
 | 
						overwrite  bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewGoString() *gostring {
 | 
				
			||||||
 | 
						return &gostring{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *gostring) Name() string {
 | 
				
			||||||
 | 
						return "gostring"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *gostring) Overwrite() {
 | 
				
			||||||
 | 
						p.overwrite = true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *gostring) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *gostring) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
 | 
				
			||||||
 | 
						p.PluginImports = generator.NewPluginImports(p.Generator)
 | 
				
			||||||
 | 
						p.atleastOne = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.localName = generator.FileName(file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmtPkg := p.NewImport("fmt")
 | 
				
			||||||
 | 
						stringsPkg := p.NewImport("strings")
 | 
				
			||||||
 | 
						protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
 | 
				
			||||||
 | 
						if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
 | 
				
			||||||
 | 
							protoPkg = p.NewImport("github.com/golang/protobuf/proto")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sortPkg := p.NewImport("sort")
 | 
				
			||||||
 | 
						strconvPkg := p.NewImport("strconv")
 | 
				
			||||||
 | 
						reflectPkg := p.NewImport("reflect")
 | 
				
			||||||
 | 
						sortKeysPkg := p.NewImport("github.com/gogo/protobuf/sortkeys")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						extensionToGoStringUsed := false
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							if !p.overwrite && !gogoproto.HasGoString(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.atleastOne = true
 | 
				
			||||||
 | 
							packageName := file.GoPackageName()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							p.P(`func (this *`, ccTypeName, `) GoString() string {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`if this == nil {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`return "nil"`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p.P(`s := make([]string, 0, `, strconv.Itoa(len(message.Field)+4), `)`)
 | 
				
			||||||
 | 
							p.P(`s = append(s, "&`, packageName, ".", ccTypeName, `{")`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							oneofs := make(map[string]struct{})
 | 
				
			||||||
 | 
							for _, field := range message.Field {
 | 
				
			||||||
 | 
								nullable := gogoproto.IsNullable(field)
 | 
				
			||||||
 | 
								repeated := field.IsRepeated()
 | 
				
			||||||
 | 
								fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
								oneof := field.OneofIndex != nil
 | 
				
			||||||
 | 
								if oneof {
 | 
				
			||||||
 | 
									if _, ok := oneofs[fieldname]; ok {
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										oneofs[fieldname] = struct{}{}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else if p.IsMap(field) {
 | 
				
			||||||
 | 
									m := p.GoMapType(nil, field)
 | 
				
			||||||
 | 
									mapgoTyp, keyField, keyAliasField := m.GoType, m.KeyField, m.KeyAliasField
 | 
				
			||||||
 | 
									keysName := `keysFor` + fieldname
 | 
				
			||||||
 | 
									keygoTyp, _ := p.GoType(nil, keyField)
 | 
				
			||||||
 | 
									keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
 | 
				
			||||||
 | 
									keygoAliasTyp, _ := p.GoType(nil, keyAliasField)
 | 
				
			||||||
 | 
									keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
 | 
				
			||||||
 | 
									keyCapTyp := generator.CamelCase(keygoTyp)
 | 
				
			||||||
 | 
									p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(this.`, fieldname, `))`)
 | 
				
			||||||
 | 
									p.P(`for k, _ := range this.`, fieldname, ` {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									if keygoAliasTyp == keygoTyp {
 | 
				
			||||||
 | 
										p.P(keysName, ` = append(`, keysName, `, k)`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.P(sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
 | 
				
			||||||
 | 
									mapName := `mapStringFor` + fieldname
 | 
				
			||||||
 | 
									p.P(mapName, ` := "`, mapgoTyp, `{"`)
 | 
				
			||||||
 | 
									p.P(`for _, k := range `, keysName, ` {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									if keygoAliasTyp == keygoTyp {
 | 
				
			||||||
 | 
										p.P(mapName, ` += fmt.Sprintf("%#v: %#v,", k, this.`, fieldname, `[k])`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(mapName, ` += fmt.Sprintf("%#v: %#v,", k, this.`, fieldname, `[`, keygoAliasTyp, `(k)])`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.P(mapName, ` += "}"`)
 | 
				
			||||||
 | 
									p.P(`if this.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`s = append(s, "`, fieldname, `: " + `, mapName, `+ ",\n")`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else if (field.IsMessage() && !gogoproto.IsCustomType(field) && !gogoproto.IsStdType(field)) || p.IsGroup(field) {
 | 
				
			||||||
 | 
									if nullable || repeated {
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if nullable {
 | 
				
			||||||
 | 
										p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
 | 
				
			||||||
 | 
									} else if repeated {
 | 
				
			||||||
 | 
										if nullable {
 | 
				
			||||||
 | 
											p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											goTyp, _ := p.GoType(message, field)
 | 
				
			||||||
 | 
											goTyp = strings.Replace(goTyp, "[]", "", 1)
 | 
				
			||||||
 | 
											p.P("vs := make([]", goTyp, ", len(this.", fieldname, "))")
 | 
				
			||||||
 | 
											p.P("for i := range vs {")
 | 
				
			||||||
 | 
											p.In()
 | 
				
			||||||
 | 
											p.P("vs[i] = this.", fieldname, "[i]")
 | 
				
			||||||
 | 
											p.Out()
 | 
				
			||||||
 | 
											p.P("}")
 | 
				
			||||||
 | 
											p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", vs) + ",\n")`)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`s = append(s, "`, fieldname, `: " + `, stringsPkg.Use(), `.Replace(this.`, fieldname, `.GoString()`, ",`&`,``,1)", ` + ",\n")`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if nullable || repeated {
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									if !proto3 && (nullable || repeated) {
 | 
				
			||||||
 | 
										p.P(`if this.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if field.IsEnum() {
 | 
				
			||||||
 | 
										if nullable && !repeated && !proto3 {
 | 
				
			||||||
 | 
											goTyp, _ := p.GoType(message, field)
 | 
				
			||||||
 | 
											p.P(`s = append(s, "`, fieldname, `: " + valueToGoString`, p.localName, `(this.`, fieldname, `,"`, generator.GoTypeToName(goTyp), `"`, `) + ",\n")`)
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										if nullable && !repeated && !proto3 {
 | 
				
			||||||
 | 
											goTyp, _ := p.GoType(message, field)
 | 
				
			||||||
 | 
											p.P(`s = append(s, "`, fieldname, `: " + valueToGoString`, p.localName, `(this.`, fieldname, `,"`, generator.GoTypeToName(goTyp), `"`, `) + ",\n")`)
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if !proto3 && (nullable || repeated) {
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.HasExtension() {
 | 
				
			||||||
 | 
								if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
									p.P(`s = append(s, "XXX_InternalExtensions: " + extensionToGoString`, p.localName, `(this) + ",\n")`)
 | 
				
			||||||
 | 
									extensionToGoStringUsed = true
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`if this.XXX_extensions != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`s = append(s, "XXX_extensions: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.XXX_extensions) + ",\n")`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								p.P(`if this.XXX_unrecognized != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`s = append(s, "XXX_unrecognized:" + `, fmtPkg.Use(), `.Sprintf("%#v", this.XXX_unrecognized) + ",\n")`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p.P(`s = append(s, "}")`)
 | 
				
			||||||
 | 
							p.P(`return `, stringsPkg.Use(), `.Join(s, "")`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//Generate GoString methods for oneof fields
 | 
				
			||||||
 | 
							for _, field := range message.Field {
 | 
				
			||||||
 | 
								oneof := field.OneofIndex != nil
 | 
				
			||||||
 | 
								if !oneof {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								ccTypeName := p.OneOfTypeName(message, field)
 | 
				
			||||||
 | 
								p.P(`func (this *`, ccTypeName, `) GoString() string {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`if this == nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return "nil"`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								fieldname := p.GetOneOfFieldName(message, field)
 | 
				
			||||||
 | 
								outStr := strings.Join([]string{
 | 
				
			||||||
 | 
									"s := ",
 | 
				
			||||||
 | 
									stringsPkg.Use(), ".Join([]string{`&", packageName, ".", ccTypeName, "{` + \n",
 | 
				
			||||||
 | 
									"`", fieldname, ":` + ", fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `)`,
 | 
				
			||||||
 | 
									" + `}`",
 | 
				
			||||||
 | 
									`}`,
 | 
				
			||||||
 | 
									`,", "`,
 | 
				
			||||||
 | 
									`)`}, "")
 | 
				
			||||||
 | 
								p.P(outStr)
 | 
				
			||||||
 | 
								p.P(`return s`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !p.atleastOne {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.P(`func valueToGoString`, p.localName, `(v interface{}, typ string) string {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`rv := `, reflectPkg.Use(), `.ValueOf(v)`)
 | 
				
			||||||
 | 
						p.P(`if rv.IsNil() {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`return "nil"`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(`pv := `, reflectPkg.Use(), `.Indirect(rv).Interface()`)
 | 
				
			||||||
 | 
						p.P(`return `, fmtPkg.Use(), `.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if extensionToGoStringUsed {
 | 
				
			||||||
 | 
							if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
 | 
				
			||||||
 | 
								fmt.Fprintf(os.Stderr, "The GoString plugin for messages with extensions requires importing gogoprotobuf. Please see file %s", file.GetName())
 | 
				
			||||||
 | 
								os.Exit(1)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.P(`func extensionToGoString`, p.localName, `(m `, protoPkg.Use(), `.Message) string {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`e := `, protoPkg.Use(), `.GetUnsafeExtensionsMap(m)`)
 | 
				
			||||||
 | 
							p.P(`if e == nil { return "nil" }`)
 | 
				
			||||||
 | 
							p.P(`s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{"`)
 | 
				
			||||||
 | 
							p.P(`keys := make([]int, 0, len(e))`)
 | 
				
			||||||
 | 
							p.P(`for k := range e {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`keys = append(keys, int(k))`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(sortPkg.Use(), `.Ints(keys)`)
 | 
				
			||||||
 | 
							p.P(`ss := []string{}`)
 | 
				
			||||||
 | 
							p.P(`for _, k := range keys {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`ss = append(ss, `, strconvPkg.Use(), `.Itoa(k) + ": " + e[int32(k)].GoString())`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(`s+=`, stringsPkg.Use(), `.Join(ss, ",") + "})"`)
 | 
				
			||||||
 | 
							p.P(`return s`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(NewGoString())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package gostring
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/plugin/testgen"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type test struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewTest(g *generator.Generator) testgen.TestPlugin {
 | 
				
			||||||
 | 
						return &test{g}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
 | 
				
			||||||
 | 
						used := false
 | 
				
			||||||
 | 
						randPkg := imports.NewImport("math/rand")
 | 
				
			||||||
 | 
						timePkg := imports.NewImport("time")
 | 
				
			||||||
 | 
						testingPkg := imports.NewImport("testing")
 | 
				
			||||||
 | 
						fmtPkg := imports.NewImport("fmt")
 | 
				
			||||||
 | 
						parserPkg := imports.NewImport("go/parser")
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							if !gogoproto.HasGoString(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								used = true
 | 
				
			||||||
 | 
								p.P(`func Test`, ccTypeName, `GoString(t *`, testingPkg.Use(), `.T) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
 | 
				
			||||||
 | 
								p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
 | 
				
			||||||
 | 
								p.P(`s1 := p.GoString()`)
 | 
				
			||||||
 | 
								p.P(`s2 := `, fmtPkg.Use(), `.Sprintf("%#v", p)`)
 | 
				
			||||||
 | 
								p.P(`if s1 != s2 {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("GoString want %v got %v", s1, s2)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`_, err := `, parserPkg.Use(), `.ParseExpr(s1)`)
 | 
				
			||||||
 | 
								p.P(`if err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatal(err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return used
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						testgen.RegisterTestPlugin(NewTest)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								@ -0,0 +1,93 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					The oneofcheck plugin is used to check whether oneof is not used incorrectly.
 | 
				
			||||||
 | 
					For instance:
 | 
				
			||||||
 | 
					An error is caused if a oneof field:
 | 
				
			||||||
 | 
					  - is used in a face
 | 
				
			||||||
 | 
					  - is an embedded field
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package oneofcheck
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type plugin struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewPlugin() *plugin {
 | 
				
			||||||
 | 
						return &plugin{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Name() string {
 | 
				
			||||||
 | 
						return "oneofcheck"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						for _, msg := range file.Messages() {
 | 
				
			||||||
 | 
							face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto)
 | 
				
			||||||
 | 
							for _, field := range msg.GetField() {
 | 
				
			||||||
 | 
								if field.OneofIndex == nil {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if face {
 | 
				
			||||||
 | 
									fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in a face and oneof\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
 | 
				
			||||||
 | 
									os.Exit(1)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if gogoproto.IsEmbed(field) {
 | 
				
			||||||
 | 
									fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and an embedded field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
 | 
				
			||||||
 | 
									os.Exit(1)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if !gogoproto.IsNullable(field) {
 | 
				
			||||||
 | 
									fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and a non-nullable field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
 | 
				
			||||||
 | 
									os.Exit(1)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if gogoproto.IsUnion(file.FileDescriptorProto, msg.DescriptorProto) {
 | 
				
			||||||
 | 
									fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and in an union (deprecated)\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
 | 
				
			||||||
 | 
									os.Exit(1)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) GenerateImports(*generator.FileDescriptor) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(NewPlugin())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,815 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					The populate plugin generates a NewPopulated function.
 | 
				
			||||||
 | 
					This function returns a newly populated structure.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is enabled by the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - populate
 | 
				
			||||||
 | 
					  - populate_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let us look at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/example.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Btw all the output can be seen at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following message:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  option (gogoproto.populate_all) = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  message B {
 | 
				
			||||||
 | 
						optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
 | 
				
			||||||
 | 
						repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					given to the populate plugin, will generate code the following code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  func NewPopulatedB(r randyExample, easy bool) *B {
 | 
				
			||||||
 | 
						this := &B{}
 | 
				
			||||||
 | 
						v2 := NewPopulatedA(r, easy)
 | 
				
			||||||
 | 
						this.A = *v2
 | 
				
			||||||
 | 
						if r.Intn(10) != 0 {
 | 
				
			||||||
 | 
							v3 := r.Intn(10)
 | 
				
			||||||
 | 
							this.G = make([]github_com_gogo_protobuf_test_custom.Uint128, v3)
 | 
				
			||||||
 | 
							for i := 0; i < v3; i++ {
 | 
				
			||||||
 | 
								v4 := github_com_gogo_protobuf_test_custom.NewPopulatedUint128(r)
 | 
				
			||||||
 | 
								this.G[i] = *v4
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !easy && r.Intn(10) != 0 {
 | 
				
			||||||
 | 
							this.XXX_unrecognized = randUnrecognizedExample(r, 3)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return this
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The idea that is useful for testing.
 | 
				
			||||||
 | 
					Most of the other plugins' generated test code uses it.
 | 
				
			||||||
 | 
					You will still be able to use the generated test code of other packages
 | 
				
			||||||
 | 
					if you turn off the popluate plugin and write your own custom NewPopulated function.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the easy flag is not set the XXX_unrecognized and XXX_extensions fields are also populated.
 | 
				
			||||||
 | 
					These have caused problems with JSON marshalling and unmarshalling tests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package populate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"math"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/vanity"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type VarGen interface {
 | 
				
			||||||
 | 
						Next() string
 | 
				
			||||||
 | 
						Current() string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type varGen struct {
 | 
				
			||||||
 | 
						index int64
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewVarGen() VarGen {
 | 
				
			||||||
 | 
						return &varGen{0}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *varGen) Next() string {
 | 
				
			||||||
 | 
						this.index++
 | 
				
			||||||
 | 
						return fmt.Sprintf("v%d", this.index)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *varGen) Current() string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("v%d", this.index)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type plugin struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
						generator.PluginImports
 | 
				
			||||||
 | 
						varGen     VarGen
 | 
				
			||||||
 | 
						atleastOne bool
 | 
				
			||||||
 | 
						localName  string
 | 
				
			||||||
 | 
						typesPkg   generator.Single
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewPlugin() *plugin {
 | 
				
			||||||
 | 
						return &plugin{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Name() string {
 | 
				
			||||||
 | 
						return "populate"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func value(typeName string, fieldType descriptor.FieldDescriptorProto_Type) string {
 | 
				
			||||||
 | 
						switch fieldType {
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
 | 
				
			||||||
 | 
							return typeName + "(r.Float64())"
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_FLOAT:
 | 
				
			||||||
 | 
							return typeName + "(r.Float32())"
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_INT64,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_SFIXED64,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_SINT64:
 | 
				
			||||||
 | 
							return typeName + "(r.Int63())"
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_UINT64,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_FIXED64:
 | 
				
			||||||
 | 
							return typeName + "(uint64(r.Uint32()))"
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_INT32,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_SINT32,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_SFIXED32,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_ENUM:
 | 
				
			||||||
 | 
							return typeName + "(r.Int31())"
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_UINT32,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_FIXED32:
 | 
				
			||||||
 | 
							return typeName + "(r.Uint32())"
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_BOOL:
 | 
				
			||||||
 | 
							return typeName + `(bool(r.Intn(2) == 0))`
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_STRING,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_GROUP,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_MESSAGE,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_BYTES:
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						panic(fmt.Errorf("unexpected type %v", typeName))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func negative(fieldType descriptor.FieldDescriptorProto_Type) bool {
 | 
				
			||||||
 | 
						switch fieldType {
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_UINT64,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_FIXED64,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_UINT32,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_FIXED32,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_BOOL:
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) getFuncName(goTypName string, field *descriptor.FieldDescriptorProto) string {
 | 
				
			||||||
 | 
						funcName := "NewPopulated" + goTypName
 | 
				
			||||||
 | 
						goTypNames := strings.Split(goTypName, ".")
 | 
				
			||||||
 | 
						if len(goTypNames) == 2 {
 | 
				
			||||||
 | 
							funcName = goTypNames[0] + ".NewPopulated" + goTypNames[1]
 | 
				
			||||||
 | 
						} else if len(goTypNames) != 1 {
 | 
				
			||||||
 | 
							panic(fmt.Errorf("unreachable: too many dots in %v", goTypName))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if field != nil {
 | 
				
			||||||
 | 
							switch {
 | 
				
			||||||
 | 
							case gogoproto.IsStdTime(field):
 | 
				
			||||||
 | 
								funcName = p.typesPkg.Use() + ".NewPopulatedStdTime"
 | 
				
			||||||
 | 
							case gogoproto.IsStdDuration(field):
 | 
				
			||||||
 | 
								funcName = p.typesPkg.Use() + ".NewPopulatedStdDuration"
 | 
				
			||||||
 | 
							case gogoproto.IsStdDouble(field):
 | 
				
			||||||
 | 
								funcName = p.typesPkg.Use() + ".NewPopulatedStdDouble"
 | 
				
			||||||
 | 
							case gogoproto.IsStdFloat(field):
 | 
				
			||||||
 | 
								funcName = p.typesPkg.Use() + ".NewPopulatedStdFloat"
 | 
				
			||||||
 | 
							case gogoproto.IsStdInt64(field):
 | 
				
			||||||
 | 
								funcName = p.typesPkg.Use() + ".NewPopulatedStdInt64"
 | 
				
			||||||
 | 
							case gogoproto.IsStdUInt64(field):
 | 
				
			||||||
 | 
								funcName = p.typesPkg.Use() + ".NewPopulatedStdUInt64"
 | 
				
			||||||
 | 
							case gogoproto.IsStdInt32(field):
 | 
				
			||||||
 | 
								funcName = p.typesPkg.Use() + ".NewPopulatedStdInt32"
 | 
				
			||||||
 | 
							case gogoproto.IsStdUInt32(field):
 | 
				
			||||||
 | 
								funcName = p.typesPkg.Use() + ".NewPopulatedStdUInt32"
 | 
				
			||||||
 | 
							case gogoproto.IsStdBool(field):
 | 
				
			||||||
 | 
								funcName = p.typesPkg.Use() + ".NewPopulatedStdBool"
 | 
				
			||||||
 | 
							case gogoproto.IsStdString(field):
 | 
				
			||||||
 | 
								funcName = p.typesPkg.Use() + ".NewPopulatedStdString"
 | 
				
			||||||
 | 
							case gogoproto.IsStdBytes(field):
 | 
				
			||||||
 | 
								funcName = p.typesPkg.Use() + ".NewPopulatedStdBytes"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return funcName
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) getFuncCall(goTypName string, field *descriptor.FieldDescriptorProto) string {
 | 
				
			||||||
 | 
						funcName := p.getFuncName(goTypName, field)
 | 
				
			||||||
 | 
						funcCall := funcName + "(r, easy)"
 | 
				
			||||||
 | 
						return funcCall
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) getCustomFuncCall(goTypName string) string {
 | 
				
			||||||
 | 
						funcName := p.getFuncName(goTypName, nil)
 | 
				
			||||||
 | 
						funcCall := funcName + "(r)"
 | 
				
			||||||
 | 
						return funcCall
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) getEnumVal(field *descriptor.FieldDescriptorProto, goTyp string) string {
 | 
				
			||||||
 | 
						enum := p.ObjectNamed(field.GetTypeName()).(*generator.EnumDescriptor)
 | 
				
			||||||
 | 
						l := len(enum.Value)
 | 
				
			||||||
 | 
						values := make([]string, l)
 | 
				
			||||||
 | 
						for i := range enum.Value {
 | 
				
			||||||
 | 
							values[i] = strconv.Itoa(int(*enum.Value[i].Number))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						arr := "[]int32{" + strings.Join(values, ",") + "}"
 | 
				
			||||||
 | 
						val := strings.Join([]string{generator.GoTypeToName(goTyp), `(`, arr, `[r.Intn(`, fmt.Sprintf("%d", l), `)])`}, "")
 | 
				
			||||||
 | 
						return val
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) GenerateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
 | 
				
			||||||
 | 
						proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
 | 
				
			||||||
 | 
						goTyp, _ := p.GoType(message, field)
 | 
				
			||||||
 | 
						fieldname := p.GetOneOfFieldName(message, field)
 | 
				
			||||||
 | 
						goTypName := generator.GoTypeToName(goTyp)
 | 
				
			||||||
 | 
						if p.IsMap(field) {
 | 
				
			||||||
 | 
							m := p.GoMapType(nil, field)
 | 
				
			||||||
 | 
							keygoTyp, _ := p.GoType(nil, m.KeyField)
 | 
				
			||||||
 | 
							keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
 | 
				
			||||||
 | 
							keygoAliasTyp, _ := p.GoType(nil, m.KeyAliasField)
 | 
				
			||||||
 | 
							keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							valuegoTyp, _ := p.GoType(nil, m.ValueField)
 | 
				
			||||||
 | 
							valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
 | 
				
			||||||
 | 
							keytypName := generator.GoTypeToName(keygoTyp)
 | 
				
			||||||
 | 
							keygoAliasTyp = generator.GoTypeToName(keygoAliasTyp)
 | 
				
			||||||
 | 
							valuetypAliasName := generator.GoTypeToName(valuegoAliasTyp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							nullable, valuegoTyp, valuegoAliasTyp := generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p.P(p.varGen.Next(), ` := r.Intn(10)`)
 | 
				
			||||||
 | 
							p.P(`this.`, fieldname, ` = make(`, m.GoType, `)`)
 | 
				
			||||||
 | 
							p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							keyval := ""
 | 
				
			||||||
 | 
							if m.KeyField.IsString() {
 | 
				
			||||||
 | 
								keyval = fmt.Sprintf("randString%v(r)", p.localName)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								keyval = value(keytypName, m.KeyField.GetType())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if keygoAliasTyp != keygoTyp {
 | 
				
			||||||
 | 
								keyval = keygoAliasTyp + `(` + keyval + `)`
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if m.ValueField.IsMessage() || p.IsGroup(field) ||
 | 
				
			||||||
 | 
								(m.ValueField.IsBytes() && gogoproto.IsCustomType(field)) {
 | 
				
			||||||
 | 
								s := `this.` + fieldname + `[` + keyval + `] = `
 | 
				
			||||||
 | 
								if gogoproto.IsStdType(field) {
 | 
				
			||||||
 | 
									valuegoTyp = valuegoAliasTyp
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								funcCall := p.getCustomFuncCall(goTypName)
 | 
				
			||||||
 | 
								if !gogoproto.IsCustomType(field) {
 | 
				
			||||||
 | 
									goTypName = generator.GoTypeToName(valuegoTyp)
 | 
				
			||||||
 | 
									funcCall = p.getFuncCall(goTypName, m.ValueAliasField)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if !nullable {
 | 
				
			||||||
 | 
									funcCall = `*` + funcCall
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if valuegoTyp != valuegoAliasTyp {
 | 
				
			||||||
 | 
									funcCall = `(` + valuegoAliasTyp + `)(` + funcCall + `)`
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								s += funcCall
 | 
				
			||||||
 | 
								p.P(s)
 | 
				
			||||||
 | 
							} else if m.ValueField.IsEnum() {
 | 
				
			||||||
 | 
								s := `this.` + fieldname + `[` + keyval + `]` + ` = ` + p.getEnumVal(m.ValueField, valuegoTyp)
 | 
				
			||||||
 | 
								p.P(s)
 | 
				
			||||||
 | 
							} else if m.ValueField.IsBytes() {
 | 
				
			||||||
 | 
								count := p.varGen.Next()
 | 
				
			||||||
 | 
								p.P(count, ` := r.Intn(100)`)
 | 
				
			||||||
 | 
								p.P(p.varGen.Next(), ` := `, keyval)
 | 
				
			||||||
 | 
								p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] = make(`, valuegoTyp, `, `, count, `)`)
 | 
				
			||||||
 | 
								p.P(`for i := 0; i < `, count, `; i++ {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`this.`, fieldname, `[`, p.varGen.Current(), `][i] = byte(r.Intn(256))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if m.ValueField.IsString() {
 | 
				
			||||||
 | 
								s := `this.` + fieldname + `[` + keyval + `]` + ` = ` + fmt.Sprintf("randString%v(r)", p.localName)
 | 
				
			||||||
 | 
								p.P(s)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.P(p.varGen.Next(), ` := `, keyval)
 | 
				
			||||||
 | 
								p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] = `, value(valuetypAliasName, m.ValueField.GetType()))
 | 
				
			||||||
 | 
								if negative(m.ValueField.GetType()) {
 | 
				
			||||||
 | 
									p.P(`if r.Intn(2) == 0 {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] *= -1`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
						} else if gogoproto.IsCustomType(field) {
 | 
				
			||||||
 | 
							funcCall := p.getCustomFuncCall(goTypName)
 | 
				
			||||||
 | 
							if field.IsRepeated() {
 | 
				
			||||||
 | 
								p.P(p.varGen.Next(), ` := r.Intn(10)`)
 | 
				
			||||||
 | 
								p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
 | 
				
			||||||
 | 
								p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(p.varGen.Next(), `:= `, funcCall)
 | 
				
			||||||
 | 
								p.P(`this.`, fieldname, `[i] = *`, p.varGen.Current())
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if gogoproto.IsNullable(field) {
 | 
				
			||||||
 | 
								p.P(`this.`, fieldname, ` = `, funcCall)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.P(p.varGen.Next(), `:= `, funcCall)
 | 
				
			||||||
 | 
								p.P(`this.`, fieldname, ` = *`, p.varGen.Current())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if field.IsMessage() || p.IsGroup(field) {
 | 
				
			||||||
 | 
							funcCall := p.getFuncCall(goTypName, field)
 | 
				
			||||||
 | 
							if field.IsRepeated() {
 | 
				
			||||||
 | 
								p.P(p.varGen.Next(), ` := r.Intn(5)`)
 | 
				
			||||||
 | 
								p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
 | 
				
			||||||
 | 
								p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if gogoproto.IsNullable(field) {
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, `[i] = `, funcCall)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(p.varGen.Next(), `:= `, funcCall)
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, `[i] = *`, p.varGen.Current())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if gogoproto.IsNullable(field) {
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, ` = `, funcCall)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(p.varGen.Next(), `:= `, funcCall)
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, ` = *`, p.varGen.Current())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if field.IsEnum() {
 | 
				
			||||||
 | 
								val := p.getEnumVal(field, goTyp)
 | 
				
			||||||
 | 
								if field.IsRepeated() {
 | 
				
			||||||
 | 
									p.P(p.varGen.Next(), ` := r.Intn(10)`)
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
 | 
				
			||||||
 | 
									p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, `[i] = `, val)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else if !gogoproto.IsNullable(field) || proto3 {
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, ` = `, val)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(p.varGen.Next(), ` := `, val)
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if field.IsBytes() {
 | 
				
			||||||
 | 
								if field.IsRepeated() {
 | 
				
			||||||
 | 
									p.P(p.varGen.Next(), ` := r.Intn(10)`)
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
 | 
				
			||||||
 | 
									p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(p.varGen.Next(), ` := r.Intn(100)`)
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, `[i] = make([]byte,`, p.varGen.Current(), `)`)
 | 
				
			||||||
 | 
									p.P(`for j := 0; j < `, p.varGen.Current(), `; j++ {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, `[i][j] = byte(r.Intn(256))`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(p.varGen.Next(), ` := r.Intn(100)`)
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
 | 
				
			||||||
 | 
									p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, `[i] = byte(r.Intn(256))`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if field.IsString() {
 | 
				
			||||||
 | 
								typName := generator.GoTypeToName(goTyp)
 | 
				
			||||||
 | 
								val := fmt.Sprintf("%s(randString%v(r))", typName, p.localName)
 | 
				
			||||||
 | 
								if field.IsRepeated() {
 | 
				
			||||||
 | 
									p.P(p.varGen.Next(), ` := r.Intn(10)`)
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
 | 
				
			||||||
 | 
									p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, `[i] = `, val)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else if !gogoproto.IsNullable(field) || proto3 {
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, ` = `, val)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(p.varGen.Next(), `:= `, val)
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								typName := generator.GoTypeToName(goTyp)
 | 
				
			||||||
 | 
								if field.IsRepeated() {
 | 
				
			||||||
 | 
									p.P(p.varGen.Next(), ` := r.Intn(10)`)
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
 | 
				
			||||||
 | 
									p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, `[i] = `, value(typName, field.GetType()))
 | 
				
			||||||
 | 
									if negative(field.GetType()) {
 | 
				
			||||||
 | 
										p.P(`if r.Intn(2) == 0 {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`this.`, fieldname, `[i] *= -1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else if !gogoproto.IsNullable(field) || proto3 {
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, ` = `, value(typName, field.GetType()))
 | 
				
			||||||
 | 
									if negative(field.GetType()) {
 | 
				
			||||||
 | 
										p.P(`if r.Intn(2) == 0 {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`this.`, fieldname, ` *= -1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(p.varGen.Next(), ` := `, value(typName, field.GetType()))
 | 
				
			||||||
 | 
									if negative(field.GetType()) {
 | 
				
			||||||
 | 
										p.P(`if r.Intn(2) == 0 {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(p.varGen.Current(), ` *= -1`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) hasLoop(pkg string, field *descriptor.FieldDescriptorProto, visited []*generator.Descriptor, excludes []*generator.Descriptor) *generator.Descriptor {
 | 
				
			||||||
 | 
						if field.IsMessage() || p.IsGroup(field) || p.IsMap(field) {
 | 
				
			||||||
 | 
							var fieldMessage *generator.Descriptor
 | 
				
			||||||
 | 
							if p.IsMap(field) {
 | 
				
			||||||
 | 
								m := p.GoMapType(nil, field)
 | 
				
			||||||
 | 
								if !m.ValueField.IsMessage() {
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								fieldMessage = p.ObjectNamed(m.ValueField.GetTypeName()).(*generator.Descriptor)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								fieldMessage = p.ObjectNamed(field.GetTypeName()).(*generator.Descriptor)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fieldTypeName := generator.CamelCaseSlice(fieldMessage.TypeName())
 | 
				
			||||||
 | 
							for _, message := range visited {
 | 
				
			||||||
 | 
								messageTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
								if fieldTypeName == messageTypeName {
 | 
				
			||||||
 | 
									for _, e := range excludes {
 | 
				
			||||||
 | 
										if fieldTypeName == generator.CamelCaseSlice(e.TypeName()) {
 | 
				
			||||||
 | 
											return nil
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return fieldMessage
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, f := range fieldMessage.Field {
 | 
				
			||||||
 | 
								if strings.HasPrefix(f.GetTypeName(), "."+pkg) {
 | 
				
			||||||
 | 
									visited = append(visited, fieldMessage)
 | 
				
			||||||
 | 
									loopTo := p.hasLoop(pkg, f, visited, excludes)
 | 
				
			||||||
 | 
									if loopTo != nil {
 | 
				
			||||||
 | 
										return loopTo
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) loops(pkg string, field *descriptor.FieldDescriptorProto, message *generator.Descriptor) int {
 | 
				
			||||||
 | 
						//fmt.Fprintf(os.Stderr, "loops %v %v\n", field.GetTypeName(), generator.CamelCaseSlice(message.TypeName()))
 | 
				
			||||||
 | 
						excludes := []*generator.Descriptor{}
 | 
				
			||||||
 | 
						loops := 0
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							visited := []*generator.Descriptor{}
 | 
				
			||||||
 | 
							loopTo := p.hasLoop(pkg, field, visited, excludes)
 | 
				
			||||||
 | 
							if loopTo == nil {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							//fmt.Fprintf(os.Stderr, "loopTo %v\n", generator.CamelCaseSlice(loopTo.TypeName()))
 | 
				
			||||||
 | 
							excludes = append(excludes, loopTo)
 | 
				
			||||||
 | 
							loops++
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return loops
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						p.atleastOne = false
 | 
				
			||||||
 | 
						p.PluginImports = generator.NewPluginImports(p.Generator)
 | 
				
			||||||
 | 
						p.varGen = NewVarGen()
 | 
				
			||||||
 | 
						proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
 | 
				
			||||||
 | 
						p.typesPkg = p.NewImport("github.com/gogo/protobuf/types")
 | 
				
			||||||
 | 
						p.localName = generator.FileName(file)
 | 
				
			||||||
 | 
						protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
 | 
				
			||||||
 | 
						if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
 | 
				
			||||||
 | 
							protoPkg = p.NewImport("github.com/golang/protobuf/proto")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							if !gogoproto.HasPopulate(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.atleastOne = true
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							loopLevels := make([]int, len(message.Field))
 | 
				
			||||||
 | 
							maxLoopLevel := 0
 | 
				
			||||||
 | 
							for i, field := range message.Field {
 | 
				
			||||||
 | 
								loopLevels[i] = p.loops(file.GetPackage(), field, message)
 | 
				
			||||||
 | 
								if loopLevels[i] > maxLoopLevel {
 | 
				
			||||||
 | 
									maxLoopLevel = loopLevels[i]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ranTotal := 0
 | 
				
			||||||
 | 
							for i := range loopLevels {
 | 
				
			||||||
 | 
								ranTotal += int(math.Pow10(maxLoopLevel - loopLevels[i]))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.P(`func NewPopulated`, ccTypeName, `(r randy`, p.localName, `, easy bool) *`, ccTypeName, ` {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`this := &`, ccTypeName, `{}`)
 | 
				
			||||||
 | 
							if gogoproto.IsUnion(message.File().FileDescriptorProto, message.DescriptorProto) && len(message.Field) > 0 {
 | 
				
			||||||
 | 
								p.P(`fieldNum := r.Intn(`, fmt.Sprintf("%d", ranTotal), `)`)
 | 
				
			||||||
 | 
								p.P(`switch fieldNum {`)
 | 
				
			||||||
 | 
								k := 0
 | 
				
			||||||
 | 
								for i, field := range message.Field {
 | 
				
			||||||
 | 
									is := []string{}
 | 
				
			||||||
 | 
									ran := int(math.Pow10(maxLoopLevel - loopLevels[i]))
 | 
				
			||||||
 | 
									for j := 0; j < ran; j++ {
 | 
				
			||||||
 | 
										is = append(is, fmt.Sprintf("%d", j+k))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									k += ran
 | 
				
			||||||
 | 
									p.P(`case `, strings.Join(is, ","), `:`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.GenerateField(file, message, field)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								var maxFieldNumber int32
 | 
				
			||||||
 | 
								oneofs := make(map[string]struct{})
 | 
				
			||||||
 | 
								for fieldIndex, field := range message.Field {
 | 
				
			||||||
 | 
									if field.GetNumber() > maxFieldNumber {
 | 
				
			||||||
 | 
										maxFieldNumber = field.GetNumber()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									oneof := field.OneofIndex != nil
 | 
				
			||||||
 | 
									if !oneof {
 | 
				
			||||||
 | 
										if field.IsRequired() || (!gogoproto.IsNullable(field) && !field.IsRepeated()) || (proto3 && !field.IsMessage()) {
 | 
				
			||||||
 | 
											p.GenerateField(file, message, field)
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											if loopLevels[fieldIndex] > 0 {
 | 
				
			||||||
 | 
												p.P(`if r.Intn(5) == 0 {`)
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												p.P(`if r.Intn(5) != 0 {`)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											p.In()
 | 
				
			||||||
 | 
											p.GenerateField(file, message, field)
 | 
				
			||||||
 | 
											p.Out()
 | 
				
			||||||
 | 
											p.P(`}`)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
										if _, ok := oneofs[fieldname]; ok {
 | 
				
			||||||
 | 
											continue
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											oneofs[fieldname] = struct{}{}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										fieldNumbers := []int32{}
 | 
				
			||||||
 | 
										for _, f := range message.Field {
 | 
				
			||||||
 | 
											fname := p.GetFieldName(message, f)
 | 
				
			||||||
 | 
											if fname == fieldname {
 | 
				
			||||||
 | 
												fieldNumbers = append(fieldNumbers, f.GetNumber())
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										p.P(`oneofNumber_`, fieldname, ` := `, fmt.Sprintf("%#v", fieldNumbers), `[r.Intn(`, strconv.Itoa(len(fieldNumbers)), `)]`)
 | 
				
			||||||
 | 
										p.P(`switch oneofNumber_`, fieldname, ` {`)
 | 
				
			||||||
 | 
										for _, f := range message.Field {
 | 
				
			||||||
 | 
											fname := p.GetFieldName(message, f)
 | 
				
			||||||
 | 
											if fname != fieldname {
 | 
				
			||||||
 | 
												continue
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											p.P(`case `, strconv.Itoa(int(f.GetNumber())), `:`)
 | 
				
			||||||
 | 
											p.In()
 | 
				
			||||||
 | 
											ccTypeName := p.OneOfTypeName(message, f)
 | 
				
			||||||
 | 
											p.P(`this.`, fname, ` = NewPopulated`, ccTypeName, `(r, easy)`)
 | 
				
			||||||
 | 
											p.Out()
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if message.DescriptorProto.HasExtension() {
 | 
				
			||||||
 | 
									p.P(`if !easy && r.Intn(10) != 0 {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`l := r.Intn(5)`)
 | 
				
			||||||
 | 
									p.P(`for i := 0; i < l; i++ {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									if len(message.DescriptorProto.GetExtensionRange()) > 1 {
 | 
				
			||||||
 | 
										p.P(`eIndex := r.Intn(`, strconv.Itoa(len(message.DescriptorProto.GetExtensionRange())), `)`)
 | 
				
			||||||
 | 
										p.P(`fieldNumber := 0`)
 | 
				
			||||||
 | 
										p.P(`switch eIndex {`)
 | 
				
			||||||
 | 
										for i, e := range message.DescriptorProto.GetExtensionRange() {
 | 
				
			||||||
 | 
											p.P(`case `, strconv.Itoa(i), `:`)
 | 
				
			||||||
 | 
											p.In()
 | 
				
			||||||
 | 
											p.P(`fieldNumber = r.Intn(`, strconv.Itoa(int(e.GetEnd()-e.GetStart())), `) + `, strconv.Itoa(int(e.GetStart())))
 | 
				
			||||||
 | 
											p.Out()
 | 
				
			||||||
 | 
											if e.GetEnd() > maxFieldNumber {
 | 
				
			||||||
 | 
												maxFieldNumber = e.GetEnd()
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										e := message.DescriptorProto.GetExtensionRange()[0]
 | 
				
			||||||
 | 
										p.P(`fieldNumber := r.Intn(`, strconv.Itoa(int(e.GetEnd()-e.GetStart())), `) + `, strconv.Itoa(int(e.GetStart())))
 | 
				
			||||||
 | 
										if e.GetEnd() > maxFieldNumber {
 | 
				
			||||||
 | 
											maxFieldNumber = e.GetEnd()
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.P(`wire := r.Intn(4)`)
 | 
				
			||||||
 | 
									p.P(`if wire == 3 { wire = 5 }`)
 | 
				
			||||||
 | 
									p.P(`dAtA := randField`, p.localName, `(nil, r, fieldNumber, wire)`)
 | 
				
			||||||
 | 
									p.P(protoPkg.Use(), `.SetRawExtension(this, int32(fieldNumber), dAtA)`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if maxFieldNumber < (1 << 10) {
 | 
				
			||||||
 | 
									p.P(`if !easy && r.Intn(10) != 0 {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
										p.P(`this.XXX_unrecognized = randUnrecognized`, p.localName, `(r, `, strconv.Itoa(int(maxFieldNumber+1)), `)`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.P(`return this`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(``)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//Generate NewPopulated functions for oneof fields
 | 
				
			||||||
 | 
							m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
 | 
				
			||||||
 | 
							for _, f := range m.Field {
 | 
				
			||||||
 | 
								oneof := f.OneofIndex != nil
 | 
				
			||||||
 | 
								if !oneof {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								ccTypeName := p.OneOfTypeName(message, f)
 | 
				
			||||||
 | 
								p.P(`func NewPopulated`, ccTypeName, `(r randy`, p.localName, `, easy bool) *`, ccTypeName, ` {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`this := &`, ccTypeName, `{}`)
 | 
				
			||||||
 | 
								vanity.TurnOffNullableForNativeTypes(f)
 | 
				
			||||||
 | 
								p.GenerateField(file, message, f)
 | 
				
			||||||
 | 
								p.P(`return this`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !p.atleastOne {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.P(`type randy`, p.localName, ` interface {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`Float32() float32`)
 | 
				
			||||||
 | 
						p.P(`Float64() float64`)
 | 
				
			||||||
 | 
						p.P(`Int63() int64`)
 | 
				
			||||||
 | 
						p.P(`Int31() int32`)
 | 
				
			||||||
 | 
						p.P(`Uint32() uint32`)
 | 
				
			||||||
 | 
						p.P(`Intn(n int) int`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.P(`func randUTF8Rune`, p.localName, `(r randy`, p.localName, `) rune {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`ru := r.Intn(62)`)
 | 
				
			||||||
 | 
						p.P(`if ru < 10 {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`return rune(ru+48)`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`} else if ru < 36 {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`return rune(ru+55)`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(`return rune(ru+61)`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.P(`func randString`, p.localName, `(r randy`, p.localName, `) string {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(p.varGen.Next(), ` := r.Intn(100)`)
 | 
				
			||||||
 | 
						p.P(`tmps := make([]rune, `, p.varGen.Current(), `)`)
 | 
				
			||||||
 | 
						p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`tmps[i] = randUTF8Rune`, p.localName, `(r)`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(`return string(tmps)`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.P(`func randUnrecognized`, p.localName, `(r randy`, p.localName, `, maxFieldNumber int) (dAtA []byte) {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`l := r.Intn(5)`)
 | 
				
			||||||
 | 
						p.P(`for i := 0; i < l; i++ {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`wire := r.Intn(4)`)
 | 
				
			||||||
 | 
						p.P(`if wire == 3 { wire = 5 }`)
 | 
				
			||||||
 | 
						p.P(`fieldNumber := maxFieldNumber + r.Intn(100)`)
 | 
				
			||||||
 | 
						p.P(`dAtA = randField`, p.localName, `(dAtA, r, fieldNumber, wire)`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(`return dAtA`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.P(`func randField`, p.localName, `(dAtA []byte, r randy`, p.localName, `, fieldNumber int, wire int) []byte {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`key := uint32(fieldNumber)<<3 | uint32(wire)`)
 | 
				
			||||||
 | 
						p.P(`switch wire {`)
 | 
				
			||||||
 | 
						p.P(`case 0:`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
 | 
				
			||||||
 | 
						p.P(p.varGen.Next(), ` := r.Int63()`)
 | 
				
			||||||
 | 
						p.P(`if r.Intn(2) == 0 {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(p.varGen.Current(), ` *= -1`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(`, p.varGen.Current(), `))`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`case 1:`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
 | 
				
			||||||
 | 
						p.P(`dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`case 2:`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
 | 
				
			||||||
 | 
						p.P(`ll := r.Intn(100)`)
 | 
				
			||||||
 | 
						p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(ll))`)
 | 
				
			||||||
 | 
						p.P(`for j := 0; j < ll; j++ {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`dAtA = append(dAtA, byte(r.Intn(256)))`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`default:`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
 | 
				
			||||||
 | 
						p.P(`dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(`return dAtA`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.P(`func encodeVarintPopulate`, p.localName, `(dAtA []byte, v uint64) []byte {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`for v >= 1<<7 {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80))`)
 | 
				
			||||||
 | 
						p.P(`v >>= 7`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(`dAtA = append(dAtA, uint8(v))`)
 | 
				
			||||||
 | 
						p.P(`return dAtA`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(NewPlugin())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,696 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					The size plugin generates a Size or ProtoSize method for each message.
 | 
				
			||||||
 | 
					This is useful with the MarshalTo method generated by the marshalto plugin and the
 | 
				
			||||||
 | 
					gogoproto.marshaler and gogoproto.marshaler_all extensions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is enabled by the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - sizer
 | 
				
			||||||
 | 
					  - sizer_all
 | 
				
			||||||
 | 
					  - protosizer
 | 
				
			||||||
 | 
					  - protosizer_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The size plugin also generates a test given it is enabled using one of the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - testgen
 | 
				
			||||||
 | 
					  - testgen_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					And a benchmark given it is enabled using one of the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - benchgen
 | 
				
			||||||
 | 
					  - benchgen_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let us look at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/example.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Btw all the output can be seen at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following message:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  option (gogoproto.sizer_all) = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  message B {
 | 
				
			||||||
 | 
						option (gogoproto.description) = true;
 | 
				
			||||||
 | 
						optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
 | 
				
			||||||
 | 
						repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					given to the size plugin, will generate the following code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  func (m *B) Size() (n int) {
 | 
				
			||||||
 | 
						if m == nil {
 | 
				
			||||||
 | 
							return 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var l int
 | 
				
			||||||
 | 
						_ = l
 | 
				
			||||||
 | 
						l = m.A.Size()
 | 
				
			||||||
 | 
						n += 1 + l + sovExample(uint64(l))
 | 
				
			||||||
 | 
						if len(m.G) > 0 {
 | 
				
			||||||
 | 
							for _, e := range m.G {
 | 
				
			||||||
 | 
								l = e.Size()
 | 
				
			||||||
 | 
								n += 1 + l + sovExample(uint64(l))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if m.XXX_unrecognized != nil {
 | 
				
			||||||
 | 
							n += len(m.XXX_unrecognized)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return n
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and the following test code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func TestBSize(t *testing5.T) {
 | 
				
			||||||
 | 
							popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano()))
 | 
				
			||||||
 | 
							p := NewPopulatedB(popr, true)
 | 
				
			||||||
 | 
							dAtA, err := github_com_gogo_protobuf_proto2.Marshal(p)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							size := p.Size()
 | 
				
			||||||
 | 
							if len(dAtA) != size {
 | 
				
			||||||
 | 
								t.Fatalf("size %v != marshalled size %v", size, len(dAtA))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func BenchmarkBSize(b *testing5.B) {
 | 
				
			||||||
 | 
							popr := math_rand5.New(math_rand5.NewSource(616))
 | 
				
			||||||
 | 
							total := 0
 | 
				
			||||||
 | 
							pops := make([]*B, 1000)
 | 
				
			||||||
 | 
							for i := 0; i < 1000; i++ {
 | 
				
			||||||
 | 
								pops[i] = NewPopulatedB(popr, false)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							b.ResetTimer()
 | 
				
			||||||
 | 
							for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
								total += pops[i%1000].Size()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							b.SetBytes(int64(total / b.N))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The sovExample function is a size of varint function for the example.pb.go file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/vanity"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type size struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
						generator.PluginImports
 | 
				
			||||||
 | 
						atleastOne bool
 | 
				
			||||||
 | 
						localName  string
 | 
				
			||||||
 | 
						typesPkg   generator.Single
 | 
				
			||||||
 | 
						bitsPkg    generator.Single
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewSize() *size {
 | 
				
			||||||
 | 
						return &size{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *size) Name() string {
 | 
				
			||||||
 | 
						return "size"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *size) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func wireToType(wire string) int {
 | 
				
			||||||
 | 
						switch wire {
 | 
				
			||||||
 | 
						case "fixed64":
 | 
				
			||||||
 | 
							return proto.WireFixed64
 | 
				
			||||||
 | 
						case "fixed32":
 | 
				
			||||||
 | 
							return proto.WireFixed32
 | 
				
			||||||
 | 
						case "varint":
 | 
				
			||||||
 | 
							return proto.WireVarint
 | 
				
			||||||
 | 
						case "bytes":
 | 
				
			||||||
 | 
							return proto.WireBytes
 | 
				
			||||||
 | 
						case "group":
 | 
				
			||||||
 | 
							return proto.WireBytes
 | 
				
			||||||
 | 
						case "zigzag32":
 | 
				
			||||||
 | 
							return proto.WireVarint
 | 
				
			||||||
 | 
						case "zigzag64":
 | 
				
			||||||
 | 
							return proto.WireVarint
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						panic("unreachable")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func keySize(fieldNumber int32, wireType int) int {
 | 
				
			||||||
 | 
						x := uint32(fieldNumber)<<3 | uint32(wireType)
 | 
				
			||||||
 | 
						size := 0
 | 
				
			||||||
 | 
						for size = 0; x > 127; size++ {
 | 
				
			||||||
 | 
							x >>= 7
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						size++
 | 
				
			||||||
 | 
						return size
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *size) sizeVarint() {
 | 
				
			||||||
 | 
						p.P(`
 | 
				
			||||||
 | 
						func sov`, p.localName, `(x uint64) (n int) {
 | 
				
			||||||
 | 
					                return (`, p.bitsPkg.Use(), `.Len64(x | 1) + 6)/ 7
 | 
				
			||||||
 | 
						}`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *size) sizeZigZag() {
 | 
				
			||||||
 | 
						p.P(`func soz`, p.localName, `(x uint64) (n int) {
 | 
				
			||||||
 | 
							return sov`, p.localName, `(uint64((x << 1) ^ uint64((int64(x) >> 63))))
 | 
				
			||||||
 | 
						}`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *size) std(field *descriptor.FieldDescriptorProto, name string) (string, bool) {
 | 
				
			||||||
 | 
						ptr := ""
 | 
				
			||||||
 | 
						if gogoproto.IsNullable(field) {
 | 
				
			||||||
 | 
							ptr = "*"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if gogoproto.IsStdTime(field) {
 | 
				
			||||||
 | 
							return p.typesPkg.Use() + `.SizeOfStdTime(` + ptr + name + `)`, true
 | 
				
			||||||
 | 
						} else if gogoproto.IsStdDuration(field) {
 | 
				
			||||||
 | 
							return p.typesPkg.Use() + `.SizeOfStdDuration(` + ptr + name + `)`, true
 | 
				
			||||||
 | 
						} else if gogoproto.IsStdDouble(field) {
 | 
				
			||||||
 | 
							return p.typesPkg.Use() + `.SizeOfStdDouble(` + ptr + name + `)`, true
 | 
				
			||||||
 | 
						} else if gogoproto.IsStdFloat(field) {
 | 
				
			||||||
 | 
							return p.typesPkg.Use() + `.SizeOfStdFloat(` + ptr + name + `)`, true
 | 
				
			||||||
 | 
						} else if gogoproto.IsStdInt64(field) {
 | 
				
			||||||
 | 
							return p.typesPkg.Use() + `.SizeOfStdInt64(` + ptr + name + `)`, true
 | 
				
			||||||
 | 
						} else if gogoproto.IsStdUInt64(field) {
 | 
				
			||||||
 | 
							return p.typesPkg.Use() + `.SizeOfStdUInt64(` + ptr + name + `)`, true
 | 
				
			||||||
 | 
						} else if gogoproto.IsStdInt32(field) {
 | 
				
			||||||
 | 
							return p.typesPkg.Use() + `.SizeOfStdInt32(` + ptr + name + `)`, true
 | 
				
			||||||
 | 
						} else if gogoproto.IsStdUInt32(field) {
 | 
				
			||||||
 | 
							return p.typesPkg.Use() + `.SizeOfStdUInt32(` + ptr + name + `)`, true
 | 
				
			||||||
 | 
						} else if gogoproto.IsStdBool(field) {
 | 
				
			||||||
 | 
							return p.typesPkg.Use() + `.SizeOfStdBool(` + ptr + name + `)`, true
 | 
				
			||||||
 | 
						} else if gogoproto.IsStdString(field) {
 | 
				
			||||||
 | 
							return p.typesPkg.Use() + `.SizeOfStdString(` + ptr + name + `)`, true
 | 
				
			||||||
 | 
						} else if gogoproto.IsStdBytes(field) {
 | 
				
			||||||
 | 
							return p.typesPkg.Use() + `.SizeOfStdBytes(` + ptr + name + `)`, true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "", false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *size) generateField(proto3 bool, file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto, sizeName string) {
 | 
				
			||||||
 | 
						fieldname := p.GetOneOfFieldName(message, field)
 | 
				
			||||||
 | 
						nullable := gogoproto.IsNullable(field)
 | 
				
			||||||
 | 
						repeated := field.IsRepeated()
 | 
				
			||||||
 | 
						doNilCheck := gogoproto.NeedsNilCheck(proto3, field)
 | 
				
			||||||
 | 
						if repeated {
 | 
				
			||||||
 | 
							p.P(`if len(m.`, fieldname, `) > 0 {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
						} else if doNilCheck {
 | 
				
			||||||
 | 
							p.P(`if m.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						packed := field.IsPacked() || (proto3 && field.IsPacked3())
 | 
				
			||||||
 | 
						_, wire := p.GoType(message, field)
 | 
				
			||||||
 | 
						wireType := wireToType(wire)
 | 
				
			||||||
 | 
						fieldNumber := field.GetNumber()
 | 
				
			||||||
 | 
						if packed {
 | 
				
			||||||
 | 
							wireType = proto.WireBytes
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						key := keySize(fieldNumber, wireType)
 | 
				
			||||||
 | 
						switch *field.Type {
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_FIXED64,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_SFIXED64:
 | 
				
			||||||
 | 
							if packed {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)*8))`, `+len(m.`, fieldname, `)*8`)
 | 
				
			||||||
 | 
							} else if repeated {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key+8), `*len(m.`, fieldname, `)`)
 | 
				
			||||||
 | 
							} else if proto3 {
 | 
				
			||||||
 | 
								p.P(`if m.`, fieldname, ` != 0 {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key+8))
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if nullable {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key+8))
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key+8))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_FLOAT,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_FIXED32,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_SFIXED32:
 | 
				
			||||||
 | 
							if packed {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)*4))`, `+len(m.`, fieldname, `)*4`)
 | 
				
			||||||
 | 
							} else if repeated {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key+4), `*len(m.`, fieldname, `)`)
 | 
				
			||||||
 | 
							} else if proto3 {
 | 
				
			||||||
 | 
								p.P(`if m.`, fieldname, ` != 0 {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key+4))
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if nullable {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key+4))
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key+4))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_INT64,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_UINT64,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_UINT32,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_ENUM,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_INT32:
 | 
				
			||||||
 | 
							if packed {
 | 
				
			||||||
 | 
								p.P(`l = 0`)
 | 
				
			||||||
 | 
								p.P(`for _, e := range m.`, fieldname, ` {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`l+=sov`, p.localName, `(uint64(e))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(l))+l`)
 | 
				
			||||||
 | 
							} else if repeated {
 | 
				
			||||||
 | 
								p.P(`for _, e := range m.`, fieldname, ` {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(e))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if proto3 {
 | 
				
			||||||
 | 
								p.P(`if m.`, fieldname, ` != 0 {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(m.`, fieldname, `))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if nullable {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(*m.`, fieldname, `))`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(m.`, fieldname, `))`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_BOOL:
 | 
				
			||||||
 | 
							if packed {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)))`, `+len(m.`, fieldname, `)*1`)
 | 
				
			||||||
 | 
							} else if repeated {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key+1), `*len(m.`, fieldname, `)`)
 | 
				
			||||||
 | 
							} else if proto3 {
 | 
				
			||||||
 | 
								p.P(`if m.`, fieldname, ` {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key+1))
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if nullable {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key+1))
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key+1))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_STRING:
 | 
				
			||||||
 | 
							if repeated {
 | 
				
			||||||
 | 
								p.P(`for _, s := range m.`, fieldname, ` { `)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`l = len(s)`)
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if proto3 {
 | 
				
			||||||
 | 
								p.P(`l=len(m.`, fieldname, `)`)
 | 
				
			||||||
 | 
								p.P(`if l > 0 {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if nullable {
 | 
				
			||||||
 | 
								p.P(`l=len(*m.`, fieldname, `)`)
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.P(`l=len(m.`, fieldname, `)`)
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_GROUP:
 | 
				
			||||||
 | 
							panic(fmt.Errorf("size does not support group %v", fieldname))
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
 | 
				
			||||||
 | 
							if p.IsMap(field) {
 | 
				
			||||||
 | 
								m := p.GoMapType(nil, field)
 | 
				
			||||||
 | 
								_, keywire := p.GoType(nil, m.KeyAliasField)
 | 
				
			||||||
 | 
								valuegoTyp, _ := p.GoType(nil, m.ValueField)
 | 
				
			||||||
 | 
								valuegoAliasTyp, valuewire := p.GoType(nil, m.ValueAliasField)
 | 
				
			||||||
 | 
								_, fieldwire := p.GoType(nil, field)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								fieldKeySize := keySize(field.GetNumber(), wireToType(fieldwire))
 | 
				
			||||||
 | 
								keyKeySize := keySize(1, wireToType(keywire))
 | 
				
			||||||
 | 
								valueKeySize := keySize(2, wireToType(valuewire))
 | 
				
			||||||
 | 
								p.P(`for k, v := range m.`, fieldname, ` { `)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`_ = k`)
 | 
				
			||||||
 | 
								p.P(`_ = v`)
 | 
				
			||||||
 | 
								sum := []string{strconv.Itoa(keyKeySize)}
 | 
				
			||||||
 | 
								switch m.KeyField.GetType() {
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_FIXED64,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_SFIXED64:
 | 
				
			||||||
 | 
									sum = append(sum, `8`)
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_FLOAT,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_FIXED32,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_SFIXED32:
 | 
				
			||||||
 | 
									sum = append(sum, `4`)
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_INT64,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_UINT64,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_UINT32,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_ENUM,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_INT32:
 | 
				
			||||||
 | 
									sum = append(sum, `sov`+p.localName+`(uint64(k))`)
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_BOOL:
 | 
				
			||||||
 | 
									sum = append(sum, `1`)
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_STRING,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_BYTES:
 | 
				
			||||||
 | 
									sum = append(sum, `len(k)+sov`+p.localName+`(uint64(len(k)))`)
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_SINT32,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_SINT64:
 | 
				
			||||||
 | 
									sum = append(sum, `soz`+p.localName+`(uint64(k))`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								switch m.ValueField.GetType() {
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_FIXED64,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_SFIXED64:
 | 
				
			||||||
 | 
									sum = append(sum, strconv.Itoa(valueKeySize))
 | 
				
			||||||
 | 
									sum = append(sum, strconv.Itoa(8))
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_FLOAT,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_FIXED32,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_SFIXED32:
 | 
				
			||||||
 | 
									sum = append(sum, strconv.Itoa(valueKeySize))
 | 
				
			||||||
 | 
									sum = append(sum, strconv.Itoa(4))
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_INT64,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_UINT64,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_UINT32,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_ENUM,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_INT32:
 | 
				
			||||||
 | 
									sum = append(sum, strconv.Itoa(valueKeySize))
 | 
				
			||||||
 | 
									sum = append(sum, `sov`+p.localName+`(uint64(v))`)
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_BOOL:
 | 
				
			||||||
 | 
									sum = append(sum, strconv.Itoa(valueKeySize))
 | 
				
			||||||
 | 
									sum = append(sum, `1`)
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_STRING:
 | 
				
			||||||
 | 
									sum = append(sum, strconv.Itoa(valueKeySize))
 | 
				
			||||||
 | 
									sum = append(sum, `len(v)+sov`+p.localName+`(uint64(len(v)))`)
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_BYTES:
 | 
				
			||||||
 | 
									if gogoproto.IsCustomType(field) {
 | 
				
			||||||
 | 
										p.P(`l = 0`)
 | 
				
			||||||
 | 
										if nullable {
 | 
				
			||||||
 | 
											p.P(`if v != nil {`)
 | 
				
			||||||
 | 
											p.In()
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										p.P(`l = v.`, sizeName, `()`)
 | 
				
			||||||
 | 
										p.P(`l += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(l))`)
 | 
				
			||||||
 | 
										if nullable {
 | 
				
			||||||
 | 
											p.Out()
 | 
				
			||||||
 | 
											p.P(`}`)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										sum = append(sum, `l`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`l = 0`)
 | 
				
			||||||
 | 
										if proto3 {
 | 
				
			||||||
 | 
											p.P(`if len(v) > 0 {`)
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											p.P(`if v != nil {`)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`l = `, strconv.Itoa(valueKeySize), ` + len(v)+sov`+p.localName+`(uint64(len(v)))`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
										sum = append(sum, `l`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_SINT32,
 | 
				
			||||||
 | 
									descriptor.FieldDescriptorProto_TYPE_SINT64:
 | 
				
			||||||
 | 
									sum = append(sum, strconv.Itoa(valueKeySize))
 | 
				
			||||||
 | 
									sum = append(sum, `soz`+p.localName+`(uint64(v))`)
 | 
				
			||||||
 | 
								case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
 | 
				
			||||||
 | 
									stdSizeCall, stdOk := p.std(m.ValueAliasField, "v")
 | 
				
			||||||
 | 
									if nullable {
 | 
				
			||||||
 | 
										p.P(`l = 0`)
 | 
				
			||||||
 | 
										p.P(`if v != nil {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										if stdOk {
 | 
				
			||||||
 | 
											p.P(`l = `, stdSizeCall)
 | 
				
			||||||
 | 
										} else if valuegoTyp != valuegoAliasTyp {
 | 
				
			||||||
 | 
											p.P(`l = ((`, valuegoTyp, `)(v)).`, sizeName, `()`)
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											p.P(`l = v.`, sizeName, `()`)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										p.P(`l += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(l))`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
										sum = append(sum, `l`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										if stdOk {
 | 
				
			||||||
 | 
											p.P(`l = `, stdSizeCall)
 | 
				
			||||||
 | 
										} else if valuegoTyp != valuegoAliasTyp {
 | 
				
			||||||
 | 
											p.P(`l = ((*`, valuegoTyp, `)(&v)).`, sizeName, `()`)
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											p.P(`l = v.`, sizeName, `()`)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										sum = append(sum, strconv.Itoa(valueKeySize))
 | 
				
			||||||
 | 
										sum = append(sum, `l+sov`+p.localName+`(uint64(l))`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`mapEntrySize := `, strings.Join(sum, "+"))
 | 
				
			||||||
 | 
								p.P(`n+=mapEntrySize+`, fieldKeySize, `+sov`, p.localName, `(uint64(mapEntrySize))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if repeated {
 | 
				
			||||||
 | 
								p.P(`for _, e := range m.`, fieldname, ` { `)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								stdSizeCall, stdOk := p.std(field, "e")
 | 
				
			||||||
 | 
								if stdOk {
 | 
				
			||||||
 | 
									p.P(`l=`, stdSizeCall)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`l=e.`, sizeName, `()`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								stdSizeCall, stdOk := p.std(field, "m."+fieldname)
 | 
				
			||||||
 | 
								if stdOk {
 | 
				
			||||||
 | 
									p.P(`l=`, stdSizeCall)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`l=m.`, fieldname, `.`, sizeName, `()`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_BYTES:
 | 
				
			||||||
 | 
							if !gogoproto.IsCustomType(field) {
 | 
				
			||||||
 | 
								if repeated {
 | 
				
			||||||
 | 
									p.P(`for _, b := range m.`, fieldname, ` { `)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`l = len(b)`)
 | 
				
			||||||
 | 
									p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else if proto3 {
 | 
				
			||||||
 | 
									p.P(`l=len(m.`, fieldname, `)`)
 | 
				
			||||||
 | 
									p.P(`if l > 0 {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`l=len(m.`, fieldname, `)`)
 | 
				
			||||||
 | 
									p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if repeated {
 | 
				
			||||||
 | 
									p.P(`for _, e := range m.`, fieldname, ` { `)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`l=e.`, sizeName, `()`)
 | 
				
			||||||
 | 
									p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`l=m.`, fieldname, `.`, sizeName, `()`)
 | 
				
			||||||
 | 
									p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case descriptor.FieldDescriptorProto_TYPE_SINT32,
 | 
				
			||||||
 | 
							descriptor.FieldDescriptorProto_TYPE_SINT64:
 | 
				
			||||||
 | 
							if packed {
 | 
				
			||||||
 | 
								p.P(`l = 0`)
 | 
				
			||||||
 | 
								p.P(`for _, e := range m.`, fieldname, ` {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`l+=soz`, p.localName, `(uint64(e))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(l))+l`)
 | 
				
			||||||
 | 
							} else if repeated {
 | 
				
			||||||
 | 
								p.P(`for _, e := range m.`, fieldname, ` {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(e))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if proto3 {
 | 
				
			||||||
 | 
								p.P(`if m.`, fieldname, ` != 0 {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(m.`, fieldname, `))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							} else if nullable {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(*m.`, fieldname, `))`)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(m.`, fieldname, `))`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							panic("not implemented")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if repeated || doNilCheck {
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *size) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						p.PluginImports = generator.NewPluginImports(p.Generator)
 | 
				
			||||||
 | 
						p.atleastOne = false
 | 
				
			||||||
 | 
						p.localName = generator.FileName(file)
 | 
				
			||||||
 | 
						p.typesPkg = p.NewImport("github.com/gogo/protobuf/types")
 | 
				
			||||||
 | 
						protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
 | 
				
			||||||
 | 
						p.bitsPkg = p.NewImport("math/bits")
 | 
				
			||||||
 | 
						if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
 | 
				
			||||||
 | 
							protoPkg = p.NewImport("github.com/golang/protobuf/proto")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							sizeName := ""
 | 
				
			||||||
 | 
							if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) && gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								fmt.Fprintf(os.Stderr, "ERROR: message %v cannot support both sizer and protosizer plugins\n", generator.CamelCase(*message.Name))
 | 
				
			||||||
 | 
								os.Exit(1)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								sizeName = "Size"
 | 
				
			||||||
 | 
							} else if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								sizeName = "ProtoSize"
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.atleastOne = true
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							p.P(`func (m *`, ccTypeName, `) `, sizeName, `() (n int) {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`if m == nil {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`return 0`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(`var l int`)
 | 
				
			||||||
 | 
							p.P(`_ = l`)
 | 
				
			||||||
 | 
							oneofs := make(map[string]struct{})
 | 
				
			||||||
 | 
							for _, field := range message.Field {
 | 
				
			||||||
 | 
								oneof := field.OneofIndex != nil
 | 
				
			||||||
 | 
								if !oneof {
 | 
				
			||||||
 | 
									proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
 | 
				
			||||||
 | 
									p.generateField(proto3, file, message, field, sizeName)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
									if _, ok := oneofs[fieldname]; ok {
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										oneofs[fieldname] = struct{}{}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.P(`if m.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`n+=m.`, fieldname, `.`, sizeName, `()`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.HasExtension() {
 | 
				
			||||||
 | 
								if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
									p.P(`n += `, protoPkg.Use(), `.SizeOfInternalExtension(m)`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(`if m.XXX_extensions != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`n+=len(m.XXX_extensions)`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								p.P(`if m.XXX_unrecognized != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`n+=len(m.XXX_unrecognized)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.P(`return n`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//Generate Size methods for oneof fields
 | 
				
			||||||
 | 
							m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
 | 
				
			||||||
 | 
							for _, f := range m.Field {
 | 
				
			||||||
 | 
								oneof := f.OneofIndex != nil
 | 
				
			||||||
 | 
								if !oneof {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								ccTypeName := p.OneOfTypeName(message, f)
 | 
				
			||||||
 | 
								p.P(`func (m *`, ccTypeName, `) `, sizeName, `() (n int) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`if m == nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return 0`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`var l int`)
 | 
				
			||||||
 | 
								p.P(`_ = l`)
 | 
				
			||||||
 | 
								vanity.TurnOffNullableForNativeTypes(f)
 | 
				
			||||||
 | 
								p.generateField(false, file, message, f, sizeName)
 | 
				
			||||||
 | 
								p.P(`return n`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !p.atleastOne {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.sizeVarint()
 | 
				
			||||||
 | 
						p.sizeZigZag()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(NewSize())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,134 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/plugin/testgen"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type test struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewTest(g *generator.Generator) testgen.TestPlugin {
 | 
				
			||||||
 | 
						return &test{g}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
 | 
				
			||||||
 | 
						used := false
 | 
				
			||||||
 | 
						randPkg := imports.NewImport("math/rand")
 | 
				
			||||||
 | 
						timePkg := imports.NewImport("time")
 | 
				
			||||||
 | 
						testingPkg := imports.NewImport("testing")
 | 
				
			||||||
 | 
						protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
 | 
				
			||||||
 | 
						if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
 | 
				
			||||||
 | 
							protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							sizeName := ""
 | 
				
			||||||
 | 
							if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								sizeName = "Size"
 | 
				
			||||||
 | 
							} else if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								sizeName = "ProtoSize"
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								used = true
 | 
				
			||||||
 | 
								p.P(`func Test`, ccTypeName, sizeName, `(t *`, testingPkg.Use(), `.T) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
 | 
				
			||||||
 | 
								p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
 | 
				
			||||||
 | 
								p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
 | 
				
			||||||
 | 
								p.P(`size2 := `, protoPkg.Use(), `.Size(p)`)
 | 
				
			||||||
 | 
								p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
 | 
				
			||||||
 | 
								p.P(`if err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`size := p.`, sizeName, `()`)
 | 
				
			||||||
 | 
								p.P(`if len(dAtA) != size {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`if size2 != size {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`size3 := `, protoPkg.Use(), `.Size(p)`)
 | 
				
			||||||
 | 
								p.P(`if size3 != size {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if gogoproto.HasBenchGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								used = true
 | 
				
			||||||
 | 
								p.P(`func Benchmark`, ccTypeName, sizeName, `(b *`, testingPkg.Use(), `.B) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
 | 
				
			||||||
 | 
								p.P(`total := 0`)
 | 
				
			||||||
 | 
								p.P(`pops := make([]*`, ccTypeName, `, 1000)`)
 | 
				
			||||||
 | 
								p.P(`for i := 0; i < 1000; i++ {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`pops[i] = NewPopulated`, ccTypeName, `(popr, false)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`b.ResetTimer()`)
 | 
				
			||||||
 | 
								p.P(`for i := 0; i < b.N; i++ {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`total += pops[i%1000].`, sizeName, `()`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`b.SetBytes(int64(total / b.N))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return used
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						testgen.RegisterTestPlugin(NewTest)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,347 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					The stringer plugin generates a String method for each message.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is enabled by the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - stringer
 | 
				
			||||||
 | 
					  - stringer_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The stringer plugin also generates a test given it is enabled using one of the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - testgen
 | 
				
			||||||
 | 
					  - testgen_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let us look at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/example.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Btw all the output can be seen at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following message:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  option (gogoproto.goproto_stringer_all) = false;
 | 
				
			||||||
 | 
					  option (gogoproto.stringer_all) =  true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  message A {
 | 
				
			||||||
 | 
						optional string Description = 1 [(gogoproto.nullable) = false];
 | 
				
			||||||
 | 
						optional int64 Number = 2 [(gogoproto.nullable) = false];
 | 
				
			||||||
 | 
						optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					given to the stringer stringer, will generate the following code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  func (this *A) String() string {
 | 
				
			||||||
 | 
						if this == nil {
 | 
				
			||||||
 | 
							return "nil"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s := strings.Join([]string{`&A{`,
 | 
				
			||||||
 | 
							`Description:` + fmt.Sprintf("%v", this.Description) + `,`,
 | 
				
			||||||
 | 
							`Number:` + fmt.Sprintf("%v", this.Number) + `,`,
 | 
				
			||||||
 | 
							`Id:` + fmt.Sprintf("%v", this.Id) + `,`,
 | 
				
			||||||
 | 
							`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
 | 
				
			||||||
 | 
							`}`,
 | 
				
			||||||
 | 
						}, "")
 | 
				
			||||||
 | 
						return s
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and the following test code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func TestAStringer(t *testing4.T) {
 | 
				
			||||||
 | 
							popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano()))
 | 
				
			||||||
 | 
							p := NewPopulatedA(popr, false)
 | 
				
			||||||
 | 
							s1 := p.String()
 | 
				
			||||||
 | 
							s2 := fmt1.Sprintf("%v", p)
 | 
				
			||||||
 | 
							if s1 != s2 {
 | 
				
			||||||
 | 
								t.Fatalf("String want %v got %v", s1, s2)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Typically fmt.Printf("%v") will stop to print when it reaches a pointer and
 | 
				
			||||||
 | 
					not print their values, while the generated String method will always print all values, recursively.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package stringer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type stringer struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
						generator.PluginImports
 | 
				
			||||||
 | 
						atleastOne bool
 | 
				
			||||||
 | 
						localName  string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewStringer() *stringer {
 | 
				
			||||||
 | 
						return &stringer{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *stringer) Name() string {
 | 
				
			||||||
 | 
						return "stringer"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *stringer) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *stringer) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
 | 
				
			||||||
 | 
						p.PluginImports = generator.NewPluginImports(p.Generator)
 | 
				
			||||||
 | 
						p.atleastOne = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.localName = generator.FileName(file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmtPkg := p.NewImport("fmt")
 | 
				
			||||||
 | 
						stringsPkg := p.NewImport("strings")
 | 
				
			||||||
 | 
						reflectPkg := p.NewImport("reflect")
 | 
				
			||||||
 | 
						sortKeysPkg := p.NewImport("github.com/gogo/protobuf/sortkeys")
 | 
				
			||||||
 | 
						protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							if !gogoproto.IsStringer(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if gogoproto.EnabledGoStringer(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								panic("old string method needs to be disabled, please use gogoproto.goproto_stringer or gogoproto.goproto_stringer_all and set it to false")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.atleastOne = true
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							p.P(`func (this *`, ccTypeName, `) String() string {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`if this == nil {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`return "nil"`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							for _, field := range message.Field {
 | 
				
			||||||
 | 
								if p.IsMap(field) || !field.IsRepeated() {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (field.IsMessage() && !gogoproto.IsCustomType(field)) || p.IsGroup(field) {
 | 
				
			||||||
 | 
									nullable := gogoproto.IsNullable(field)
 | 
				
			||||||
 | 
									desc := p.ObjectNamed(field.GetTypeName())
 | 
				
			||||||
 | 
									msgname := p.TypeName(desc)
 | 
				
			||||||
 | 
									msgnames := strings.Split(msgname, ".")
 | 
				
			||||||
 | 
									typeName := msgnames[len(msgnames)-1]
 | 
				
			||||||
 | 
									fieldMessageDesc := file.GetMessage(msgname)
 | 
				
			||||||
 | 
									gogoStringer := false
 | 
				
			||||||
 | 
									if fieldMessageDesc != nil {
 | 
				
			||||||
 | 
										gogoStringer = gogoproto.IsStringer(file.FileDescriptorProto, fieldMessageDesc)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
									stringfunc := fmtPkg.Use() + `.Sprintf("%v", f)`
 | 
				
			||||||
 | 
									if gogoStringer {
 | 
				
			||||||
 | 
										stringfunc = `f.String()`
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									repeatedName := `repeatedStringFor` + fieldname
 | 
				
			||||||
 | 
									if nullable {
 | 
				
			||||||
 | 
										p.P(repeatedName, ` := "[]*`, typeName, `{"`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(repeatedName, ` := "[]`, typeName, `{"`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									p.P(`for _, f := range `, `this.`, fieldname, ` {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									if nullable {
 | 
				
			||||||
 | 
										p.P(repeatedName, " += ", stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1)", ` + ","`)
 | 
				
			||||||
 | 
									} else if gogoStringer {
 | 
				
			||||||
 | 
										p.P(repeatedName, " += ", stringsPkg.Use(), `.Replace(`, stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1),`&`,``,1)", ` + ","`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(repeatedName, " += ", stringfunc, ` + ","`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.P(repeatedName, ` += "}"`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for _, field := range message.Field {
 | 
				
			||||||
 | 
								if !p.IsMap(field) {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								m := p.GoMapType(nil, field)
 | 
				
			||||||
 | 
								mapgoTyp, keyField, keyAliasField := m.GoType, m.KeyField, m.KeyAliasField
 | 
				
			||||||
 | 
								keysName := `keysFor` + fieldname
 | 
				
			||||||
 | 
								keygoTyp, _ := p.GoType(nil, keyField)
 | 
				
			||||||
 | 
								keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
 | 
				
			||||||
 | 
								keygoAliasTyp, _ := p.GoType(nil, keyAliasField)
 | 
				
			||||||
 | 
								keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
 | 
				
			||||||
 | 
								keyCapTyp := generator.CamelCase(keygoTyp)
 | 
				
			||||||
 | 
								p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(this.`, fieldname, `))`)
 | 
				
			||||||
 | 
								p.P(`for k, _ := range this.`, fieldname, ` {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if keygoAliasTyp == keygoTyp {
 | 
				
			||||||
 | 
									p.P(keysName, ` = append(`, keysName, `, k)`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
 | 
				
			||||||
 | 
								mapName := `mapStringFor` + fieldname
 | 
				
			||||||
 | 
								p.P(mapName, ` := "`, mapgoTyp, `{"`)
 | 
				
			||||||
 | 
								p.P(`for _, k := range `, keysName, ` {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								if keygoAliasTyp == keygoTyp {
 | 
				
			||||||
 | 
									p.P(mapName, ` += fmt.Sprintf("%v: %v,", k, this.`, fieldname, `[k])`)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P(mapName, ` += fmt.Sprintf("%v: %v,", k, this.`, fieldname, `[`, keygoAliasTyp, `(k)])`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(mapName, ` += "}"`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.P("s := ", stringsPkg.Use(), ".Join([]string{`&", ccTypeName, "{`,")
 | 
				
			||||||
 | 
							oneofs := make(map[string]struct{})
 | 
				
			||||||
 | 
							for _, field := range message.Field {
 | 
				
			||||||
 | 
								nullable := gogoproto.IsNullable(field)
 | 
				
			||||||
 | 
								repeated := field.IsRepeated()
 | 
				
			||||||
 | 
								fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
								oneof := field.OneofIndex != nil
 | 
				
			||||||
 | 
								if oneof {
 | 
				
			||||||
 | 
									if _, ok := oneofs[fieldname]; ok {
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										oneofs[fieldname] = struct{}{}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
 | 
				
			||||||
 | 
								} else if p.IsMap(field) {
 | 
				
			||||||
 | 
									mapName := `mapStringFor` + fieldname
 | 
				
			||||||
 | 
									p.P("`", fieldname, ":`", ` + `, mapName, " + `,", "`,")
 | 
				
			||||||
 | 
								} else if (field.IsMessage() && !gogoproto.IsCustomType(field)) || p.IsGroup(field) {
 | 
				
			||||||
 | 
									desc := p.ObjectNamed(field.GetTypeName())
 | 
				
			||||||
 | 
									msgname := p.TypeName(desc)
 | 
				
			||||||
 | 
									msgnames := strings.Split(msgname, ".")
 | 
				
			||||||
 | 
									typeName := msgnames[len(msgnames)-1]
 | 
				
			||||||
 | 
									fieldMessageDesc := file.GetMessage(msgname)
 | 
				
			||||||
 | 
									gogoStringer := false
 | 
				
			||||||
 | 
									if fieldMessageDesc != nil {
 | 
				
			||||||
 | 
										gogoStringer = gogoproto.IsStringer(file.FileDescriptorProto, fieldMessageDesc)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									stringfunc := fmtPkg.Use() + `.Sprintf("%v", this.` + fieldname + `)`
 | 
				
			||||||
 | 
									if gogoStringer {
 | 
				
			||||||
 | 
										stringfunc = `this.` + fieldname + `.String()`
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if nullable && !repeated {
 | 
				
			||||||
 | 
										p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1) + `,", "`,")
 | 
				
			||||||
 | 
									} else if repeated {
 | 
				
			||||||
 | 
										repeatedName := `repeatedStringFor` + fieldname
 | 
				
			||||||
 | 
										p.P("`", fieldname, ":`", ` + `, repeatedName, " + `,", "`,")
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1),`&`,``,1) + `,", "`,")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									if nullable && !repeated && !proto3 {
 | 
				
			||||||
 | 
										p.P("`", fieldname, ":`", ` + valueToString`, p.localName, `(this.`, fieldname, ") + `,", "`,")
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.HasExtension() {
 | 
				
			||||||
 | 
								if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
									p.P("`XXX_InternalExtensions:` + ", protoPkg.Use(), ".StringFromInternalExtension(this) + `,`,")
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P("`XXX_extensions:` + ", protoPkg.Use(), ".StringFromExtensionsBytes(this.XXX_extensions) + `,`,")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								p.P("`XXX_unrecognized:` + ", fmtPkg.Use(), `.Sprintf("%v", this.XXX_unrecognized) + `, "`,`,")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.P("`}`,")
 | 
				
			||||||
 | 
							p.P(`}`, `,""`, ")")
 | 
				
			||||||
 | 
							p.P(`return s`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//Generate String methods for oneof fields
 | 
				
			||||||
 | 
							for _, field := range message.Field {
 | 
				
			||||||
 | 
								oneof := field.OneofIndex != nil
 | 
				
			||||||
 | 
								if !oneof {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								ccTypeName := p.OneOfTypeName(message, field)
 | 
				
			||||||
 | 
								p.P(`func (this *`, ccTypeName, `) String() string {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`if this == nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return "nil"`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P("s := ", stringsPkg.Use(), ".Join([]string{`&", ccTypeName, "{`,")
 | 
				
			||||||
 | 
								fieldname := p.GetOneOfFieldName(message, field)
 | 
				
			||||||
 | 
								if field.IsMessage() || p.IsGroup(field) {
 | 
				
			||||||
 | 
									desc := p.ObjectNamed(field.GetTypeName())
 | 
				
			||||||
 | 
									msgname := p.TypeName(desc)
 | 
				
			||||||
 | 
									msgnames := strings.Split(msgname, ".")
 | 
				
			||||||
 | 
									typeName := msgnames[len(msgnames)-1]
 | 
				
			||||||
 | 
									p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, `), "`, typeName, `","`, msgname, `"`, ", 1) + `,", "`,")
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P("`}`,")
 | 
				
			||||||
 | 
								p.P(`}`, `,""`, ")")
 | 
				
			||||||
 | 
								p.P(`return s`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !p.atleastOne {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.P(`func valueToString`, p.localName, `(v interface{}) string {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`rv := `, reflectPkg.Use(), `.ValueOf(v)`)
 | 
				
			||||||
 | 
						p.P(`if rv.IsNil() {`)
 | 
				
			||||||
 | 
						p.In()
 | 
				
			||||||
 | 
						p.P(`return "nil"`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
						p.P(`pv := `, reflectPkg.Use(), `.Indirect(rv).Interface()`)
 | 
				
			||||||
 | 
						p.P(`return `, fmtPkg.Use(), `.Sprintf("*%v", pv)`)
 | 
				
			||||||
 | 
						p.Out()
 | 
				
			||||||
 | 
						p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(NewStringer())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package stringer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/plugin/testgen"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type test struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewTest(g *generator.Generator) testgen.TestPlugin {
 | 
				
			||||||
 | 
						return &test{g}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
 | 
				
			||||||
 | 
						used := false
 | 
				
			||||||
 | 
						randPkg := imports.NewImport("math/rand")
 | 
				
			||||||
 | 
						timePkg := imports.NewImport("time")
 | 
				
			||||||
 | 
						testingPkg := imports.NewImport("testing")
 | 
				
			||||||
 | 
						fmtPkg := imports.NewImport("fmt")
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							if !gogoproto.IsStringer(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								used = true
 | 
				
			||||||
 | 
								p.P(`func Test`, ccTypeName, `Stringer(t *`, testingPkg.Use(), `.T) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
 | 
				
			||||||
 | 
								p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
 | 
				
			||||||
 | 
								p.P(`s1 := p.String()`)
 | 
				
			||||||
 | 
								p.P(`s2 := `, fmtPkg.Use(), `.Sprintf("%v", p)`)
 | 
				
			||||||
 | 
								p.P(`if s1 != s2 {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("String want %v got %v", s1, s2)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return used
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						testgen.RegisterTestPlugin(NewTest)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,608 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					The testgen plugin generates Test and Benchmark functions for each message.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Tests are enabled using the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - testgen
 | 
				
			||||||
 | 
					  - testgen_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Benchmarks are enabled using the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - benchgen
 | 
				
			||||||
 | 
					  - benchgen_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let us look at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/example.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Btw all the output can be seen at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following message:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  option (gogoproto.testgen_all) = true;
 | 
				
			||||||
 | 
					  option (gogoproto.benchgen_all) = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  message A {
 | 
				
			||||||
 | 
						optional string Description = 1 [(gogoproto.nullable) = false];
 | 
				
			||||||
 | 
						optional int64 Number = 2 [(gogoproto.nullable) = false];
 | 
				
			||||||
 | 
						optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					given to the testgen plugin, will generate the following test code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func TestAProto(t *testing.T) {
 | 
				
			||||||
 | 
							popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano()))
 | 
				
			||||||
 | 
							p := NewPopulatedA(popr, false)
 | 
				
			||||||
 | 
							dAtA, err := github_com_gogo_protobuf_proto.Marshal(p)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							msg := &A{}
 | 
				
			||||||
 | 
							if err := github_com_gogo_protobuf_proto.Unmarshal(dAtA, msg); err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for i := range dAtA {
 | 
				
			||||||
 | 
								dAtA[i] = byte(popr.Intn(256))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := p.VerboseEqual(msg); err != nil {
 | 
				
			||||||
 | 
								t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !p.Equal(msg) {
 | 
				
			||||||
 | 
								t.Fatalf("%#v !Proto %#v", msg, p)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func BenchmarkAProtoMarshal(b *testing.B) {
 | 
				
			||||||
 | 
							popr := math_rand.New(math_rand.NewSource(616))
 | 
				
			||||||
 | 
							total := 0
 | 
				
			||||||
 | 
							pops := make([]*A, 10000)
 | 
				
			||||||
 | 
							for i := 0; i < 10000; i++ {
 | 
				
			||||||
 | 
								pops[i] = NewPopulatedA(popr, false)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							b.ResetTimer()
 | 
				
			||||||
 | 
							for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
								dAtA, err := github_com_gogo_protobuf_proto.Marshal(pops[i%10000])
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									panic(err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								total += len(dAtA)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							b.SetBytes(int64(total / b.N))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func BenchmarkAProtoUnmarshal(b *testing.B) {
 | 
				
			||||||
 | 
							popr := math_rand.New(math_rand.NewSource(616))
 | 
				
			||||||
 | 
							total := 0
 | 
				
			||||||
 | 
							datas := make([][]byte, 10000)
 | 
				
			||||||
 | 
							for i := 0; i < 10000; i++ {
 | 
				
			||||||
 | 
								dAtA, err := github_com_gogo_protobuf_proto.Marshal(NewPopulatedA(popr, false))
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									panic(err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								datas[i] = dAtA
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							msg := &A{}
 | 
				
			||||||
 | 
							b.ResetTimer()
 | 
				
			||||||
 | 
							for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
								total += len(datas[i%10000])
 | 
				
			||||||
 | 
								if err := github_com_gogo_protobuf_proto.Unmarshal(datas[i%10000], msg); err != nil {
 | 
				
			||||||
 | 
									panic(err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							b.SetBytes(int64(total / b.N))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func TestAJSON(t *testing1.T) {
 | 
				
			||||||
 | 
							popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano()))
 | 
				
			||||||
 | 
							p := NewPopulatedA(popr, true)
 | 
				
			||||||
 | 
							jsondata, err := encoding_json.Marshal(p)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							msg := &A{}
 | 
				
			||||||
 | 
							err = encoding_json.Unmarshal(jsondata, msg)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := p.VerboseEqual(msg); err != nil {
 | 
				
			||||||
 | 
								t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !p.Equal(msg) {
 | 
				
			||||||
 | 
								t.Fatalf("%#v !Json Equal %#v", msg, p)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func TestAProtoText(t *testing2.T) {
 | 
				
			||||||
 | 
							popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano()))
 | 
				
			||||||
 | 
							p := NewPopulatedA(popr, true)
 | 
				
			||||||
 | 
							dAtA := github_com_gogo_protobuf_proto1.MarshalTextString(p)
 | 
				
			||||||
 | 
							msg := &A{}
 | 
				
			||||||
 | 
							if err := github_com_gogo_protobuf_proto1.UnmarshalText(dAtA, msg); err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := p.VerboseEqual(msg); err != nil {
 | 
				
			||||||
 | 
								t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !p.Equal(msg) {
 | 
				
			||||||
 | 
								t.Fatalf("%#v !Proto %#v", msg, p)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func TestAProtoCompactText(t *testing2.T) {
 | 
				
			||||||
 | 
							popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano()))
 | 
				
			||||||
 | 
							p := NewPopulatedA(popr, true)
 | 
				
			||||||
 | 
							dAtA := github_com_gogo_protobuf_proto1.CompactTextString(p)
 | 
				
			||||||
 | 
							msg := &A{}
 | 
				
			||||||
 | 
							if err := github_com_gogo_protobuf_proto1.UnmarshalText(dAtA, msg); err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := p.VerboseEqual(msg); err != nil {
 | 
				
			||||||
 | 
								t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !p.Equal(msg) {
 | 
				
			||||||
 | 
								t.Fatalf("%#v !Proto %#v", msg, p)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Other registered tests are also generated.
 | 
				
			||||||
 | 
					Tests are registered to this test plugin by calling the following function.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  func RegisterTestPlugin(newFunc NewTestPlugin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					where NewTestPlugin is:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  type NewTestPlugin func(g *generator.Generator) TestPlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and TestPlugin is an interface:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  type TestPlugin interface {
 | 
				
			||||||
 | 
						Generate(imports generator.PluginImports, file *generator.FileDescriptor) (used bool)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Plugins that use this interface include:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - populate
 | 
				
			||||||
 | 
					  - gostring
 | 
				
			||||||
 | 
					  - equal
 | 
				
			||||||
 | 
					  - union
 | 
				
			||||||
 | 
					  - and more
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please look at these plugins as examples of how to create your own.
 | 
				
			||||||
 | 
					A good idea is to let each plugin generate its own tests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package testgen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TestPlugin interface {
 | 
				
			||||||
 | 
						Generate(imports generator.PluginImports, file *generator.FileDescriptor) (used bool)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type NewTestPlugin func(g *generator.Generator) TestPlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var testplugins = make([]NewTestPlugin, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RegisterTestPlugin(newFunc NewTestPlugin) {
 | 
				
			||||||
 | 
						testplugins = append(testplugins, newFunc)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type plugin struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
						generator.PluginImports
 | 
				
			||||||
 | 
						tests []TestPlugin
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewPlugin() *plugin {
 | 
				
			||||||
 | 
						return &plugin{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Name() string {
 | 
				
			||||||
 | 
						return "testgen"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
						p.tests = make([]TestPlugin, 0, len(testplugins))
 | 
				
			||||||
 | 
						for i := range testplugins {
 | 
				
			||||||
 | 
							p.tests = append(p.tests, testplugins[i](g))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *plugin) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						p.PluginImports = generator.NewPluginImports(p.Generator)
 | 
				
			||||||
 | 
						atLeastOne := false
 | 
				
			||||||
 | 
						for i := range p.tests {
 | 
				
			||||||
 | 
							used := p.tests[i].Generate(p.PluginImports, file)
 | 
				
			||||||
 | 
							if used {
 | 
				
			||||||
 | 
								atLeastOne = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if atLeastOne {
 | 
				
			||||||
 | 
							p.P(`//These tests are generated by github.com/gogo/protobuf/plugin/testgen`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type testProto struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newProto(g *generator.Generator) TestPlugin {
 | 
				
			||||||
 | 
						return &testProto{g}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *testProto) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
 | 
				
			||||||
 | 
						used := false
 | 
				
			||||||
 | 
						testingPkg := imports.NewImport("testing")
 | 
				
			||||||
 | 
						randPkg := imports.NewImport("math/rand")
 | 
				
			||||||
 | 
						timePkg := imports.NewImport("time")
 | 
				
			||||||
 | 
						protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
 | 
				
			||||||
 | 
						if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
 | 
				
			||||||
 | 
							protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								used = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								p.P(`func Test`, ccTypeName, `Proto(t *`, testingPkg.Use(), `.T) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
 | 
				
			||||||
 | 
								p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
 | 
				
			||||||
 | 
								p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
 | 
				
			||||||
 | 
								p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
 | 
				
			||||||
 | 
								p.P(`if err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`msg := &`, ccTypeName, `{}`)
 | 
				
			||||||
 | 
								p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`littlefuzz := make([]byte, len(dAtA))`)
 | 
				
			||||||
 | 
								p.P(`copy(littlefuzz, dAtA)`)
 | 
				
			||||||
 | 
								p.P(`for i := range dAtA {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`dAtA[i] = byte(popr.Intn(256))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
									p.P(`if err := p.VerboseEqual(msg); err != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`if !p.Equal(msg) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`if len(littlefuzz) > 0 {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`fuzzamount := 100`)
 | 
				
			||||||
 | 
								p.P(`for i := 0; i < fuzzamount; i++ {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256))`)
 | 
				
			||||||
 | 
								p.P(`littlefuzz = append(littlefuzz, byte(popr.Intn(256)))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`// shouldn't panic`)
 | 
				
			||||||
 | 
								p.P(`_ = `, protoPkg.Use(), `.Unmarshal(littlefuzz, msg)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								if gogoproto.IsMarshaler(file.FileDescriptorProto, message.DescriptorProto) || gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
									p.P(`func Test`, ccTypeName, `MarshalTo(t *`, testingPkg.Use(), `.T) {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
 | 
				
			||||||
 | 
									p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
 | 
				
			||||||
 | 
									p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
 | 
				
			||||||
 | 
									if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
										p.P(`size := p.ProtoSize()`)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										p.P(`size := p.Size()`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.P(`dAtA := make([]byte, size)`)
 | 
				
			||||||
 | 
									p.P(`for i := range dAtA {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`dAtA[i] = byte(popr.Intn(256))`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.P(`_, err := p.MarshalTo(dAtA)`)
 | 
				
			||||||
 | 
									p.P(`if err != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.P(`msg := &`, ccTypeName, `{}`)
 | 
				
			||||||
 | 
									p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.P(`for i := range dAtA {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`dAtA[i] = byte(popr.Intn(256))`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
										p.P(`if err := p.VerboseEqual(msg); err != nil {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									p.P(`if !p.Equal(msg) {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
									p.P()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if gogoproto.HasBenchGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								used = true
 | 
				
			||||||
 | 
								p.P(`func Benchmark`, ccTypeName, `ProtoMarshal(b *`, testingPkg.Use(), `.B) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
 | 
				
			||||||
 | 
								p.P(`total := 0`)
 | 
				
			||||||
 | 
								p.P(`pops := make([]*`, ccTypeName, `, 10000)`)
 | 
				
			||||||
 | 
								p.P(`for i := 0; i < 10000; i++ {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`pops[i] = NewPopulated`, ccTypeName, `(popr, false)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`b.ResetTimer()`)
 | 
				
			||||||
 | 
								p.P(`for i := 0; i < b.N; i++ {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(pops[i%10000])`)
 | 
				
			||||||
 | 
								p.P(`if err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`panic(err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`total += len(dAtA)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`b.SetBytes(int64(total / b.N))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								p.P(`func Benchmark`, ccTypeName, `ProtoUnmarshal(b *`, testingPkg.Use(), `.B) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
 | 
				
			||||||
 | 
								p.P(`total := 0`)
 | 
				
			||||||
 | 
								p.P(`datas := make([][]byte, 10000)`)
 | 
				
			||||||
 | 
								p.P(`for i := 0; i < 10000; i++ {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(NewPopulated`, ccTypeName, `(popr, false))`)
 | 
				
			||||||
 | 
								p.P(`if err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`panic(err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`datas[i] = dAtA`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`msg := &`, ccTypeName, `{}`)
 | 
				
			||||||
 | 
								p.P(`b.ResetTimer()`)
 | 
				
			||||||
 | 
								p.P(`for i := 0; i < b.N; i++ {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`total += len(datas[i%10000])`)
 | 
				
			||||||
 | 
								p.P(`if err := `, protoPkg.Use(), `.Unmarshal(datas[i%10000], msg); err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`panic(err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`b.SetBytes(int64(total / b.N))`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return used
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type testJson struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newJson(g *generator.Generator) TestPlugin {
 | 
				
			||||||
 | 
						return &testJson{g}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *testJson) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
 | 
				
			||||||
 | 
						used := false
 | 
				
			||||||
 | 
						testingPkg := imports.NewImport("testing")
 | 
				
			||||||
 | 
						randPkg := imports.NewImport("math/rand")
 | 
				
			||||||
 | 
						timePkg := imports.NewImport("time")
 | 
				
			||||||
 | 
						jsonPkg := imports.NewImport("github.com/gogo/protobuf/jsonpb")
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								used = true
 | 
				
			||||||
 | 
								p.P(`func Test`, ccTypeName, `JSON(t *`, testingPkg.Use(), `.T) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
 | 
				
			||||||
 | 
								p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
 | 
				
			||||||
 | 
								p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
 | 
				
			||||||
 | 
								p.P(`marshaler := `, jsonPkg.Use(), `.Marshaler{}`)
 | 
				
			||||||
 | 
								p.P(`jsondata, err := marshaler.MarshalToString(p)`)
 | 
				
			||||||
 | 
								p.P(`if err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P(`msg := &`, ccTypeName, `{}`)
 | 
				
			||||||
 | 
								p.P(`err = `, jsonPkg.Use(), `.UnmarshalString(jsondata, msg)`)
 | 
				
			||||||
 | 
								p.P(`if err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
									p.P(`if err := p.VerboseEqual(msg); err != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`if !p.Equal(msg) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return used
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type testText struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newText(g *generator.Generator) TestPlugin {
 | 
				
			||||||
 | 
						return &testText{g}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *testText) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
 | 
				
			||||||
 | 
						used := false
 | 
				
			||||||
 | 
						testingPkg := imports.NewImport("testing")
 | 
				
			||||||
 | 
						randPkg := imports.NewImport("math/rand")
 | 
				
			||||||
 | 
						timePkg := imports.NewImport("time")
 | 
				
			||||||
 | 
						protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
 | 
				
			||||||
 | 
						if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
 | 
				
			||||||
 | 
							protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						//fmtPkg := imports.NewImport("fmt")
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								used = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								p.P(`func Test`, ccTypeName, `ProtoText(t *`, testingPkg.Use(), `.T) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
 | 
				
			||||||
 | 
								p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
 | 
				
			||||||
 | 
								p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
 | 
				
			||||||
 | 
								p.P(`dAtA := `, protoPkg.Use(), `.MarshalTextString(p)`)
 | 
				
			||||||
 | 
								p.P(`msg := &`, ccTypeName, `{}`)
 | 
				
			||||||
 | 
								p.P(`if err := `, protoPkg.Use(), `.UnmarshalText(dAtA, msg); err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
									p.P(`if err := p.VerboseEqual(msg); err != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`if !p.Equal(msg) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								p.P(`func Test`, ccTypeName, `ProtoCompactText(t *`, testingPkg.Use(), `.T) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
 | 
				
			||||||
 | 
								p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
 | 
				
			||||||
 | 
								p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
 | 
				
			||||||
 | 
								p.P(`dAtA := `, protoPkg.Use(), `.CompactTextString(p)`)
 | 
				
			||||||
 | 
								p.P(`msg := &`, ccTypeName, `{}`)
 | 
				
			||||||
 | 
								p.P(`if err := `, protoPkg.Use(), `.UnmarshalText(dAtA, msg); err != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
									p.P(`if err := p.VerboseEqual(msg); err != nil {`)
 | 
				
			||||||
 | 
									p.In()
 | 
				
			||||||
 | 
									p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
 | 
				
			||||||
 | 
									p.Out()
 | 
				
			||||||
 | 
									p.P(`}`)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`if !p.Equal(msg) {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
								p.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return used
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						RegisterTestPlugin(newProto)
 | 
				
			||||||
 | 
						RegisterTestPlugin(newJson)
 | 
				
			||||||
 | 
						RegisterTestPlugin(newText)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,209 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					The onlyone plugin generates code for the onlyone extension.
 | 
				
			||||||
 | 
					All fields must be nullable and only one of the fields may be set, like a union.
 | 
				
			||||||
 | 
					Two methods are generated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  GetValue() interface{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SetValue(v interface{}) (set bool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These provide easier interaction with a onlyone.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The onlyone extension is not called union as this causes compile errors in the C++ generated code.
 | 
				
			||||||
 | 
					There can only be one ;)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is enabled by the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - onlyone
 | 
				
			||||||
 | 
					  - onlyone_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The onlyone plugin also generates a test given it is enabled using one of the following extensions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - testgen
 | 
				
			||||||
 | 
					  - testgen_all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Lets look at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/example.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Btw all the output can be seen at:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  github.com/gogo/protobuf/test/example/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following message:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  message U {
 | 
				
			||||||
 | 
						  option (gogoproto.onlyone) = true;
 | 
				
			||||||
 | 
						  optional A A = 1;
 | 
				
			||||||
 | 
						  optional B B = 2;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					given to the onlyone plugin, will generate code which looks a lot like this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func (this *U) GetValue() interface{} {
 | 
				
			||||||
 | 
							if this.A != nil {
 | 
				
			||||||
 | 
								return this.A
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if this.B != nil {
 | 
				
			||||||
 | 
								return this.B
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						func (this *U) SetValue(value interface{}) bool {
 | 
				
			||||||
 | 
							switch vt := value.(type) {
 | 
				
			||||||
 | 
							case *A:
 | 
				
			||||||
 | 
								this.A = vt
 | 
				
			||||||
 | 
							case *B:
 | 
				
			||||||
 | 
								this.B = vt
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and the following test code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  func TestUUnion(t *testing.T) {
 | 
				
			||||||
 | 
						popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano()))
 | 
				
			||||||
 | 
						p := NewPopulatedU(popr)
 | 
				
			||||||
 | 
						v := p.GetValue()
 | 
				
			||||||
 | 
						msg := &U{}
 | 
				
			||||||
 | 
						if !msg.SetValue(v) {
 | 
				
			||||||
 | 
							t.Fatalf("Union: Could not set Value")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !p.Equal(msg) {
 | 
				
			||||||
 | 
							t.Fatalf("%#v !Union Equal %#v", msg, p)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type union struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
						generator.PluginImports
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewUnion() *union {
 | 
				
			||||||
 | 
						return &union{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *union) Name() string {
 | 
				
			||||||
 | 
						return "union"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *union) Init(g *generator.Generator) {
 | 
				
			||||||
 | 
						p.Generator = g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *union) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						p.PluginImports = generator.NewPluginImports(p.Generator)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							if !gogoproto.IsUnion(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.HasExtension() {
 | 
				
			||||||
 | 
								panic("onlyone does not currently support extensions")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
							p.P(`func (this *`, ccTypeName, `) GetValue() interface{} {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							for _, field := range message.Field {
 | 
				
			||||||
 | 
								fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
								if fieldname == "Value" {
 | 
				
			||||||
 | 
									panic("cannot have a onlyone message " + ccTypeName + " with a field named Value")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.P(`if this.`, fieldname, ` != nil {`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`return this.`, fieldname)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
								p.P(`}`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.P(`return nil`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(``)
 | 
				
			||||||
 | 
							p.P(`func (this *`, ccTypeName, `) SetValue(value interface{}) bool {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`switch vt := value.(type) {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							for _, field := range message.Field {
 | 
				
			||||||
 | 
								fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
								goTyp, _ := p.GoType(message, field)
 | 
				
			||||||
 | 
								p.P(`case `, goTyp, `:`)
 | 
				
			||||||
 | 
								p.In()
 | 
				
			||||||
 | 
								p.P(`this.`, fieldname, ` = vt`)
 | 
				
			||||||
 | 
								p.Out()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.P(`default:`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							for _, field := range message.Field {
 | 
				
			||||||
 | 
								fieldname := p.GetFieldName(message, field)
 | 
				
			||||||
 | 
								if field.IsMessage() {
 | 
				
			||||||
 | 
									goTyp, _ := p.GoType(message, field)
 | 
				
			||||||
 | 
									obj := p.ObjectNamed(field.GetTypeName()).(*generator.Descriptor)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if gogoproto.IsUnion(obj.File().FileDescriptorProto, obj.DescriptorProto) {
 | 
				
			||||||
 | 
										p.P(`this.`, fieldname, ` = new(`, generator.GoTypeToName(goTyp), `)`)
 | 
				
			||||||
 | 
										p.P(`if set := this.`, fieldname, `.SetValue(value); set {`)
 | 
				
			||||||
 | 
										p.In()
 | 
				
			||||||
 | 
										p.P(`return true`)
 | 
				
			||||||
 | 
										p.Out()
 | 
				
			||||||
 | 
										p.P(`}`)
 | 
				
			||||||
 | 
										p.P(`this.`, fieldname, ` = nil`)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.P(`return false`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(`return true`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(NewUnion())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/plugin/testgen"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type test struct {
 | 
				
			||||||
 | 
						*generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewTest(g *generator.Generator) testgen.TestPlugin {
 | 
				
			||||||
 | 
						return &test{g}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
 | 
				
			||||||
 | 
						used := false
 | 
				
			||||||
 | 
						randPkg := imports.NewImport("math/rand")
 | 
				
			||||||
 | 
						timePkg := imports.NewImport("time")
 | 
				
			||||||
 | 
						testingPkg := imports.NewImport("testing")
 | 
				
			||||||
 | 
						for _, message := range file.Messages() {
 | 
				
			||||||
 | 
							if !gogoproto.IsUnion(file.FileDescriptorProto, message.DescriptorProto) ||
 | 
				
			||||||
 | 
								!gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if message.DescriptorProto.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							used = true
 | 
				
			||||||
 | 
							ccTypeName := generator.CamelCaseSlice(message.TypeName())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p.P(`func Test`, ccTypeName, `OnlyOne(t *`, testingPkg.Use(), `.T) {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
 | 
				
			||||||
 | 
							p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
 | 
				
			||||||
 | 
							p.P(`v := p.GetValue()`)
 | 
				
			||||||
 | 
							p.P(`msg := &`, ccTypeName, `{}`)
 | 
				
			||||||
 | 
							p.P(`if !msg.SetValue(v) {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`t.Fatalf("OnlyOne: Could not set Value")`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.P(`if !p.Equal(msg) {`)
 | 
				
			||||||
 | 
							p.In()
 | 
				
			||||||
 | 
							p.P(`t.Fatalf("%#v !OnlyOne Equal %#v", msg, p)`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
							p.Out()
 | 
				
			||||||
 | 
							p.P(`}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return used
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						testgen.RegisterTestPlugin(NewTest)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					# Go support for Protocol Buffers - Google's data interchange format
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright 2010 The Go Authors.  All rights reserved.
 | 
				
			||||||
 | 
					# https://github.com/golang/protobuf
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					# modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					# met:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					# notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					#     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					# copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					# in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					# distribution.
 | 
				
			||||||
 | 
					#     * Neither the name of Google Inc. nor the names of its
 | 
				
			||||||
 | 
					# contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 | 
					# this software without specific prior written permission.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					all: test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test:
 | 
				
			||||||
 | 
						go test
 | 
				
			||||||
 | 
						make -C testdata test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					regenerate:
 | 
				
			||||||
 | 
						go test --regenerate
 | 
				
			||||||
 | 
						make -C descriptor regenerate
 | 
				
			||||||
 | 
						make -C plugin regenerate
 | 
				
			||||||
@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					// Go support for Protocol Buffers - Google's data interchange format
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright 2010 The Go Authors.  All rights reserved.
 | 
				
			||||||
 | 
					// https://github.com/golang/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//     * Neither the name of Google Inc. nor the names of its
 | 
				
			||||||
 | 
					// contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 | 
					// this software without specific prior written permission.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						A plugin for the Google protocol buffer compiler to generate Go code.
 | 
				
			||||||
 | 
						Run it by building this program and putting it in your path with the name
 | 
				
			||||||
 | 
							protoc-gen-gogo
 | 
				
			||||||
 | 
						That word 'gogo' at the end becomes part of the option string set for the
 | 
				
			||||||
 | 
						protocol compiler, so once the protocol compiler (protoc) is installed
 | 
				
			||||||
 | 
						you can run
 | 
				
			||||||
 | 
							protoc --gogo_out=output_directory input_directory/file.proto
 | 
				
			||||||
 | 
						to generate Go bindings for the protocol defined by file.proto.
 | 
				
			||||||
 | 
						With that input, the output will be written to
 | 
				
			||||||
 | 
							output_directory/go_package/file.pb.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						The generated code is documented in the package comment for
 | 
				
			||||||
 | 
						the library.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						See the README and documentation for protocol buffers to learn more:
 | 
				
			||||||
 | 
							https://developers.google.com/protocol-buffers/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package documentation
 | 
				
			||||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								@ -0,0 +1,461 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package generator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"go/parser"
 | 
				
			||||||
 | 
						"go/printer"
 | 
				
			||||||
 | 
						"go/token"
 | 
				
			||||||
 | 
						"path"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
 | 
				
			||||||
 | 
						plugin "github.com/gogo/protobuf/protoc-gen-gogo/plugin"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (d *FileDescriptor) Messages() []*Descriptor {
 | 
				
			||||||
 | 
						return d.desc
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (d *FileDescriptor) Enums() []*EnumDescriptor {
 | 
				
			||||||
 | 
						return d.enum
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (d *Descriptor) IsGroup() bool {
 | 
				
			||||||
 | 
						return d.group
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) IsGroup(field *descriptor.FieldDescriptorProto) bool {
 | 
				
			||||||
 | 
						if d, ok := g.typeNameToObject[field.GetTypeName()].(*Descriptor); ok {
 | 
				
			||||||
 | 
							return d.IsGroup()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) TypeNameByObject(typeName string) Object {
 | 
				
			||||||
 | 
						o, ok := g.typeNameToObject[typeName]
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							g.Fail("can't find object with type", typeName)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return o
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) OneOfTypeName(message *Descriptor, field *descriptor.FieldDescriptorProto) string {
 | 
				
			||||||
 | 
						typeName := message.TypeName()
 | 
				
			||||||
 | 
						ccTypeName := CamelCaseSlice(typeName)
 | 
				
			||||||
 | 
						fieldName := g.GetOneOfFieldName(message, field)
 | 
				
			||||||
 | 
						tname := ccTypeName + "_" + fieldName
 | 
				
			||||||
 | 
						// It is possible for this to collide with a message or enum
 | 
				
			||||||
 | 
						// nested in this message. Check for collisions.
 | 
				
			||||||
 | 
						ok := true
 | 
				
			||||||
 | 
						for _, desc := range message.nested {
 | 
				
			||||||
 | 
							if strings.Join(desc.TypeName(), "_") == tname {
 | 
				
			||||||
 | 
								ok = false
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, enum := range message.enums {
 | 
				
			||||||
 | 
							if strings.Join(enum.TypeName(), "_") == tname {
 | 
				
			||||||
 | 
								ok = false
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							tname += "_"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return tname
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PluginImports interface {
 | 
				
			||||||
 | 
						NewImport(pkg string) Single
 | 
				
			||||||
 | 
						GenerateImports(file *FileDescriptor)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type pluginImports struct {
 | 
				
			||||||
 | 
						generator *Generator
 | 
				
			||||||
 | 
						singles   []Single
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewPluginImports(generator *Generator) *pluginImports {
 | 
				
			||||||
 | 
						return &pluginImports{generator, make([]Single, 0)}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *pluginImports) NewImport(pkg string) Single {
 | 
				
			||||||
 | 
						imp := newImportedPackage(this.generator.ImportPrefix, pkg)
 | 
				
			||||||
 | 
						this.singles = append(this.singles, imp)
 | 
				
			||||||
 | 
						return imp
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *pluginImports) GenerateImports(file *FileDescriptor) {
 | 
				
			||||||
 | 
						for _, s := range this.singles {
 | 
				
			||||||
 | 
							if s.IsUsed() {
 | 
				
			||||||
 | 
								this.generator.PrintImport(GoPackageName(s.Name()), GoImportPath(s.Location()))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Single interface {
 | 
				
			||||||
 | 
						Use() string
 | 
				
			||||||
 | 
						IsUsed() bool
 | 
				
			||||||
 | 
						Name() string
 | 
				
			||||||
 | 
						Location() string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type importedPackage struct {
 | 
				
			||||||
 | 
						used         bool
 | 
				
			||||||
 | 
						pkg          string
 | 
				
			||||||
 | 
						name         string
 | 
				
			||||||
 | 
						importPrefix string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newImportedPackage(importPrefix string, pkg string) *importedPackage {
 | 
				
			||||||
 | 
						return &importedPackage{
 | 
				
			||||||
 | 
							pkg:          pkg,
 | 
				
			||||||
 | 
							importPrefix: importPrefix,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *importedPackage) Use() string {
 | 
				
			||||||
 | 
						if !this.used {
 | 
				
			||||||
 | 
							this.name = string(cleanPackageName(this.pkg))
 | 
				
			||||||
 | 
							this.used = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return this.name
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *importedPackage) IsUsed() bool {
 | 
				
			||||||
 | 
						return this.used
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *importedPackage) Name() string {
 | 
				
			||||||
 | 
						return this.name
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *importedPackage) Location() string {
 | 
				
			||||||
 | 
						return this.importPrefix + this.pkg
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) GetFieldName(message *Descriptor, field *descriptor.FieldDescriptorProto) string {
 | 
				
			||||||
 | 
						goTyp, _ := g.GoType(message, field)
 | 
				
			||||||
 | 
						fieldname := CamelCase(*field.Name)
 | 
				
			||||||
 | 
						if gogoproto.IsCustomName(field) {
 | 
				
			||||||
 | 
							fieldname = gogoproto.GetCustomName(field)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if gogoproto.IsEmbed(field) {
 | 
				
			||||||
 | 
							fieldname = EmbedFieldName(goTyp)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if field.OneofIndex != nil {
 | 
				
			||||||
 | 
							fieldname = message.OneofDecl[int(*field.OneofIndex)].GetName()
 | 
				
			||||||
 | 
							fieldname = CamelCase(fieldname)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, f := range methodNames {
 | 
				
			||||||
 | 
							if f == fieldname {
 | 
				
			||||||
 | 
								return fieldname + "_"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !gogoproto.IsProtoSizer(message.file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
							if fieldname == "Size" {
 | 
				
			||||||
 | 
								return fieldname + "_"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return fieldname
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) GetOneOfFieldName(message *Descriptor, field *descriptor.FieldDescriptorProto) string {
 | 
				
			||||||
 | 
						goTyp, _ := g.GoType(message, field)
 | 
				
			||||||
 | 
						fieldname := CamelCase(*field.Name)
 | 
				
			||||||
 | 
						if gogoproto.IsCustomName(field) {
 | 
				
			||||||
 | 
							fieldname = gogoproto.GetCustomName(field)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if gogoproto.IsEmbed(field) {
 | 
				
			||||||
 | 
							fieldname = EmbedFieldName(goTyp)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, f := range methodNames {
 | 
				
			||||||
 | 
							if f == fieldname {
 | 
				
			||||||
 | 
								return fieldname + "_"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !gogoproto.IsProtoSizer(message.file.FileDescriptorProto, message.DescriptorProto) {
 | 
				
			||||||
 | 
							if fieldname == "Size" {
 | 
				
			||||||
 | 
								return fieldname + "_"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return fieldname
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) IsMap(field *descriptor.FieldDescriptorProto) bool {
 | 
				
			||||||
 | 
						if !field.IsMessage() {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						byName := g.ObjectNamed(field.GetTypeName())
 | 
				
			||||||
 | 
						desc, ok := byName.(*Descriptor)
 | 
				
			||||||
 | 
						if byName == nil || !ok || !desc.GetOptions().GetMapEntry() {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) GetMapKeyField(field, keyField *descriptor.FieldDescriptorProto) *descriptor.FieldDescriptorProto {
 | 
				
			||||||
 | 
						if !gogoproto.IsCastKey(field) {
 | 
				
			||||||
 | 
							return keyField
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						keyField = proto.Clone(keyField).(*descriptor.FieldDescriptorProto)
 | 
				
			||||||
 | 
						if keyField.Options == nil {
 | 
				
			||||||
 | 
							keyField.Options = &descriptor.FieldOptions{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						keyType := gogoproto.GetCastKey(field)
 | 
				
			||||||
 | 
						if err := proto.SetExtension(keyField.Options, gogoproto.E_Casttype, &keyType); err != nil {
 | 
				
			||||||
 | 
							g.Fail(err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return keyField
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) GetMapValueField(field, valField *descriptor.FieldDescriptorProto) *descriptor.FieldDescriptorProto {
 | 
				
			||||||
 | 
						if gogoproto.IsCustomType(field) && gogoproto.IsCastValue(field) {
 | 
				
			||||||
 | 
							g.Fail("cannot have a customtype and casttype: ", field.String())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						valField = proto.Clone(valField).(*descriptor.FieldDescriptorProto)
 | 
				
			||||||
 | 
						if valField.Options == nil {
 | 
				
			||||||
 | 
							valField.Options = &descriptor.FieldOptions{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stdtime := gogoproto.IsStdTime(field)
 | 
				
			||||||
 | 
						if stdtime {
 | 
				
			||||||
 | 
							if err := proto.SetExtension(valField.Options, gogoproto.E_Stdtime, &stdtime); err != nil {
 | 
				
			||||||
 | 
								g.Fail(err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stddur := gogoproto.IsStdDuration(field)
 | 
				
			||||||
 | 
						if stddur {
 | 
				
			||||||
 | 
							if err := proto.SetExtension(valField.Options, gogoproto.E_Stdduration, &stddur); err != nil {
 | 
				
			||||||
 | 
								g.Fail(err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wktptr := gogoproto.IsWktPtr(field)
 | 
				
			||||||
 | 
						if wktptr {
 | 
				
			||||||
 | 
							if err := proto.SetExtension(valField.Options, gogoproto.E_Wktpointer, &wktptr); err != nil {
 | 
				
			||||||
 | 
								g.Fail(err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if valType := gogoproto.GetCastValue(field); len(valType) > 0 {
 | 
				
			||||||
 | 
							if err := proto.SetExtension(valField.Options, gogoproto.E_Casttype, &valType); err != nil {
 | 
				
			||||||
 | 
								g.Fail(err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if valType := gogoproto.GetCustomType(field); len(valType) > 0 {
 | 
				
			||||||
 | 
							if err := proto.SetExtension(valField.Options, gogoproto.E_Customtype, &valType); err != nil {
 | 
				
			||||||
 | 
								g.Fail(err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nullable := gogoproto.IsNullable(field)
 | 
				
			||||||
 | 
						if err := proto.SetExtension(valField.Options, gogoproto.E_Nullable, &nullable); err != nil {
 | 
				
			||||||
 | 
							g.Fail(err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return valField
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GoMapValueTypes returns the map value Go type and the alias map value Go type (for casting), taking into
 | 
				
			||||||
 | 
					// account whether the map is nullable or the value is a message.
 | 
				
			||||||
 | 
					func GoMapValueTypes(mapField, valueField *descriptor.FieldDescriptorProto, goValueType, goValueAliasType string) (nullable bool, outGoType string, outGoAliasType string) {
 | 
				
			||||||
 | 
						nullable = gogoproto.IsNullable(mapField) && (valueField.IsMessage() || gogoproto.IsCustomType(mapField))
 | 
				
			||||||
 | 
						if nullable {
 | 
				
			||||||
 | 
							// ensure the non-aliased Go value type is a pointer for consistency
 | 
				
			||||||
 | 
							if strings.HasPrefix(goValueType, "*") {
 | 
				
			||||||
 | 
								outGoType = goValueType
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								outGoType = "*" + goValueType
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							outGoAliasType = goValueAliasType
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							outGoType = strings.Replace(goValueType, "*", "", 1)
 | 
				
			||||||
 | 
							outGoAliasType = strings.Replace(goValueAliasType, "*", "", 1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GoTypeToName(goTyp string) string {
 | 
				
			||||||
 | 
						return strings.Replace(strings.Replace(goTyp, "*", "", -1), "[]", "", -1)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func EmbedFieldName(goTyp string) string {
 | 
				
			||||||
 | 
						goTyp = GoTypeToName(goTyp)
 | 
				
			||||||
 | 
						goTyps := strings.Split(goTyp, ".")
 | 
				
			||||||
 | 
						if len(goTyps) == 1 {
 | 
				
			||||||
 | 
							return goTyp
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(goTyps) == 2 {
 | 
				
			||||||
 | 
							return goTyps[1]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						panic("unreachable")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) GeneratePlugin(p Plugin) {
 | 
				
			||||||
 | 
						plugins = []Plugin{p}
 | 
				
			||||||
 | 
						p.Init(g)
 | 
				
			||||||
 | 
						// Generate the output. The generator runs for every file, even the files
 | 
				
			||||||
 | 
						// that we don't generate output for, so that we can collate the full list
 | 
				
			||||||
 | 
						// of exported symbols to support public imports.
 | 
				
			||||||
 | 
						genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles))
 | 
				
			||||||
 | 
						for _, file := range g.genFiles {
 | 
				
			||||||
 | 
							genFileMap[file] = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, file := range g.allFiles {
 | 
				
			||||||
 | 
							g.Reset()
 | 
				
			||||||
 | 
							g.writeOutput = genFileMap[file]
 | 
				
			||||||
 | 
							g.generatePlugin(file, p)
 | 
				
			||||||
 | 
							if !g.writeOutput {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
 | 
				
			||||||
 | 
								Name:    proto.String(file.goFileName(g.pathType)),
 | 
				
			||||||
 | 
								Content: proto.String(g.String()),
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) SetFile(filename string) {
 | 
				
			||||||
 | 
						g.file = g.fileByName(filename)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) generatePlugin(file *FileDescriptor, p Plugin) {
 | 
				
			||||||
 | 
						g.writtenImports = make(map[string]bool)
 | 
				
			||||||
 | 
						g.usedPackages = make(map[GoImportPath]bool)
 | 
				
			||||||
 | 
						g.packageNames = make(map[GoImportPath]GoPackageName)
 | 
				
			||||||
 | 
						g.usedPackageNames = make(map[GoPackageName]bool)
 | 
				
			||||||
 | 
						g.addedImports = make(map[GoImportPath]bool)
 | 
				
			||||||
 | 
						g.file = file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Run the plugins before the imports so we know which imports are necessary.
 | 
				
			||||||
 | 
						p.Generate(file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Generate header and imports last, though they appear first in the output.
 | 
				
			||||||
 | 
						rem := g.Buffer
 | 
				
			||||||
 | 
						g.Buffer = new(bytes.Buffer)
 | 
				
			||||||
 | 
						g.generateHeader()
 | 
				
			||||||
 | 
						// p.GenerateImports(g.file)
 | 
				
			||||||
 | 
						g.generateImports()
 | 
				
			||||||
 | 
						if !g.writeOutput {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.Write(rem.Bytes())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Reformat generated code.
 | 
				
			||||||
 | 
						contents := string(g.Buffer.Bytes())
 | 
				
			||||||
 | 
						fset := token.NewFileSet()
 | 
				
			||||||
 | 
						ast, err := parser.ParseFile(fset, "", g, parser.ParseComments)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							g.Fail("bad Go source code was generated:", contents, err.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.Reset()
 | 
				
			||||||
 | 
						err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(g, fset, ast)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							g.Fail("generated Go source code could not be reformatted:", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetCustomType(field *descriptor.FieldDescriptorProto) (packageName string, typ string, err error) {
 | 
				
			||||||
 | 
						return getCustomType(field)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getCustomType(field *descriptor.FieldDescriptorProto) (packageName string, typ string, err error) {
 | 
				
			||||||
 | 
						if field.Options != nil {
 | 
				
			||||||
 | 
							var v interface{}
 | 
				
			||||||
 | 
							v, err = proto.GetExtension(field.Options, gogoproto.E_Customtype)
 | 
				
			||||||
 | 
							if err == nil && v.(*string) != nil {
 | 
				
			||||||
 | 
								ctype := *(v.(*string))
 | 
				
			||||||
 | 
								packageName, typ = splitCPackageType(ctype)
 | 
				
			||||||
 | 
								return packageName, typ, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "", "", err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func splitCPackageType(ctype string) (packageName string, typ string) {
 | 
				
			||||||
 | 
						ss := strings.Split(ctype, ".")
 | 
				
			||||||
 | 
						if len(ss) == 1 {
 | 
				
			||||||
 | 
							return "", ctype
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						packageName = strings.Join(ss[0:len(ss)-1], ".")
 | 
				
			||||||
 | 
						typeName := ss[len(ss)-1]
 | 
				
			||||||
 | 
						importStr := strings.Map(badToUnderscore, packageName)
 | 
				
			||||||
 | 
						typ = importStr + "." + typeName
 | 
				
			||||||
 | 
						return packageName, typ
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getCastType(field *descriptor.FieldDescriptorProto) (packageName string, typ string, err error) {
 | 
				
			||||||
 | 
						if field.Options != nil {
 | 
				
			||||||
 | 
							var v interface{}
 | 
				
			||||||
 | 
							v, err = proto.GetExtension(field.Options, gogoproto.E_Casttype)
 | 
				
			||||||
 | 
							if err == nil && v.(*string) != nil {
 | 
				
			||||||
 | 
								ctype := *(v.(*string))
 | 
				
			||||||
 | 
								packageName, typ = splitCPackageType(ctype)
 | 
				
			||||||
 | 
								return packageName, typ, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "", "", err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func FileName(file *FileDescriptor) string {
 | 
				
			||||||
 | 
						fname := path.Base(file.FileDescriptorProto.GetName())
 | 
				
			||||||
 | 
						fname = strings.Replace(fname, ".proto", "", -1)
 | 
				
			||||||
 | 
						fname = strings.Replace(fname, "-", "_", -1)
 | 
				
			||||||
 | 
						fname = strings.Replace(fname, ".", "_", -1)
 | 
				
			||||||
 | 
						return CamelCase(fname)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) AllFiles() *descriptor.FileDescriptorSet {
 | 
				
			||||||
 | 
						set := &descriptor.FileDescriptorSet{}
 | 
				
			||||||
 | 
						set.File = make([]*descriptor.FileDescriptorProto, len(g.allFiles))
 | 
				
			||||||
 | 
						for i := range g.allFiles {
 | 
				
			||||||
 | 
							set.File[i] = g.allFiles[i].FileDescriptorProto
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return set
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (d *Descriptor) Path() string {
 | 
				
			||||||
 | 
						return d.path
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *Generator) useTypes() string {
 | 
				
			||||||
 | 
						pkg := strings.Map(badToUnderscore, "github.com/gogo/protobuf/types")
 | 
				
			||||||
 | 
						g.customImports = append(g.customImports, "github.com/gogo/protobuf/types")
 | 
				
			||||||
 | 
						return pkg
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (d *FileDescriptor) GoPackageName() string {
 | 
				
			||||||
 | 
						return string(d.packageName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
								
									
										
											
										
									
									
										
											117
										
									
									vendor/github.com/gogo/protobuf/protoc-gen-gogo/generator/internal/remap/remap.go
									
										generated
									
									
										vendored
									
								
								
							
							
										
											117
										
									
									vendor/github.com/gogo/protobuf/protoc-gen-gogo/generator/internal/remap/remap.go
									
										generated
									
									
										vendored
									
								@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					// Go support for Protocol Buffers - Google's data interchange format
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright 2017 The Go Authors.  All rights reserved.
 | 
				
			||||||
 | 
					// https://github.com/golang/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//     * Neither the name of Google Inc. nor the names of its
 | 
				
			||||||
 | 
					// contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 | 
					// this software without specific prior written permission.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Package remap handles tracking the locations of Go tokens in a source text
 | 
				
			||||||
 | 
					across a rewrite by the Go formatter.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package remap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"go/scanner"
 | 
				
			||||||
 | 
						"go/token"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A Location represents a span of byte offsets in the source text.
 | 
				
			||||||
 | 
					type Location struct {
 | 
				
			||||||
 | 
						Pos, End int // End is exclusive
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A Map represents a mapping between token locations in an input source text
 | 
				
			||||||
 | 
					// and locations in the correspnding output text.
 | 
				
			||||||
 | 
					type Map map[Location]Location
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Find reports whether the specified span is recorded by m, and if so returns
 | 
				
			||||||
 | 
					// the new location it was mapped to. If the input span was not found, the
 | 
				
			||||||
 | 
					// returned location is the same as the input.
 | 
				
			||||||
 | 
					func (m Map) Find(pos, end int) (Location, bool) {
 | 
				
			||||||
 | 
						key := Location{
 | 
				
			||||||
 | 
							Pos: pos,
 | 
				
			||||||
 | 
							End: end,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if loc, ok := m[key]; ok {
 | 
				
			||||||
 | 
							return loc, true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return key, false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m Map) add(opos, oend, npos, nend int) {
 | 
				
			||||||
 | 
						m[Location{Pos: opos, End: oend}] = Location{Pos: npos, End: nend}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Compute constructs a location mapping from input to output.  An error is
 | 
				
			||||||
 | 
					// reported if any of the tokens of output cannot be mapped.
 | 
				
			||||||
 | 
					func Compute(input, output []byte) (Map, error) {
 | 
				
			||||||
 | 
						itok := tokenize(input)
 | 
				
			||||||
 | 
						otok := tokenize(output)
 | 
				
			||||||
 | 
						if len(itok) != len(otok) {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("wrong number of tokens, %d ≠ %d", len(itok), len(otok))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m := make(Map)
 | 
				
			||||||
 | 
						for i, ti := range itok {
 | 
				
			||||||
 | 
							to := otok[i]
 | 
				
			||||||
 | 
							if ti.Token != to.Token {
 | 
				
			||||||
 | 
								return nil, fmt.Errorf("token %d type mismatch: %s ≠ %s", i+1, ti, to)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							m.add(ti.pos, ti.end, to.pos, to.end)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return m, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// tokinfo records the span and type of a source token.
 | 
				
			||||||
 | 
					type tokinfo struct {
 | 
				
			||||||
 | 
						pos, end int
 | 
				
			||||||
 | 
						token.Token
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func tokenize(src []byte) []tokinfo {
 | 
				
			||||||
 | 
						fs := token.NewFileSet()
 | 
				
			||||||
 | 
						var s scanner.Scanner
 | 
				
			||||||
 | 
						s.Init(fs.AddFile("src", fs.Base(), len(src)), src, nil, scanner.ScanComments)
 | 
				
			||||||
 | 
						var info []tokinfo
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							pos, next, lit := s.Scan()
 | 
				
			||||||
 | 
							switch next {
 | 
				
			||||||
 | 
							case token.SEMICOLON:
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							info = append(info, tokinfo{
 | 
				
			||||||
 | 
								pos:   int(pos - 1),
 | 
				
			||||||
 | 
								end:   int(pos + token.Pos(len(lit)) - 1),
 | 
				
			||||||
 | 
								Token: next,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							if next == token.EOF {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return info
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,536 @@
 | 
				
			|||||||
 | 
					// Go support for Protocol Buffers - Google's data interchange format
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright 2015 The Go Authors.  All rights reserved.
 | 
				
			||||||
 | 
					// https://github.com/golang/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//     * Neither the name of Google Inc. nor the names of its
 | 
				
			||||||
 | 
					// contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 | 
					// this software without specific prior written permission.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Package grpc outputs gRPC service descriptions in Go code.
 | 
				
			||||||
 | 
					// It runs as a plugin for the Go protocol buffer compiler plugin.
 | 
				
			||||||
 | 
					// It is linked in to protoc-gen-go.
 | 
				
			||||||
 | 
					package grpc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pb "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// generatedCodeVersion indicates a version of the generated code.
 | 
				
			||||||
 | 
					// It is incremented whenever an incompatibility between the generated code and
 | 
				
			||||||
 | 
					// the grpc package is introduced; the generated code references
 | 
				
			||||||
 | 
					// a constant, grpc.SupportPackageIsVersionN (where N is generatedCodeVersion).
 | 
				
			||||||
 | 
					const generatedCodeVersion = 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Paths for packages used by code generated in this file,
 | 
				
			||||||
 | 
					// relative to the import_prefix of the generator.Generator.
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						contextPkgPath = "context"
 | 
				
			||||||
 | 
						grpcPkgPath    = "google.golang.org/grpc"
 | 
				
			||||||
 | 
						codePkgPath    = "google.golang.org/grpc/codes"
 | 
				
			||||||
 | 
						statusPkgPath  = "google.golang.org/grpc/status"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						generator.RegisterPlugin(new(grpc))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// grpc is an implementation of the Go protocol buffer compiler's
 | 
				
			||||||
 | 
					// plugin architecture.  It generates bindings for gRPC support.
 | 
				
			||||||
 | 
					type grpc struct {
 | 
				
			||||||
 | 
						gen *generator.Generator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Name returns the name of this plugin, "grpc".
 | 
				
			||||||
 | 
					func (g *grpc) Name() string {
 | 
				
			||||||
 | 
						return "grpc"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The names for packages imported in the generated code.
 | 
				
			||||||
 | 
					// They may vary from the final path component of the import path
 | 
				
			||||||
 | 
					// if the name is used by other packages.
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						contextPkg string
 | 
				
			||||||
 | 
						grpcPkg    string
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Init initializes the plugin.
 | 
				
			||||||
 | 
					func (g *grpc) Init(gen *generator.Generator) {
 | 
				
			||||||
 | 
						g.gen = gen
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Given a type name defined in a .proto, return its object.
 | 
				
			||||||
 | 
					// Also record that we're using it, to guarantee the associated import.
 | 
				
			||||||
 | 
					func (g *grpc) objectNamed(name string) generator.Object {
 | 
				
			||||||
 | 
						g.gen.RecordTypeUse(name)
 | 
				
			||||||
 | 
						return g.gen.ObjectNamed(name)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Given a type name defined in a .proto, return its name as we will print it.
 | 
				
			||||||
 | 
					func (g *grpc) typeName(str string) string {
 | 
				
			||||||
 | 
						return g.gen.TypeName(g.objectNamed(str))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// P forwards to g.gen.P.
 | 
				
			||||||
 | 
					func (g *grpc) P(args ...interface{}) { g.gen.P(args...) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Generate generates code for the services in the given file.
 | 
				
			||||||
 | 
					func (g *grpc) Generate(file *generator.FileDescriptor) {
 | 
				
			||||||
 | 
						if len(file.FileDescriptorProto.Service) == 0 {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						contextPkg = string(g.gen.AddImport(contextPkgPath))
 | 
				
			||||||
 | 
						grpcPkg = string(g.gen.AddImport(grpcPkgPath))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("// Reference imports to suppress errors if they are not otherwise used.")
 | 
				
			||||||
 | 
						g.P("var _ ", contextPkg, ".Context")
 | 
				
			||||||
 | 
						g.P("var _ ", grpcPkg, ".ClientConn")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Assert version compatibility.
 | 
				
			||||||
 | 
						g.P("// This is a compile-time assertion to ensure that this generated file")
 | 
				
			||||||
 | 
						g.P("// is compatible with the grpc package it is being compiled against.")
 | 
				
			||||||
 | 
						g.P("const _ = ", grpcPkg, ".SupportPackageIsVersion", generatedCodeVersion)
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i, service := range file.FileDescriptorProto.Service {
 | 
				
			||||||
 | 
							g.generateService(file, service, i)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GenerateImports generates the import declaration for this file.
 | 
				
			||||||
 | 
					func (g *grpc) GenerateImports(file *generator.FileDescriptor) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// reservedClientName records whether a client name is reserved on the client side.
 | 
				
			||||||
 | 
					var reservedClientName = map[string]bool{
 | 
				
			||||||
 | 
						// TODO: do we need any in gRPC?
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func unexport(s string) string { return strings.ToLower(s[:1]) + s[1:] }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// deprecationComment is the standard comment added to deprecated
 | 
				
			||||||
 | 
					// messages, fields, enums, and enum values.
 | 
				
			||||||
 | 
					var deprecationComment = "// Deprecated: Do not use."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// generateService generates all the code for the named service.
 | 
				
			||||||
 | 
					func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) {
 | 
				
			||||||
 | 
						path := fmt.Sprintf("6,%d", index) // 6 means service.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						origServName := service.GetName()
 | 
				
			||||||
 | 
						fullServName := origServName
 | 
				
			||||||
 | 
						if pkg := file.GetPackage(); pkg != "" {
 | 
				
			||||||
 | 
							fullServName = pkg + "." + fullServName
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						servName := generator.CamelCase(origServName)
 | 
				
			||||||
 | 
						deprecated := service.GetOptions().GetDeprecated()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
						g.P(fmt.Sprintf(`// %sClient is the client API for %s service.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.`, servName, servName))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Client interface.
 | 
				
			||||||
 | 
						if deprecated {
 | 
				
			||||||
 | 
							g.P("//")
 | 
				
			||||||
 | 
							g.P(deprecationComment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("type ", servName, "Client interface {")
 | 
				
			||||||
 | 
						for i, method := range service.Method {
 | 
				
			||||||
 | 
							g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
 | 
				
			||||||
 | 
							g.P(g.generateClientSignature(servName, method))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Client structure.
 | 
				
			||||||
 | 
						g.P("type ", unexport(servName), "Client struct {")
 | 
				
			||||||
 | 
						g.P("cc *", grpcPkg, ".ClientConn")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// NewClient factory.
 | 
				
			||||||
 | 
						if deprecated {
 | 
				
			||||||
 | 
							g.P(deprecationComment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("func New", servName, "Client (cc *", grpcPkg, ".ClientConn) ", servName, "Client {")
 | 
				
			||||||
 | 
						g.P("return &", unexport(servName), "Client{cc}")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var methodIndex, streamIndex int
 | 
				
			||||||
 | 
						serviceDescVar := "_" + servName + "_serviceDesc"
 | 
				
			||||||
 | 
						// Client method implementations.
 | 
				
			||||||
 | 
						for _, method := range service.Method {
 | 
				
			||||||
 | 
							var descExpr string
 | 
				
			||||||
 | 
							if !method.GetServerStreaming() && !method.GetClientStreaming() {
 | 
				
			||||||
 | 
								// Unary RPC method
 | 
				
			||||||
 | 
								descExpr = fmt.Sprintf("&%s.Methods[%d]", serviceDescVar, methodIndex)
 | 
				
			||||||
 | 
								methodIndex++
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								// Streaming RPC method
 | 
				
			||||||
 | 
								descExpr = fmt.Sprintf("&%s.Streams[%d]", serviceDescVar, streamIndex)
 | 
				
			||||||
 | 
								streamIndex++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.generateClientMethod(servName, fullServName, serviceDescVar, method, descExpr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Server interface.
 | 
				
			||||||
 | 
						serverType := servName + "Server"
 | 
				
			||||||
 | 
						g.P("// ", serverType, " is the server API for ", servName, " service.")
 | 
				
			||||||
 | 
						if deprecated {
 | 
				
			||||||
 | 
							g.P("//")
 | 
				
			||||||
 | 
							g.P(deprecationComment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("type ", serverType, " interface {")
 | 
				
			||||||
 | 
						for i, method := range service.Method {
 | 
				
			||||||
 | 
							g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
 | 
				
			||||||
 | 
							g.P(g.generateServerSignature(servName, method))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Server Unimplemented struct for forward compatability.
 | 
				
			||||||
 | 
						if deprecated {
 | 
				
			||||||
 | 
							g.P(deprecationComment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.generateUnimplementedServer(servName, service)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Server registration.
 | 
				
			||||||
 | 
						if deprecated {
 | 
				
			||||||
 | 
							g.P(deprecationComment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("func Register", servName, "Server(s *", grpcPkg, ".Server, srv ", serverType, ") {")
 | 
				
			||||||
 | 
						g.P("s.RegisterService(&", serviceDescVar, `, srv)`)
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Server handler implementations.
 | 
				
			||||||
 | 
						var handlerNames []string
 | 
				
			||||||
 | 
						for _, method := range service.Method {
 | 
				
			||||||
 | 
							hname := g.generateServerMethod(servName, fullServName, method)
 | 
				
			||||||
 | 
							handlerNames = append(handlerNames, hname)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Service descriptor.
 | 
				
			||||||
 | 
						g.P("var ", serviceDescVar, " = ", grpcPkg, ".ServiceDesc {")
 | 
				
			||||||
 | 
						g.P("ServiceName: ", strconv.Quote(fullServName), ",")
 | 
				
			||||||
 | 
						g.P("HandlerType: (*", serverType, ")(nil),")
 | 
				
			||||||
 | 
						g.P("Methods: []", grpcPkg, ".MethodDesc{")
 | 
				
			||||||
 | 
						for i, method := range service.Method {
 | 
				
			||||||
 | 
							if method.GetServerStreaming() || method.GetClientStreaming() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P("{")
 | 
				
			||||||
 | 
							g.P("MethodName: ", strconv.Quote(method.GetName()), ",")
 | 
				
			||||||
 | 
							g.P("Handler: ", handlerNames[i], ",")
 | 
				
			||||||
 | 
							g.P("},")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("},")
 | 
				
			||||||
 | 
						g.P("Streams: []", grpcPkg, ".StreamDesc{")
 | 
				
			||||||
 | 
						for i, method := range service.Method {
 | 
				
			||||||
 | 
							if !method.GetServerStreaming() && !method.GetClientStreaming() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P("{")
 | 
				
			||||||
 | 
							g.P("StreamName: ", strconv.Quote(method.GetName()), ",")
 | 
				
			||||||
 | 
							g.P("Handler: ", handlerNames[i], ",")
 | 
				
			||||||
 | 
							if method.GetServerStreaming() {
 | 
				
			||||||
 | 
								g.P("ServerStreams: true,")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if method.GetClientStreaming() {
 | 
				
			||||||
 | 
								g.P("ClientStreams: true,")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P("},")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("},")
 | 
				
			||||||
 | 
						g.P("Metadata: \"", file.GetName(), "\",")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// generateUnimplementedServer creates the unimplemented server struct
 | 
				
			||||||
 | 
					func (g *grpc) generateUnimplementedServer(servName string, service *pb.ServiceDescriptorProto) {
 | 
				
			||||||
 | 
						serverType := servName + "Server"
 | 
				
			||||||
 | 
						g.P("// Unimplemented", serverType, " can be embedded to have forward compatible implementations.")
 | 
				
			||||||
 | 
						g.P("type Unimplemented", serverType, " struct {")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
						// Unimplemented<service_name>Server's concrete methods
 | 
				
			||||||
 | 
						for _, method := range service.Method {
 | 
				
			||||||
 | 
							g.generateServerMethodConcrete(servName, method)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// generateServerMethodConcrete returns unimplemented methods which ensure forward compatibility
 | 
				
			||||||
 | 
					func (g *grpc) generateServerMethodConcrete(servName string, method *pb.MethodDescriptorProto) {
 | 
				
			||||||
 | 
						header := g.generateServerSignatureWithParamNames(servName, method)
 | 
				
			||||||
 | 
						g.P("func (*Unimplemented", servName, "Server) ", header, " {")
 | 
				
			||||||
 | 
						var nilArg string
 | 
				
			||||||
 | 
						if !method.GetServerStreaming() && !method.GetClientStreaming() {
 | 
				
			||||||
 | 
							nilArg = "nil, "
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						methName := generator.CamelCase(method.GetName())
 | 
				
			||||||
 | 
						statusPkg := string(g.gen.AddImport(statusPkgPath))
 | 
				
			||||||
 | 
						codePkg := string(g.gen.AddImport(codePkgPath))
 | 
				
			||||||
 | 
						g.P("return ", nilArg, statusPkg, `.Errorf(`, codePkg, `.Unimplemented, "method `, methName, ` not implemented")`)
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// generateClientSignature returns the client-side signature for a method.
 | 
				
			||||||
 | 
					func (g *grpc) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string {
 | 
				
			||||||
 | 
						origMethName := method.GetName()
 | 
				
			||||||
 | 
						methName := generator.CamelCase(origMethName)
 | 
				
			||||||
 | 
						if reservedClientName[methName] {
 | 
				
			||||||
 | 
							methName += "_"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						reqArg := ", in *" + g.typeName(method.GetInputType())
 | 
				
			||||||
 | 
						if method.GetClientStreaming() {
 | 
				
			||||||
 | 
							reqArg = ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						respName := "*" + g.typeName(method.GetOutputType())
 | 
				
			||||||
 | 
						if method.GetServerStreaming() || method.GetClientStreaming() {
 | 
				
			||||||
 | 
							respName = servName + "_" + generator.CamelCase(origMethName) + "Client"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return fmt.Sprintf("%s(ctx %s.Context%s, opts ...%s.CallOption) (%s, error)", methName, contextPkg, reqArg, grpcPkg, respName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *grpc) generateClientMethod(servName, fullServName, serviceDescVar string, method *pb.MethodDescriptorProto, descExpr string) {
 | 
				
			||||||
 | 
						sname := fmt.Sprintf("/%s/%s", fullServName, method.GetName())
 | 
				
			||||||
 | 
						methName := generator.CamelCase(method.GetName())
 | 
				
			||||||
 | 
						inType := g.typeName(method.GetInputType())
 | 
				
			||||||
 | 
						outType := g.typeName(method.GetOutputType())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if method.GetOptions().GetDeprecated() {
 | 
				
			||||||
 | 
							g.P(deprecationComment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("func (c *", unexport(servName), "Client) ", g.generateClientSignature(servName, method), "{")
 | 
				
			||||||
 | 
						if !method.GetServerStreaming() && !method.GetClientStreaming() {
 | 
				
			||||||
 | 
							g.P("out := new(", outType, ")")
 | 
				
			||||||
 | 
							// TODO: Pass descExpr to Invoke.
 | 
				
			||||||
 | 
							g.P(`err := c.cc.Invoke(ctx, "`, sname, `", in, out, opts...)`)
 | 
				
			||||||
 | 
							g.P("if err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("return out, nil")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						streamType := unexport(servName) + methName + "Client"
 | 
				
			||||||
 | 
						g.P("stream, err := c.cc.NewStream(ctx, ", descExpr, `, "`, sname, `", opts...)`)
 | 
				
			||||||
 | 
						g.P("if err != nil { return nil, err }")
 | 
				
			||||||
 | 
						g.P("x := &", streamType, "{stream}")
 | 
				
			||||||
 | 
						if !method.GetClientStreaming() {
 | 
				
			||||||
 | 
							g.P("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("return x, nil")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						genSend := method.GetClientStreaming()
 | 
				
			||||||
 | 
						genRecv := method.GetServerStreaming()
 | 
				
			||||||
 | 
						genCloseAndRecv := !method.GetServerStreaming()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Stream auxiliary types and methods.
 | 
				
			||||||
 | 
						g.P("type ", servName, "_", methName, "Client interface {")
 | 
				
			||||||
 | 
						if genSend {
 | 
				
			||||||
 | 
							g.P("Send(*", inType, ") error")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genRecv {
 | 
				
			||||||
 | 
							g.P("Recv() (*", outType, ", error)")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genCloseAndRecv {
 | 
				
			||||||
 | 
							g.P("CloseAndRecv() (*", outType, ", error)")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P(grpcPkg, ".ClientStream")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("type ", streamType, " struct {")
 | 
				
			||||||
 | 
						g.P(grpcPkg, ".ClientStream")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if genSend {
 | 
				
			||||||
 | 
							g.P("func (x *", streamType, ") Send(m *", inType, ") error {")
 | 
				
			||||||
 | 
							g.P("return x.ClientStream.SendMsg(m)")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genRecv {
 | 
				
			||||||
 | 
							g.P("func (x *", streamType, ") Recv() (*", outType, ", error) {")
 | 
				
			||||||
 | 
							g.P("m := new(", outType, ")")
 | 
				
			||||||
 | 
							g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("return m, nil")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genCloseAndRecv {
 | 
				
			||||||
 | 
							g.P("func (x *", streamType, ") CloseAndRecv() (*", outType, ", error) {")
 | 
				
			||||||
 | 
							g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("m := new(", outType, ")")
 | 
				
			||||||
 | 
							g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("return m, nil")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// generateServerSignatureWithParamNames returns the server-side signature for a method with parameter names.
 | 
				
			||||||
 | 
					func (g *grpc) generateServerSignatureWithParamNames(servName string, method *pb.MethodDescriptorProto) string {
 | 
				
			||||||
 | 
						origMethName := method.GetName()
 | 
				
			||||||
 | 
						methName := generator.CamelCase(origMethName)
 | 
				
			||||||
 | 
						if reservedClientName[methName] {
 | 
				
			||||||
 | 
							methName += "_"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var reqArgs []string
 | 
				
			||||||
 | 
						ret := "error"
 | 
				
			||||||
 | 
						if !method.GetServerStreaming() && !method.GetClientStreaming() {
 | 
				
			||||||
 | 
							reqArgs = append(reqArgs, "ctx "+contextPkg+".Context")
 | 
				
			||||||
 | 
							ret = "(*" + g.typeName(method.GetOutputType()) + ", error)"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !method.GetClientStreaming() {
 | 
				
			||||||
 | 
							reqArgs = append(reqArgs, "req *"+g.typeName(method.GetInputType()))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if method.GetServerStreaming() || method.GetClientStreaming() {
 | 
				
			||||||
 | 
							reqArgs = append(reqArgs, "srv "+servName+"_"+generator.CamelCase(origMethName)+"Server")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// generateServerSignature returns the server-side signature for a method.
 | 
				
			||||||
 | 
					func (g *grpc) generateServerSignature(servName string, method *pb.MethodDescriptorProto) string {
 | 
				
			||||||
 | 
						origMethName := method.GetName()
 | 
				
			||||||
 | 
						methName := generator.CamelCase(origMethName)
 | 
				
			||||||
 | 
						if reservedClientName[methName] {
 | 
				
			||||||
 | 
							methName += "_"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var reqArgs []string
 | 
				
			||||||
 | 
						ret := "error"
 | 
				
			||||||
 | 
						if !method.GetServerStreaming() && !method.GetClientStreaming() {
 | 
				
			||||||
 | 
							reqArgs = append(reqArgs, contextPkg+".Context")
 | 
				
			||||||
 | 
							ret = "(*" + g.typeName(method.GetOutputType()) + ", error)"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !method.GetClientStreaming() {
 | 
				
			||||||
 | 
							reqArgs = append(reqArgs, "*"+g.typeName(method.GetInputType()))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if method.GetServerStreaming() || method.GetClientStreaming() {
 | 
				
			||||||
 | 
							reqArgs = append(reqArgs, servName+"_"+generator.CamelCase(origMethName)+"Server")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *grpc) generateServerMethod(servName, fullServName string, method *pb.MethodDescriptorProto) string {
 | 
				
			||||||
 | 
						methName := generator.CamelCase(method.GetName())
 | 
				
			||||||
 | 
						hname := fmt.Sprintf("_%s_%s_Handler", servName, methName)
 | 
				
			||||||
 | 
						inType := g.typeName(method.GetInputType())
 | 
				
			||||||
 | 
						outType := g.typeName(method.GetOutputType())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !method.GetServerStreaming() && !method.GetClientStreaming() {
 | 
				
			||||||
 | 
							g.P("func ", hname, "(srv interface{}, ctx ", contextPkg, ".Context, dec func(interface{}) error, interceptor ", grpcPkg, ".UnaryServerInterceptor) (interface{}, error) {")
 | 
				
			||||||
 | 
							g.P("in := new(", inType, ")")
 | 
				
			||||||
 | 
							g.P("if err := dec(in); err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("if interceptor == nil { return srv.(", servName, "Server).", methName, "(ctx, in) }")
 | 
				
			||||||
 | 
							g.P("info := &", grpcPkg, ".UnaryServerInfo{")
 | 
				
			||||||
 | 
							g.P("Server: srv,")
 | 
				
			||||||
 | 
							g.P("FullMethod: ", strconv.Quote(fmt.Sprintf("/%s/%s", fullServName, methName)), ",")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P("handler := func(ctx ", contextPkg, ".Context, req interface{}) (interface{}, error) {")
 | 
				
			||||||
 | 
							g.P("return srv.(", servName, "Server).", methName, "(ctx, req.(*", inType, "))")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P("return interceptor(ctx, in, info, handler)")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
							return hname
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						streamType := unexport(servName) + methName + "Server"
 | 
				
			||||||
 | 
						g.P("func ", hname, "(srv interface{}, stream ", grpcPkg, ".ServerStream) error {")
 | 
				
			||||||
 | 
						if !method.GetClientStreaming() {
 | 
				
			||||||
 | 
							g.P("m := new(", inType, ")")
 | 
				
			||||||
 | 
							g.P("if err := stream.RecvMsg(m); err != nil { return err }")
 | 
				
			||||||
 | 
							g.P("return srv.(", servName, "Server).", methName, "(m, &", streamType, "{stream})")
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							g.P("return srv.(", servName, "Server).", methName, "(&", streamType, "{stream})")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						genSend := method.GetServerStreaming()
 | 
				
			||||||
 | 
						genSendAndClose := !method.GetServerStreaming()
 | 
				
			||||||
 | 
						genRecv := method.GetClientStreaming()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Stream auxiliary types and methods.
 | 
				
			||||||
 | 
						g.P("type ", servName, "_", methName, "Server interface {")
 | 
				
			||||||
 | 
						if genSend {
 | 
				
			||||||
 | 
							g.P("Send(*", outType, ") error")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genSendAndClose {
 | 
				
			||||||
 | 
							g.P("SendAndClose(*", outType, ") error")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genRecv {
 | 
				
			||||||
 | 
							g.P("Recv() (*", inType, ", error)")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P(grpcPkg, ".ServerStream")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("type ", streamType, " struct {")
 | 
				
			||||||
 | 
						g.P(grpcPkg, ".ServerStream")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if genSend {
 | 
				
			||||||
 | 
							g.P("func (x *", streamType, ") Send(m *", outType, ") error {")
 | 
				
			||||||
 | 
							g.P("return x.ServerStream.SendMsg(m)")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genSendAndClose {
 | 
				
			||||||
 | 
							g.P("func (x *", streamType, ") SendAndClose(m *", outType, ") error {")
 | 
				
			||||||
 | 
							g.P("return x.ServerStream.SendMsg(m)")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genRecv {
 | 
				
			||||||
 | 
							g.P("func (x *", streamType, ") Recv() (*", inType, ", error) {")
 | 
				
			||||||
 | 
							g.P("m := new(", inType, ")")
 | 
				
			||||||
 | 
							g.P("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("return m, nil")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return hname
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					// Go support for Protocol Buffers - Google's data interchange format
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright 2010 The Go Authors.  All rights reserved.
 | 
				
			||||||
 | 
					// https://github.com/golang/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//     * Neither the name of Google Inc. nor the names of its
 | 
				
			||||||
 | 
					// contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 | 
					// this software without specific prior written permission.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// protoc-gen-go is a plugin for the Google protocol buffer compiler to generate
 | 
				
			||||||
 | 
					// Go code.  Run it by building this program and putting it in your path with
 | 
				
			||||||
 | 
					// the name
 | 
				
			||||||
 | 
					// 	protoc-gen-gogo
 | 
				
			||||||
 | 
					// That word 'gogo' at the end becomes part of the option string set for the
 | 
				
			||||||
 | 
					// protocol compiler, so once the protocol compiler (protoc) is installed
 | 
				
			||||||
 | 
					// you can run
 | 
				
			||||||
 | 
					// 	protoc --gogo_out=output_directory input_directory/file.proto
 | 
				
			||||||
 | 
					// to generate Go bindings for the protocol defined by file.proto.
 | 
				
			||||||
 | 
					// With that input, the output will be written to
 | 
				
			||||||
 | 
					// 	output_directory/file.pb.go
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The generated code is documented in the package comment for
 | 
				
			||||||
 | 
					// the library.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See the README and documentation for protocol buffers to learn more:
 | 
				
			||||||
 | 
					// 	https://developers.google.com/protocol-buffers/
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/vanity/command"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						command.Write(command.Generate(command.Read()))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					# Go support for Protocol Buffers - Google's data interchange format
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright 2010 The Go Authors.  All rights reserved.
 | 
				
			||||||
 | 
					# https://github.com/golang/protobuf
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					# modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					# met:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					# notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					#     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					# copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					# in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					# distribution.
 | 
				
			||||||
 | 
					#     * Neither the name of Google Inc. nor the names of its
 | 
				
			||||||
 | 
					# contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 | 
					# this software without specific prior written permission.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Not stored here, but plugin.proto is in https://github.com/google/protobuf/
 | 
				
			||||||
 | 
					# at src/google/protobuf/compiler/plugin.proto
 | 
				
			||||||
 | 
					# Also we need to fix an import.
 | 
				
			||||||
 | 
					regenerate:
 | 
				
			||||||
 | 
						go install github.com/gogo/protobuf/protoc-gen-gogo
 | 
				
			||||||
 | 
						protoc --gogo_out=Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor:. -I=../../protobuf/google/protobuf/compiler/:../../protobuf/ ../../protobuf/google/protobuf/compiler/plugin.proto
 | 
				
			||||||
@ -0,0 +1,365 @@
 | 
				
			|||||||
 | 
					// Code generated by protoc-gen-gogo. DO NOT EDIT.
 | 
				
			||||||
 | 
					// source: plugin.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package plugin_go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						fmt "fmt"
 | 
				
			||||||
 | 
						proto "github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
 | 
				
			||||||
 | 
						math "math"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Reference imports to suppress errors if they are not otherwise used.
 | 
				
			||||||
 | 
					var _ = proto.Marshal
 | 
				
			||||||
 | 
					var _ = fmt.Errorf
 | 
				
			||||||
 | 
					var _ = math.Inf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is a compile-time assertion to ensure that this generated file
 | 
				
			||||||
 | 
					// is compatible with the proto package it is being compiled against.
 | 
				
			||||||
 | 
					// A compilation error at this line likely means your copy of the
 | 
				
			||||||
 | 
					// proto package needs to be updated.
 | 
				
			||||||
 | 
					const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The version number of protocol compiler.
 | 
				
			||||||
 | 
					type Version struct {
 | 
				
			||||||
 | 
						Major *int32 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"`
 | 
				
			||||||
 | 
						Minor *int32 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"`
 | 
				
			||||||
 | 
						Patch *int32 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"`
 | 
				
			||||||
 | 
						// A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
 | 
				
			||||||
 | 
						// be empty for mainline stable releases.
 | 
				
			||||||
 | 
						Suffix               *string  `protobuf:"bytes,4,opt,name=suffix" json:"suffix,omitempty"`
 | 
				
			||||||
 | 
						XXX_NoUnkeyedLiteral struct{} `json:"-"`
 | 
				
			||||||
 | 
						XXX_unrecognized     []byte   `json:"-"`
 | 
				
			||||||
 | 
						XXX_sizecache        int32    `json:"-"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Version) Reset()         { *m = Version{} }
 | 
				
			||||||
 | 
					func (m *Version) String() string { return proto.CompactTextString(m) }
 | 
				
			||||||
 | 
					func (*Version) ProtoMessage()    {}
 | 
				
			||||||
 | 
					func (*Version) Descriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return fileDescriptor_22a625af4bc1cc87, []int{0}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *Version) XXX_Unmarshal(b []byte) error {
 | 
				
			||||||
 | 
						return xxx_messageInfo_Version.Unmarshal(m, b)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 | 
				
			||||||
 | 
						return xxx_messageInfo_Version.Marshal(b, m, deterministic)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *Version) XXX_Merge(src proto.Message) {
 | 
				
			||||||
 | 
						xxx_messageInfo_Version.Merge(m, src)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *Version) XXX_Size() int {
 | 
				
			||||||
 | 
						return xxx_messageInfo_Version.Size(m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *Version) XXX_DiscardUnknown() {
 | 
				
			||||||
 | 
						xxx_messageInfo_Version.DiscardUnknown(m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var xxx_messageInfo_Version proto.InternalMessageInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Version) GetMajor() int32 {
 | 
				
			||||||
 | 
						if m != nil && m.Major != nil {
 | 
				
			||||||
 | 
							return *m.Major
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Version) GetMinor() int32 {
 | 
				
			||||||
 | 
						if m != nil && m.Minor != nil {
 | 
				
			||||||
 | 
							return *m.Minor
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Version) GetPatch() int32 {
 | 
				
			||||||
 | 
						if m != nil && m.Patch != nil {
 | 
				
			||||||
 | 
							return *m.Patch
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Version) GetSuffix() string {
 | 
				
			||||||
 | 
						if m != nil && m.Suffix != nil {
 | 
				
			||||||
 | 
							return *m.Suffix
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// An encoded CodeGeneratorRequest is written to the plugin's stdin.
 | 
				
			||||||
 | 
					type CodeGeneratorRequest struct {
 | 
				
			||||||
 | 
						// The .proto files that were explicitly listed on the command-line.  The
 | 
				
			||||||
 | 
						// code generator should generate code only for these files.  Each file's
 | 
				
			||||||
 | 
						// descriptor will be included in proto_file, below.
 | 
				
			||||||
 | 
						FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate,json=fileToGenerate" json:"file_to_generate,omitempty"`
 | 
				
			||||||
 | 
						// The generator parameter passed on the command-line.
 | 
				
			||||||
 | 
						Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"`
 | 
				
			||||||
 | 
						// FileDescriptorProtos for all files in files_to_generate and everything
 | 
				
			||||||
 | 
						// they import.  The files will appear in topological order, so each file
 | 
				
			||||||
 | 
						// appears before any file that imports it.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// protoc guarantees that all proto_files will be written after
 | 
				
			||||||
 | 
						// the fields above, even though this is not technically guaranteed by the
 | 
				
			||||||
 | 
						// protobuf wire format.  This theoretically could allow a plugin to stream
 | 
				
			||||||
 | 
						// in the FileDescriptorProtos and handle them one by one rather than read
 | 
				
			||||||
 | 
						// the entire set into memory at once.  However, as of this writing, this
 | 
				
			||||||
 | 
						// is not similarly optimized on protoc's end -- it will store all fields in
 | 
				
			||||||
 | 
						// memory at once before sending them to the plugin.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Type names of fields and extensions in the FileDescriptorProto are always
 | 
				
			||||||
 | 
						// fully qualified.
 | 
				
			||||||
 | 
						ProtoFile []*descriptor.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file,json=protoFile" json:"proto_file,omitempty"`
 | 
				
			||||||
 | 
						// The version number of protocol compiler.
 | 
				
			||||||
 | 
						CompilerVersion      *Version `protobuf:"bytes,3,opt,name=compiler_version,json=compilerVersion" json:"compiler_version,omitempty"`
 | 
				
			||||||
 | 
						XXX_NoUnkeyedLiteral struct{} `json:"-"`
 | 
				
			||||||
 | 
						XXX_unrecognized     []byte   `json:"-"`
 | 
				
			||||||
 | 
						XXX_sizecache        int32    `json:"-"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *CodeGeneratorRequest) Reset()         { *m = CodeGeneratorRequest{} }
 | 
				
			||||||
 | 
					func (m *CodeGeneratorRequest) String() string { return proto.CompactTextString(m) }
 | 
				
			||||||
 | 
					func (*CodeGeneratorRequest) ProtoMessage()    {}
 | 
				
			||||||
 | 
					func (*CodeGeneratorRequest) Descriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return fileDescriptor_22a625af4bc1cc87, []int{1}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorRequest) XXX_Unmarshal(b []byte) error {
 | 
				
			||||||
 | 
						return xxx_messageInfo_CodeGeneratorRequest.Unmarshal(m, b)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 | 
				
			||||||
 | 
						return xxx_messageInfo_CodeGeneratorRequest.Marshal(b, m, deterministic)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorRequest) XXX_Merge(src proto.Message) {
 | 
				
			||||||
 | 
						xxx_messageInfo_CodeGeneratorRequest.Merge(m, src)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorRequest) XXX_Size() int {
 | 
				
			||||||
 | 
						return xxx_messageInfo_CodeGeneratorRequest.Size(m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorRequest) XXX_DiscardUnknown() {
 | 
				
			||||||
 | 
						xxx_messageInfo_CodeGeneratorRequest.DiscardUnknown(m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var xxx_messageInfo_CodeGeneratorRequest proto.InternalMessageInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *CodeGeneratorRequest) GetFileToGenerate() []string {
 | 
				
			||||||
 | 
						if m != nil {
 | 
				
			||||||
 | 
							return m.FileToGenerate
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *CodeGeneratorRequest) GetParameter() string {
 | 
				
			||||||
 | 
						if m != nil && m.Parameter != nil {
 | 
				
			||||||
 | 
							return *m.Parameter
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *CodeGeneratorRequest) GetProtoFile() []*descriptor.FileDescriptorProto {
 | 
				
			||||||
 | 
						if m != nil {
 | 
				
			||||||
 | 
							return m.ProtoFile
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *CodeGeneratorRequest) GetCompilerVersion() *Version {
 | 
				
			||||||
 | 
						if m != nil {
 | 
				
			||||||
 | 
							return m.CompilerVersion
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The plugin writes an encoded CodeGeneratorResponse to stdout.
 | 
				
			||||||
 | 
					type CodeGeneratorResponse struct {
 | 
				
			||||||
 | 
						// Error message.  If non-empty, code generation failed.  The plugin process
 | 
				
			||||||
 | 
						// should exit with status code zero even if it reports an error in this way.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// This should be used to indicate errors in .proto files which prevent the
 | 
				
			||||||
 | 
						// code generator from generating correct code.  Errors which indicate a
 | 
				
			||||||
 | 
						// problem in protoc itself -- such as the input CodeGeneratorRequest being
 | 
				
			||||||
 | 
						// unparseable -- should be reported by writing a message to stderr and
 | 
				
			||||||
 | 
						// exiting with a non-zero status code.
 | 
				
			||||||
 | 
						Error                *string                       `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"`
 | 
				
			||||||
 | 
						File                 []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"`
 | 
				
			||||||
 | 
						XXX_NoUnkeyedLiteral struct{}                      `json:"-"`
 | 
				
			||||||
 | 
						XXX_unrecognized     []byte                        `json:"-"`
 | 
				
			||||||
 | 
						XXX_sizecache        int32                         `json:"-"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse) Reset()         { *m = CodeGeneratorResponse{} }
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse) String() string { return proto.CompactTextString(m) }
 | 
				
			||||||
 | 
					func (*CodeGeneratorResponse) ProtoMessage()    {}
 | 
				
			||||||
 | 
					func (*CodeGeneratorResponse) Descriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return fileDescriptor_22a625af4bc1cc87, []int{2}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse) XXX_Unmarshal(b []byte) error {
 | 
				
			||||||
 | 
						return xxx_messageInfo_CodeGeneratorResponse.Unmarshal(m, b)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 | 
				
			||||||
 | 
						return xxx_messageInfo_CodeGeneratorResponse.Marshal(b, m, deterministic)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse) XXX_Merge(src proto.Message) {
 | 
				
			||||||
 | 
						xxx_messageInfo_CodeGeneratorResponse.Merge(m, src)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse) XXX_Size() int {
 | 
				
			||||||
 | 
						return xxx_messageInfo_CodeGeneratorResponse.Size(m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse) XXX_DiscardUnknown() {
 | 
				
			||||||
 | 
						xxx_messageInfo_CodeGeneratorResponse.DiscardUnknown(m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var xxx_messageInfo_CodeGeneratorResponse proto.InternalMessageInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse) GetError() string {
 | 
				
			||||||
 | 
						if m != nil && m.Error != nil {
 | 
				
			||||||
 | 
							return *m.Error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse) GetFile() []*CodeGeneratorResponse_File {
 | 
				
			||||||
 | 
						if m != nil {
 | 
				
			||||||
 | 
							return m.File
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Represents a single generated file.
 | 
				
			||||||
 | 
					type CodeGeneratorResponse_File struct {
 | 
				
			||||||
 | 
						// The file name, relative to the output directory.  The name must not
 | 
				
			||||||
 | 
						// contain "." or ".." components and must be relative, not be absolute (so,
 | 
				
			||||||
 | 
						// the file cannot lie outside the output directory).  "/" must be used as
 | 
				
			||||||
 | 
						// the path separator, not "\".
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// If the name is omitted, the content will be appended to the previous
 | 
				
			||||||
 | 
						// file.  This allows the generator to break large files into small chunks,
 | 
				
			||||||
 | 
						// and allows the generated text to be streamed back to protoc so that large
 | 
				
			||||||
 | 
						// files need not reside completely in memory at one time.  Note that as of
 | 
				
			||||||
 | 
						// this writing protoc does not optimize for this -- it will read the entire
 | 
				
			||||||
 | 
						// CodeGeneratorResponse before writing files to disk.
 | 
				
			||||||
 | 
						Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
 | 
				
			||||||
 | 
						// If non-empty, indicates that the named file should already exist, and the
 | 
				
			||||||
 | 
						// content here is to be inserted into that file at a defined insertion
 | 
				
			||||||
 | 
						// point.  This feature allows a code generator to extend the output
 | 
				
			||||||
 | 
						// produced by another code generator.  The original generator may provide
 | 
				
			||||||
 | 
						// insertion points by placing special annotations in the file that look
 | 
				
			||||||
 | 
						// like:
 | 
				
			||||||
 | 
						//   @@protoc_insertion_point(NAME)
 | 
				
			||||||
 | 
						// The annotation can have arbitrary text before and after it on the line,
 | 
				
			||||||
 | 
						// which allows it to be placed in a comment.  NAME should be replaced with
 | 
				
			||||||
 | 
						// an identifier naming the point -- this is what other generators will use
 | 
				
			||||||
 | 
						// as the insertion_point.  Code inserted at this point will be placed
 | 
				
			||||||
 | 
						// immediately above the line containing the insertion point (thus multiple
 | 
				
			||||||
 | 
						// insertions to the same point will come out in the order they were added).
 | 
				
			||||||
 | 
						// The double-@ is intended to make it unlikely that the generated code
 | 
				
			||||||
 | 
						// could contain things that look like insertion points by accident.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// For example, the C++ code generator places the following line in the
 | 
				
			||||||
 | 
						// .pb.h files that it generates:
 | 
				
			||||||
 | 
						//   // @@protoc_insertion_point(namespace_scope)
 | 
				
			||||||
 | 
						// This line appears within the scope of the file's package namespace, but
 | 
				
			||||||
 | 
						// outside of any particular class.  Another plugin can then specify the
 | 
				
			||||||
 | 
						// insertion_point "namespace_scope" to generate additional classes or
 | 
				
			||||||
 | 
						// other declarations that should be placed in this scope.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Note that if the line containing the insertion point begins with
 | 
				
			||||||
 | 
						// whitespace, the same whitespace will be added to every line of the
 | 
				
			||||||
 | 
						// inserted text.  This is useful for languages like Python, where
 | 
				
			||||||
 | 
						// indentation matters.  In these languages, the insertion point comment
 | 
				
			||||||
 | 
						// should be indented the same amount as any inserted code will need to be
 | 
				
			||||||
 | 
						// in order to work correctly in that context.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// The code generator that generates the initial file and the one which
 | 
				
			||||||
 | 
						// inserts into it must both run as part of a single invocation of protoc.
 | 
				
			||||||
 | 
						// Code generators are executed in the order in which they appear on the
 | 
				
			||||||
 | 
						// command line.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// If |insertion_point| is present, |name| must also be present.
 | 
				
			||||||
 | 
						InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point,json=insertionPoint" json:"insertion_point,omitempty"`
 | 
				
			||||||
 | 
						// The file contents.
 | 
				
			||||||
 | 
						Content              *string  `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"`
 | 
				
			||||||
 | 
						XXX_NoUnkeyedLiteral struct{} `json:"-"`
 | 
				
			||||||
 | 
						XXX_unrecognized     []byte   `json:"-"`
 | 
				
			||||||
 | 
						XXX_sizecache        int32    `json:"-"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse_File) Reset()         { *m = CodeGeneratorResponse_File{} }
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(m) }
 | 
				
			||||||
 | 
					func (*CodeGeneratorResponse_File) ProtoMessage()    {}
 | 
				
			||||||
 | 
					func (*CodeGeneratorResponse_File) Descriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return fileDescriptor_22a625af4bc1cc87, []int{2, 0}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse_File) XXX_Unmarshal(b []byte) error {
 | 
				
			||||||
 | 
						return xxx_messageInfo_CodeGeneratorResponse_File.Unmarshal(m, b)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse_File) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 | 
				
			||||||
 | 
						return xxx_messageInfo_CodeGeneratorResponse_File.Marshal(b, m, deterministic)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse_File) XXX_Merge(src proto.Message) {
 | 
				
			||||||
 | 
						xxx_messageInfo_CodeGeneratorResponse_File.Merge(m, src)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse_File) XXX_Size() int {
 | 
				
			||||||
 | 
						return xxx_messageInfo_CodeGeneratorResponse_File.Size(m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse_File) XXX_DiscardUnknown() {
 | 
				
			||||||
 | 
						xxx_messageInfo_CodeGeneratorResponse_File.DiscardUnknown(m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var xxx_messageInfo_CodeGeneratorResponse_File proto.InternalMessageInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse_File) GetName() string {
 | 
				
			||||||
 | 
						if m != nil && m.Name != nil {
 | 
				
			||||||
 | 
							return *m.Name
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse_File) GetInsertionPoint() string {
 | 
				
			||||||
 | 
						if m != nil && m.InsertionPoint != nil {
 | 
				
			||||||
 | 
							return *m.InsertionPoint
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *CodeGeneratorResponse_File) GetContent() string {
 | 
				
			||||||
 | 
						if m != nil && m.Content != nil {
 | 
				
			||||||
 | 
							return *m.Content
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						proto.RegisterType((*Version)(nil), "google.protobuf.compiler.Version")
 | 
				
			||||||
 | 
						proto.RegisterType((*CodeGeneratorRequest)(nil), "google.protobuf.compiler.CodeGeneratorRequest")
 | 
				
			||||||
 | 
						proto.RegisterType((*CodeGeneratorResponse)(nil), "google.protobuf.compiler.CodeGeneratorResponse")
 | 
				
			||||||
 | 
						proto.RegisterType((*CodeGeneratorResponse_File)(nil), "google.protobuf.compiler.CodeGeneratorResponse.File")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() { proto.RegisterFile("plugin.proto", fileDescriptor_22a625af4bc1cc87) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var fileDescriptor_22a625af4bc1cc87 = []byte{
 | 
				
			||||||
 | 
						// 383 bytes of a gzipped FileDescriptorProto
 | 
				
			||||||
 | 
						0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xcd, 0x6a, 0xd5, 0x40,
 | 
				
			||||||
 | 
						0x14, 0xc7, 0x89, 0x37, 0xb5, 0xe4, 0xb4, 0x34, 0x65, 0xa8, 0x32, 0x94, 0x2e, 0xe2, 0x45, 0x30,
 | 
				
			||||||
 | 
						0xab, 0x14, 0x8a, 0xe0, 0xbe, 0x15, 0x75, 0xe1, 0xe2, 0x32, 0x88, 0x0b, 0x41, 0x42, 0x4c, 0x4f,
 | 
				
			||||||
 | 
						0xe2, 0x48, 0x32, 0x67, 0x9c, 0x99, 0x88, 0x4f, 0xea, 0x7b, 0xf8, 0x06, 0x32, 0x1f, 0xa9, 0x72,
 | 
				
			||||||
 | 
						0xf1, 0xee, 0xe6, 0xff, 0x3b, 0xf3, 0x71, 0xce, 0x8f, 0x81, 0x53, 0x3d, 0x2d, 0xa3, 0x54, 0x8d,
 | 
				
			||||||
 | 
						0x36, 0xe4, 0x88, 0xf1, 0x91, 0x68, 0x9c, 0x30, 0xa6, 0x2f, 0xcb, 0xd0, 0xf4, 0x34, 0x6b, 0x39,
 | 
				
			||||||
 | 
						0xa1, 0xb9, 0xac, 0x62, 0xe5, 0x7a, 0xad, 0x5c, 0xdf, 0xa3, 0xed, 0x8d, 0xd4, 0x8e, 0x4c, 0xdc,
 | 
				
			||||||
 | 
						0xbd, 0xed, 0xe1, 0xf8, 0x23, 0x1a, 0x2b, 0x49, 0xb1, 0x0b, 0x38, 0x9a, 0xbb, 0x6f, 0x64, 0x78,
 | 
				
			||||||
 | 
						0x56, 0x65, 0xf5, 0x91, 0x88, 0x21, 0x50, 0xa9, 0xc8, 0xf0, 0x47, 0x89, 0xfa, 0xe0, 0xa9, 0xee,
 | 
				
			||||||
 | 
						0x5c, 0xff, 0x95, 0x6f, 0x22, 0x0d, 0x81, 0x3d, 0x85, 0xc7, 0x76, 0x19, 0x06, 0xf9, 0x93, 0xe7,
 | 
				
			||||||
 | 
						0x55, 0x56, 0x17, 0x22, 0xa5, 0xed, 0xef, 0x0c, 0x2e, 0xee, 0xe8, 0x1e, 0xdf, 0xa2, 0x42, 0xd3,
 | 
				
			||||||
 | 
						0x39, 0x32, 0x02, 0xbf, 0x2f, 0x68, 0x1d, 0xab, 0xe1, 0x7c, 0x90, 0x13, 0xb6, 0x8e, 0xda, 0x31,
 | 
				
			||||||
 | 
						0xd6, 0x90, 0x67, 0xd5, 0xa6, 0x2e, 0xc4, 0x99, 0xe7, 0x1f, 0x28, 0x9d, 0x40, 0x76, 0x05, 0x85,
 | 
				
			||||||
 | 
						0xee, 0x4c, 0x37, 0xa3, 0xc3, 0xd8, 0x4a, 0x21, 0xfe, 0x02, 0x76, 0x07, 0x10, 0xc6, 0x69, 0xfd,
 | 
				
			||||||
 | 
						0x29, 0x5e, 0x56, 0x9b, 0xfa, 0xe4, 0xe6, 0x79, 0xb3, 0xaf, 0xe5, 0x8d, 0x9c, 0xf0, 0xf5, 0x83,
 | 
				
			||||||
 | 
						0x80, 0x9d, 0xc7, 0xa2, 0x08, 0x55, 0x5f, 0x61, 0xef, 0xe1, 0x7c, 0x15, 0xd7, 0xfe, 0x88, 0x4e,
 | 
				
			||||||
 | 
						0xc2, 0x78, 0x27, 0x37, 0xcf, 0x9a, 0x43, 0x86, 0x9b, 0x24, 0x4f, 0x94, 0x2b, 0x49, 0x60, 0xfb,
 | 
				
			||||||
 | 
						0x2b, 0x83, 0x27, 0x7b, 0x33, 0x5b, 0x4d, 0xca, 0xa2, 0x77, 0x87, 0xc6, 0x24, 0xcf, 0x85, 0x88,
 | 
				
			||||||
 | 
						0x81, 0xbd, 0x83, 0xfc, 0x9f, 0xe6, 0x5f, 0x1e, 0x7e, 0xf1, 0xbf, 0x97, 0x86, 0xd9, 0x44, 0xb8,
 | 
				
			||||||
 | 
						0xe1, 0xf2, 0x33, 0xe4, 0x61, 0x1e, 0x06, 0xb9, 0xea, 0x66, 0x4c, 0xcf, 0x84, 0x35, 0x7b, 0x01,
 | 
				
			||||||
 | 
						0xa5, 0x54, 0x16, 0x8d, 0x93, 0xa4, 0x5a, 0x4d, 0x52, 0xb9, 0x24, 0xf3, 0xec, 0x01, 0xef, 0x3c,
 | 
				
			||||||
 | 
						0x65, 0x1c, 0x8e, 0x7b, 0x52, 0x0e, 0x95, 0xe3, 0x65, 0xd8, 0xb0, 0xc6, 0xdb, 0x57, 0x70, 0xd5,
 | 
				
			||||||
 | 
						0xd3, 0x7c, 0xb0, 0xbf, 0xdb, 0xd3, 0x5d, 0xf8, 0x9b, 0x41, 0xaf, 0xfd, 0x54, 0xc4, 0x9f, 0xda,
 | 
				
			||||||
 | 
						0x8e, 0xf4, 0x27, 0x00, 0x00, 0xff, 0xff, 0x7a, 0x72, 0x3d, 0x18, 0xb5, 0x02, 0x00, 0x00,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2015, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/vanity"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/vanity/command"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						req := command.Read()
 | 
				
			||||||
 | 
						files := req.GetProtoFile()
 | 
				
			||||||
 | 
						files = vanity.FilterFiles(files, vanity.NotGoogleProtobufDescriptorProto)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOnMarshalerAll)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOnSizerAll)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOnUnmarshalerAll)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vanity.ForEachFieldInFilesExcludingExtensions(vanity.OnlyProto2(files), vanity.TurnOffNullableForNativeTypesWithoutDefaultsOnly)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOffGoUnrecognizedAll)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOffGoUnkeyedAll)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOffGoSizecacheAll)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp := command.Generate(req)
 | 
				
			||||||
 | 
						command.Write(resp)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2015, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/vanity"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/vanity/command"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						req := command.Read()
 | 
				
			||||||
 | 
						files := req.GetProtoFile()
 | 
				
			||||||
 | 
						files = vanity.FilterFiles(files, vanity.NotGoogleProtobufDescriptorProto)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOnMarshalerAll)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOnSizerAll)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOnUnmarshalerAll)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vanity.ForEachFieldInFilesExcludingExtensions(vanity.OnlyProto2(files), vanity.TurnOffNullableForNativeTypesWithoutDefaultsOnly)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOffGoUnrecognizedAll)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOffGoUnkeyedAll)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOffGoSizecacheAll)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOffGoEnumPrefixAll)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOffGoEnumStringerAll)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOnEnumStringerAll)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOnEqualAll)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOnGoStringAll)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOffGoStringerAll)
 | 
				
			||||||
 | 
						vanity.ForEachFile(files, vanity.TurnOnStringerAll)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp := command.Generate(req)
 | 
				
			||||||
 | 
						command.Write(resp)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,161 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2015, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"go/format"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/compare"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/defaultcheck"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/description"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/embedcheck"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/enumstringer"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/equal"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/face"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/gostring"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/marshalto"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/oneofcheck"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/populate"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/size"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/stringer"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/plugin/testgen"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/union"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/plugin/unmarshal"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/protoc-gen-gogo/generator"
 | 
				
			||||||
 | 
						_ "github.com/gogo/protobuf/protoc-gen-gogo/grpc"
 | 
				
			||||||
 | 
						plugin "github.com/gogo/protobuf/protoc-gen-gogo/plugin"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Read() *plugin.CodeGeneratorRequest {
 | 
				
			||||||
 | 
						g := generator.New()
 | 
				
			||||||
 | 
						data, err := ioutil.ReadAll(os.Stdin)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							g.Error(err, "reading input")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := proto.Unmarshal(data, g.Request); err != nil {
 | 
				
			||||||
 | 
							g.Error(err, "parsing input proto")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(g.Request.FileToGenerate) == 0 {
 | 
				
			||||||
 | 
							g.Fail("no files to generate")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return g.Request
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// filenameSuffix replaces the .pb.go at the end of each filename.
 | 
				
			||||||
 | 
					func GeneratePlugin(req *plugin.CodeGeneratorRequest, p generator.Plugin, filenameSuffix string) *plugin.CodeGeneratorResponse {
 | 
				
			||||||
 | 
						g := generator.New()
 | 
				
			||||||
 | 
						g.Request = req
 | 
				
			||||||
 | 
						if len(g.Request.FileToGenerate) == 0 {
 | 
				
			||||||
 | 
							g.Fail("no files to generate")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.CommandLineParameters(g.Request.GetParameter())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.WrapTypes()
 | 
				
			||||||
 | 
						g.SetPackageNames()
 | 
				
			||||||
 | 
						g.BuildTypeNameMap()
 | 
				
			||||||
 | 
						g.GeneratePlugin(p)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < len(g.Response.File); i++ {
 | 
				
			||||||
 | 
							g.Response.File[i].Name = proto.String(
 | 
				
			||||||
 | 
								strings.Replace(*g.Response.File[i].Name, ".pb.go", filenameSuffix, -1),
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := goformat(g.Response); err != nil {
 | 
				
			||||||
 | 
							g.Error(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return g.Response
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func goformat(resp *plugin.CodeGeneratorResponse) error {
 | 
				
			||||||
 | 
						for i := 0; i < len(resp.File); i++ {
 | 
				
			||||||
 | 
							formatted, err := format.Source([]byte(resp.File[i].GetContent()))
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("go format error: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fmts := string(formatted)
 | 
				
			||||||
 | 
							resp.File[i].Content = &fmts
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Generate(req *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse {
 | 
				
			||||||
 | 
						// Begin by allocating a generator. The request and response structures are stored there
 | 
				
			||||||
 | 
						// so we can do error handling easily - the response structure contains the field to
 | 
				
			||||||
 | 
						// report failure.
 | 
				
			||||||
 | 
						g := generator.New()
 | 
				
			||||||
 | 
						g.Request = req
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.CommandLineParameters(g.Request.GetParameter())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create a wrapped version of the Descriptors and EnumDescriptors that
 | 
				
			||||||
 | 
						// point to the file that defines them.
 | 
				
			||||||
 | 
						g.WrapTypes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.SetPackageNames()
 | 
				
			||||||
 | 
						g.BuildTypeNameMap()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.GenerateAllFiles()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := goformat(g.Response); err != nil {
 | 
				
			||||||
 | 
							g.Error(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testReq := proto.Clone(req).(*plugin.CodeGeneratorRequest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testResp := GeneratePlugin(testReq, testgen.NewPlugin(), "pb_test.go")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < len(testResp.File); i++ {
 | 
				
			||||||
 | 
							if strings.Contains(*testResp.File[i].Content, `//These tests are generated by github.com/gogo/protobuf/plugin/testgen`) {
 | 
				
			||||||
 | 
								g.Response.File = append(g.Response.File, testResp.File[i])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return g.Response
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Write(resp *plugin.CodeGeneratorResponse) {
 | 
				
			||||||
 | 
						g := generator.New()
 | 
				
			||||||
 | 
						// Send back the results.
 | 
				
			||||||
 | 
						data, err := proto.Marshal(resp)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							g.Error(err, "failed to marshal output proto")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err = os.Stdout.Write(data)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							g.Error(err, "failed to write output proto")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2015, The GoGo Authors.  rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package vanity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func EnumHasBoolExtension(enum *descriptor.EnumDescriptorProto, extension *proto.ExtensionDesc) bool {
 | 
				
			||||||
 | 
						if enum.Options == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						value, err := proto.GetExtension(enum.Options, extension)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if value == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if value.(*bool) == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func SetBoolEnumOption(extension *proto.ExtensionDesc, value bool) func(enum *descriptor.EnumDescriptorProto) {
 | 
				
			||||||
 | 
						return func(enum *descriptor.EnumDescriptorProto) {
 | 
				
			||||||
 | 
							if EnumHasBoolExtension(enum, extension) {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if enum.Options == nil {
 | 
				
			||||||
 | 
								enum.Options = &descriptor.EnumOptions{}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := proto.SetExtension(enum.Options, extension, &value); err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoEnumPrefix(enum *descriptor.EnumDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolEnumOption(gogoproto.E_GoprotoEnumPrefix, false)(enum)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoEnumStringer(enum *descriptor.EnumDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolEnumOption(gogoproto.E_GoprotoEnumStringer, false)(enum)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnEnumStringer(enum *descriptor.EnumDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolEnumOption(gogoproto.E_EnumStringer, true)(enum)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2015, The GoGo Authors.  rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package vanity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func FieldHasBoolExtension(field *descriptor.FieldDescriptorProto, extension *proto.ExtensionDesc) bool {
 | 
				
			||||||
 | 
						if field.Options == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						value, err := proto.GetExtension(field.Options, extension)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if value == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if value.(*bool) == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func SetBoolFieldOption(extension *proto.ExtensionDesc, value bool) func(field *descriptor.FieldDescriptorProto) {
 | 
				
			||||||
 | 
						return func(field *descriptor.FieldDescriptorProto) {
 | 
				
			||||||
 | 
							if FieldHasBoolExtension(field, extension) {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if field.Options == nil {
 | 
				
			||||||
 | 
								field.Options = &descriptor.FieldOptions{}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := proto.SetExtension(field.Options, extension, &value); err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffNullable(field *descriptor.FieldDescriptorProto) {
 | 
				
			||||||
 | 
						if field.IsRepeated() && !field.IsMessage() {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffNullableForNativeTypes(field *descriptor.FieldDescriptorProto) {
 | 
				
			||||||
 | 
						if field.IsRepeated() || field.IsMessage() {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffNullableForNativeTypesWithoutDefaultsOnly(field *descriptor.FieldDescriptorProto) {
 | 
				
			||||||
 | 
						if field.IsRepeated() || field.IsMessage() {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if field.DefaultValue != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,197 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2015, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package vanity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NotGoogleProtobufDescriptorProto(file *descriptor.FileDescriptorProto) bool {
 | 
				
			||||||
 | 
						// can not just check if file.GetName() == "google/protobuf/descriptor.proto" because we do not want to assume compile path
 | 
				
			||||||
 | 
						_, fileName := filepath.Split(file.GetName())
 | 
				
			||||||
 | 
						return !(file.GetPackage() == "google.protobuf" && fileName == "descriptor.proto")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func FilterFiles(files []*descriptor.FileDescriptorProto, f func(file *descriptor.FileDescriptorProto) bool) []*descriptor.FileDescriptorProto {
 | 
				
			||||||
 | 
						filtered := make([]*descriptor.FileDescriptorProto, 0, len(files))
 | 
				
			||||||
 | 
						for i := range files {
 | 
				
			||||||
 | 
							if !f(files[i]) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							filtered = append(filtered, files[i])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return filtered
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func FileHasBoolExtension(file *descriptor.FileDescriptorProto, extension *proto.ExtensionDesc) bool {
 | 
				
			||||||
 | 
						if file.Options == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						value, err := proto.GetExtension(file.Options, extension)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if value == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if value.(*bool) == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func SetBoolFileOption(extension *proto.ExtensionDesc, value bool) func(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						return func(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
							if FileHasBoolExtension(file, extension) {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if file.Options == nil {
 | 
				
			||||||
 | 
								file.Options = &descriptor.FileOptions{}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := proto.SetExtension(file.Options, extension, &value); err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoGettersAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_GoprotoGettersAll, false)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoEnumPrefixAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_GoprotoEnumPrefixAll, false)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoStringerAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_GoprotoStringerAll, false)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnVerboseEqualAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_VerboseEqualAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnFaceAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_FaceAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnGoStringAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_GostringAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnPopulateAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_PopulateAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnStringerAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_StringerAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnEqualAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_EqualAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnDescriptionAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_DescriptionAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnTestGenAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_TestgenAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnBenchGenAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_BenchgenAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnMarshalerAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_MarshalerAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnUnmarshalerAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_UnmarshalerAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnStable_MarshalerAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_StableMarshalerAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnSizerAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_SizerAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoEnumStringerAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_GoprotoEnumStringerAll, false)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnEnumStringerAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_EnumStringerAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnUnsafeUnmarshalerAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_UnsafeUnmarshalerAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnUnsafeMarshalerAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_UnsafeMarshalerAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoExtensionsMapAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_GoprotoExtensionsMapAll, false)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoUnrecognizedAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_GoprotoUnrecognizedAll, false)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoUnkeyedAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_GoprotoUnkeyedAll, false)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoSizecacheAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_GoprotoSizecacheAll, false)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGogoImport(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_GogoprotoImport, false)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnCompareAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_CompareAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnMessageNameAll(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_MessagenameAll, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnGoRegistration(file *descriptor.FileDescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolFileOption(gogoproto.E_GoprotoRegistration, true)(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,125 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2015, The GoGo Authors. All rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package vanity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ForEachFile(files []*descriptor.FileDescriptorProto, f func(file *descriptor.FileDescriptorProto)) {
 | 
				
			||||||
 | 
						for _, file := range files {
 | 
				
			||||||
 | 
							f(file)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func OnlyProto2(files []*descriptor.FileDescriptorProto) []*descriptor.FileDescriptorProto {
 | 
				
			||||||
 | 
						outs := make([]*descriptor.FileDescriptorProto, 0, len(files))
 | 
				
			||||||
 | 
						for i, file := range files {
 | 
				
			||||||
 | 
							if file.GetSyntax() == "proto3" {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							outs = append(outs, files[i])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return outs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func OnlyProto3(files []*descriptor.FileDescriptorProto) []*descriptor.FileDescriptorProto {
 | 
				
			||||||
 | 
						outs := make([]*descriptor.FileDescriptorProto, 0, len(files))
 | 
				
			||||||
 | 
						for i, file := range files {
 | 
				
			||||||
 | 
							if file.GetSyntax() != "proto3" {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							outs = append(outs, files[i])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return outs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ForEachMessageInFiles(files []*descriptor.FileDescriptorProto, f func(msg *descriptor.DescriptorProto)) {
 | 
				
			||||||
 | 
						for _, file := range files {
 | 
				
			||||||
 | 
							ForEachMessage(file.MessageType, f)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ForEachMessage(msgs []*descriptor.DescriptorProto, f func(msg *descriptor.DescriptorProto)) {
 | 
				
			||||||
 | 
						for _, msg := range msgs {
 | 
				
			||||||
 | 
							f(msg)
 | 
				
			||||||
 | 
							ForEachMessage(msg.NestedType, f)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ForEachFieldInFilesExcludingExtensions(files []*descriptor.FileDescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
 | 
				
			||||||
 | 
						for _, file := range files {
 | 
				
			||||||
 | 
							ForEachFieldExcludingExtensions(file.MessageType, f)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ForEachFieldInFiles(files []*descriptor.FileDescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
 | 
				
			||||||
 | 
						for _, file := range files {
 | 
				
			||||||
 | 
							for _, ext := range file.Extension {
 | 
				
			||||||
 | 
								f(ext)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ForEachField(file.MessageType, f)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ForEachFieldExcludingExtensions(msgs []*descriptor.DescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
 | 
				
			||||||
 | 
						for _, msg := range msgs {
 | 
				
			||||||
 | 
							for _, field := range msg.Field {
 | 
				
			||||||
 | 
								f(field)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ForEachField(msg.NestedType, f)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ForEachField(msgs []*descriptor.DescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
 | 
				
			||||||
 | 
						for _, msg := range msgs {
 | 
				
			||||||
 | 
							for _, field := range msg.Field {
 | 
				
			||||||
 | 
								f(field)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for _, ext := range msg.Extension {
 | 
				
			||||||
 | 
								f(ext)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ForEachField(msg.NestedType, f)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ForEachEnumInFiles(files []*descriptor.FileDescriptorProto, f func(enum *descriptor.EnumDescriptorProto)) {
 | 
				
			||||||
 | 
						for _, file := range files {
 | 
				
			||||||
 | 
							for _, enum := range file.EnumType {
 | 
				
			||||||
 | 
								f(enum)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ForEachEnum(msgs []*descriptor.DescriptorProto, f func(field *descriptor.EnumDescriptorProto)) {
 | 
				
			||||||
 | 
						for _, msg := range msgs {
 | 
				
			||||||
 | 
							for _, field := range msg.EnumType {
 | 
				
			||||||
 | 
								f(field)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ForEachEnum(msg.NestedType, f)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,154 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers for Go with Gadgets
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright (c) 2015, The GoGo Authors.  rights reserved.
 | 
				
			||||||
 | 
					// http://github.com/gogo/protobuf
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package vanity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/gogoproto"
 | 
				
			||||||
 | 
						"github.com/gogo/protobuf/proto"
 | 
				
			||||||
 | 
						descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func MessageHasBoolExtension(msg *descriptor.DescriptorProto, extension *proto.ExtensionDesc) bool {
 | 
				
			||||||
 | 
						if msg.Options == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						value, err := proto.GetExtension(msg.Options, extension)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if value == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if value.(*bool) == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func SetBoolMessageOption(extension *proto.ExtensionDesc, value bool) func(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						return func(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
							if MessageHasBoolExtension(msg, extension) {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if msg.Options == nil {
 | 
				
			||||||
 | 
								msg.Options = &descriptor.MessageOptions{}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := proto.SetExtension(msg.Options, extension, &value); err != nil {
 | 
				
			||||||
 | 
								panic(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoGetters(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_GoprotoGetters, false)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoStringer(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_GoprotoStringer, false)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnVerboseEqual(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_VerboseEqual, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnFace(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_Face, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnGoString(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_Face, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnPopulate(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_Populate, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnStringer(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_Stringer, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnEqual(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_Equal, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnDescription(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_Description, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnTestGen(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_Testgen, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnBenchGen(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_Benchgen, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnMarshaler(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_Marshaler, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnUnmarshaler(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_Unmarshaler, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnSizer(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_Sizer, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnUnsafeUnmarshaler(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_UnsafeUnmarshaler, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnUnsafeMarshaler(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_UnsafeMarshaler, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoExtensionsMap(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_GoprotoExtensionsMap, false)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoUnrecognized(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_GoprotoUnrecognized, false)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoUnkeyed(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_GoprotoUnkeyed, false)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOffGoSizecache(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_GoprotoSizecache, false)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnCompare(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_Compare, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TurnOnMessageName(msg *descriptor.DescriptorProto) {
 | 
				
			||||||
 | 
						SetBoolMessageOption(gogoproto.E_Messagename, true)(msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,398 @@
 | 
				
			|||||||
 | 
					// Copyright 2018 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Package gengogrpc contains the gRPC code generator.
 | 
				
			||||||
 | 
					package gengogrpc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/compiler/protogen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/descriptorpb"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						contextPackage = protogen.GoImportPath("context")
 | 
				
			||||||
 | 
						grpcPackage    = protogen.GoImportPath("google.golang.org/grpc")
 | 
				
			||||||
 | 
						codesPackage   = protogen.GoImportPath("google.golang.org/grpc/codes")
 | 
				
			||||||
 | 
						statusPackage  = protogen.GoImportPath("google.golang.org/grpc/status")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GenerateFile generates a _grpc.pb.go file containing gRPC service definitions.
 | 
				
			||||||
 | 
					func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile {
 | 
				
			||||||
 | 
						if len(file.Services) == 0 {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						filename := file.GeneratedFilenamePrefix + "_grpc.pb.go"
 | 
				
			||||||
 | 
						g := gen.NewGeneratedFile(filename, file.GoImportPath)
 | 
				
			||||||
 | 
						g.P("// Code generated by protoc-gen-go-grpc. DO NOT EDIT.")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
						g.P("package ", file.GoPackageName)
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
						GenerateFileContent(gen, file, g)
 | 
				
			||||||
 | 
						return g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GenerateFileContent generates the gRPC service definitions, excluding the package statement.
 | 
				
			||||||
 | 
					func GenerateFileContent(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile) {
 | 
				
			||||||
 | 
						if len(file.Services) == 0 {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: Remove this. We don't need to include these references any more.
 | 
				
			||||||
 | 
						g.P("// Reference imports to suppress errors if they are not otherwise used.")
 | 
				
			||||||
 | 
						g.P("var _ ", contextPackage.Ident("Context"))
 | 
				
			||||||
 | 
						g.P("var _ ", grpcPackage.Ident("ClientConnInterface"))
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("// This is a compile-time assertion to ensure that this generated file")
 | 
				
			||||||
 | 
						g.P("// is compatible with the grpc package it is being compiled against.")
 | 
				
			||||||
 | 
						g.P("const _ = ", grpcPackage.Ident("SupportPackageIsVersion6"))
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
						for _, service := range file.Services {
 | 
				
			||||||
 | 
							genService(gen, file, g, service)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, service *protogen.Service) {
 | 
				
			||||||
 | 
						clientName := service.GoName + "Client"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("// ", clientName, " is the client API for ", service.GoName, " service.")
 | 
				
			||||||
 | 
						g.P("//")
 | 
				
			||||||
 | 
						g.P("// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Client interface.
 | 
				
			||||||
 | 
						if service.Desc.Options().(*descriptorpb.ServiceOptions).GetDeprecated() {
 | 
				
			||||||
 | 
							g.P("//")
 | 
				
			||||||
 | 
							g.P(deprecationComment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.Annotate(clientName, service.Location)
 | 
				
			||||||
 | 
						g.P("type ", clientName, " interface {")
 | 
				
			||||||
 | 
						for _, method := range service.Methods {
 | 
				
			||||||
 | 
							g.Annotate(clientName+"."+method.GoName, method.Location)
 | 
				
			||||||
 | 
							if method.Desc.Options().(*descriptorpb.MethodOptions).GetDeprecated() {
 | 
				
			||||||
 | 
								g.P(deprecationComment)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P(method.Comments.Leading,
 | 
				
			||||||
 | 
								clientSignature(g, method))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Client structure.
 | 
				
			||||||
 | 
						g.P("type ", unexport(clientName), " struct {")
 | 
				
			||||||
 | 
						g.P("cc ", grpcPackage.Ident("ClientConnInterface"))
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// NewClient factory.
 | 
				
			||||||
 | 
						if service.Desc.Options().(*descriptorpb.ServiceOptions).GetDeprecated() {
 | 
				
			||||||
 | 
							g.P(deprecationComment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("func New", clientName, " (cc ", grpcPackage.Ident("ClientConnInterface"), ") ", clientName, " {")
 | 
				
			||||||
 | 
						g.P("return &", unexport(clientName), "{cc}")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var methodIndex, streamIndex int
 | 
				
			||||||
 | 
						// Client method implementations.
 | 
				
			||||||
 | 
						for _, method := range service.Methods {
 | 
				
			||||||
 | 
							if !method.Desc.IsStreamingServer() && !method.Desc.IsStreamingClient() {
 | 
				
			||||||
 | 
								// Unary RPC method
 | 
				
			||||||
 | 
								genClientMethod(gen, file, g, method, methodIndex)
 | 
				
			||||||
 | 
								methodIndex++
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								// Streaming RPC method
 | 
				
			||||||
 | 
								genClientMethod(gen, file, g, method, streamIndex)
 | 
				
			||||||
 | 
								streamIndex++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Server interface.
 | 
				
			||||||
 | 
						serverType := service.GoName + "Server"
 | 
				
			||||||
 | 
						g.P("// ", serverType, " is the server API for ", service.GoName, " service.")
 | 
				
			||||||
 | 
						if service.Desc.Options().(*descriptorpb.ServiceOptions).GetDeprecated() {
 | 
				
			||||||
 | 
							g.P("//")
 | 
				
			||||||
 | 
							g.P(deprecationComment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.Annotate(serverType, service.Location)
 | 
				
			||||||
 | 
						g.P("type ", serverType, " interface {")
 | 
				
			||||||
 | 
						for _, method := range service.Methods {
 | 
				
			||||||
 | 
							g.Annotate(serverType+"."+method.GoName, method.Location)
 | 
				
			||||||
 | 
							if method.Desc.Options().(*descriptorpb.MethodOptions).GetDeprecated() {
 | 
				
			||||||
 | 
								g.P(deprecationComment)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P(method.Comments.Leading,
 | 
				
			||||||
 | 
								serverSignature(g, method))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Server Unimplemented struct for forward compatibility.
 | 
				
			||||||
 | 
						g.P("// Unimplemented", serverType, " can be embedded to have forward compatible implementations.")
 | 
				
			||||||
 | 
						g.P("type Unimplemented", serverType, " struct {")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
						for _, method := range service.Methods {
 | 
				
			||||||
 | 
							nilArg := ""
 | 
				
			||||||
 | 
							if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() {
 | 
				
			||||||
 | 
								nilArg = "nil,"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P("func (*Unimplemented", serverType, ") ", serverSignature(g, method), "{")
 | 
				
			||||||
 | 
							g.P("return ", nilArg, statusPackage.Ident("Errorf"), "(", codesPackage.Ident("Unimplemented"), `, "method `, method.GoName, ` not implemented")`)
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Server registration.
 | 
				
			||||||
 | 
						if service.Desc.Options().(*descriptorpb.ServiceOptions).GetDeprecated() {
 | 
				
			||||||
 | 
							g.P(deprecationComment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						serviceDescVar := "_" + service.GoName + "_serviceDesc"
 | 
				
			||||||
 | 
						g.P("func Register", service.GoName, "Server(s *", grpcPackage.Ident("Server"), ", srv ", serverType, ") {")
 | 
				
			||||||
 | 
						g.P("s.RegisterService(&", serviceDescVar, `, srv)`)
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Server handler implementations.
 | 
				
			||||||
 | 
						var handlerNames []string
 | 
				
			||||||
 | 
						for _, method := range service.Methods {
 | 
				
			||||||
 | 
							hname := genServerMethod(gen, file, g, method)
 | 
				
			||||||
 | 
							handlerNames = append(handlerNames, hname)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Service descriptor.
 | 
				
			||||||
 | 
						g.P("var ", serviceDescVar, " = ", grpcPackage.Ident("ServiceDesc"), " {")
 | 
				
			||||||
 | 
						g.P("ServiceName: ", strconv.Quote(string(service.Desc.FullName())), ",")
 | 
				
			||||||
 | 
						g.P("HandlerType: (*", serverType, ")(nil),")
 | 
				
			||||||
 | 
						g.P("Methods: []", grpcPackage.Ident("MethodDesc"), "{")
 | 
				
			||||||
 | 
						for i, method := range service.Methods {
 | 
				
			||||||
 | 
							if method.Desc.IsStreamingClient() || method.Desc.IsStreamingServer() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P("{")
 | 
				
			||||||
 | 
							g.P("MethodName: ", strconv.Quote(string(method.Desc.Name())), ",")
 | 
				
			||||||
 | 
							g.P("Handler: ", handlerNames[i], ",")
 | 
				
			||||||
 | 
							g.P("},")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("},")
 | 
				
			||||||
 | 
						g.P("Streams: []", grpcPackage.Ident("StreamDesc"), "{")
 | 
				
			||||||
 | 
						for i, method := range service.Methods {
 | 
				
			||||||
 | 
							if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P("{")
 | 
				
			||||||
 | 
							g.P("StreamName: ", strconv.Quote(string(method.Desc.Name())), ",")
 | 
				
			||||||
 | 
							g.P("Handler: ", handlerNames[i], ",")
 | 
				
			||||||
 | 
							if method.Desc.IsStreamingServer() {
 | 
				
			||||||
 | 
								g.P("ServerStreams: true,")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if method.Desc.IsStreamingClient() {
 | 
				
			||||||
 | 
								g.P("ClientStreams: true,")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P("},")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("},")
 | 
				
			||||||
 | 
						g.P("Metadata: \"", file.Desc.Path(), "\",")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func clientSignature(g *protogen.GeneratedFile, method *protogen.Method) string {
 | 
				
			||||||
 | 
						s := method.GoName + "(ctx " + g.QualifiedGoIdent(contextPackage.Ident("Context"))
 | 
				
			||||||
 | 
						if !method.Desc.IsStreamingClient() {
 | 
				
			||||||
 | 
							s += ", in *" + g.QualifiedGoIdent(method.Input.GoIdent)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s += ", opts ..." + g.QualifiedGoIdent(grpcPackage.Ident("CallOption")) + ") ("
 | 
				
			||||||
 | 
						if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() {
 | 
				
			||||||
 | 
							s += "*" + g.QualifiedGoIdent(method.Output.GoIdent)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							s += method.Parent.GoName + "_" + method.GoName + "Client"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s += ", error)"
 | 
				
			||||||
 | 
						return s
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genClientMethod(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, method *protogen.Method, index int) {
 | 
				
			||||||
 | 
						service := method.Parent
 | 
				
			||||||
 | 
						sname := fmt.Sprintf("/%s/%s", service.Desc.FullName(), method.Desc.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if method.Desc.Options().(*descriptorpb.MethodOptions).GetDeprecated() {
 | 
				
			||||||
 | 
							g.P(deprecationComment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("func (c *", unexport(service.GoName), "Client) ", clientSignature(g, method), "{")
 | 
				
			||||||
 | 
						if !method.Desc.IsStreamingServer() && !method.Desc.IsStreamingClient() {
 | 
				
			||||||
 | 
							g.P("out := new(", method.Output.GoIdent, ")")
 | 
				
			||||||
 | 
							g.P(`err := c.cc.Invoke(ctx, "`, sname, `", in, out, opts...)`)
 | 
				
			||||||
 | 
							g.P("if err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("return out, nil")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						streamType := unexport(service.GoName) + method.GoName + "Client"
 | 
				
			||||||
 | 
						serviceDescVar := "_" + service.GoName + "_serviceDesc"
 | 
				
			||||||
 | 
						g.P("stream, err := c.cc.NewStream(ctx, &", serviceDescVar, ".Streams[", index, `], "`, sname, `", opts...)`)
 | 
				
			||||||
 | 
						g.P("if err != nil { return nil, err }")
 | 
				
			||||||
 | 
						g.P("x := &", streamType, "{stream}")
 | 
				
			||||||
 | 
						if !method.Desc.IsStreamingClient() {
 | 
				
			||||||
 | 
							g.P("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("return x, nil")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						genSend := method.Desc.IsStreamingClient()
 | 
				
			||||||
 | 
						genRecv := method.Desc.IsStreamingServer()
 | 
				
			||||||
 | 
						genCloseAndRecv := !method.Desc.IsStreamingServer()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Stream auxiliary types and methods.
 | 
				
			||||||
 | 
						g.P("type ", service.GoName, "_", method.GoName, "Client interface {")
 | 
				
			||||||
 | 
						if genSend {
 | 
				
			||||||
 | 
							g.P("Send(*", method.Input.GoIdent, ") error")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genRecv {
 | 
				
			||||||
 | 
							g.P("Recv() (*", method.Output.GoIdent, ", error)")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genCloseAndRecv {
 | 
				
			||||||
 | 
							g.P("CloseAndRecv() (*", method.Output.GoIdent, ", error)")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P(grpcPackage.Ident("ClientStream"))
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("type ", streamType, " struct {")
 | 
				
			||||||
 | 
						g.P(grpcPackage.Ident("ClientStream"))
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if genSend {
 | 
				
			||||||
 | 
							g.P("func (x *", streamType, ") Send(m *", method.Input.GoIdent, ") error {")
 | 
				
			||||||
 | 
							g.P("return x.ClientStream.SendMsg(m)")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genRecv {
 | 
				
			||||||
 | 
							g.P("func (x *", streamType, ") Recv() (*", method.Output.GoIdent, ", error) {")
 | 
				
			||||||
 | 
							g.P("m := new(", method.Output.GoIdent, ")")
 | 
				
			||||||
 | 
							g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("return m, nil")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genCloseAndRecv {
 | 
				
			||||||
 | 
							g.P("func (x *", streamType, ") CloseAndRecv() (*", method.Output.GoIdent, ", error) {")
 | 
				
			||||||
 | 
							g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("m := new(", method.Output.GoIdent, ")")
 | 
				
			||||||
 | 
							g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("return m, nil")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func serverSignature(g *protogen.GeneratedFile, method *protogen.Method) string {
 | 
				
			||||||
 | 
						var reqArgs []string
 | 
				
			||||||
 | 
						ret := "error"
 | 
				
			||||||
 | 
						if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() {
 | 
				
			||||||
 | 
							reqArgs = append(reqArgs, g.QualifiedGoIdent(contextPackage.Ident("Context")))
 | 
				
			||||||
 | 
							ret = "(*" + g.QualifiedGoIdent(method.Output.GoIdent) + ", error)"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !method.Desc.IsStreamingClient() {
 | 
				
			||||||
 | 
							reqArgs = append(reqArgs, "*"+g.QualifiedGoIdent(method.Input.GoIdent))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if method.Desc.IsStreamingClient() || method.Desc.IsStreamingServer() {
 | 
				
			||||||
 | 
							reqArgs = append(reqArgs, method.Parent.GoName+"_"+method.GoName+"Server")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return method.GoName + "(" + strings.Join(reqArgs, ", ") + ") " + ret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genServerMethod(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, method *protogen.Method) string {
 | 
				
			||||||
 | 
						service := method.Parent
 | 
				
			||||||
 | 
						hname := fmt.Sprintf("_%s_%s_Handler", service.GoName, method.GoName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() {
 | 
				
			||||||
 | 
							g.P("func ", hname, "(srv interface{}, ctx ", contextPackage.Ident("Context"), ", dec func(interface{}) error, interceptor ", grpcPackage.Ident("UnaryServerInterceptor"), ") (interface{}, error) {")
 | 
				
			||||||
 | 
							g.P("in := new(", method.Input.GoIdent, ")")
 | 
				
			||||||
 | 
							g.P("if err := dec(in); err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("if interceptor == nil { return srv.(", service.GoName, "Server).", method.GoName, "(ctx, in) }")
 | 
				
			||||||
 | 
							g.P("info := &", grpcPackage.Ident("UnaryServerInfo"), "{")
 | 
				
			||||||
 | 
							g.P("Server: srv,")
 | 
				
			||||||
 | 
							g.P("FullMethod: ", strconv.Quote(fmt.Sprintf("/%s/%s", service.Desc.FullName(), method.GoName)), ",")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P("handler := func(ctx ", contextPackage.Ident("Context"), ", req interface{}) (interface{}, error) {")
 | 
				
			||||||
 | 
							g.P("return srv.(", service.GoName, "Server).", method.GoName, "(ctx, req.(*", method.Input.GoIdent, "))")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P("return interceptor(ctx, in, info, handler)")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
							return hname
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						streamType := unexport(service.GoName) + method.GoName + "Server"
 | 
				
			||||||
 | 
						g.P("func ", hname, "(srv interface{}, stream ", grpcPackage.Ident("ServerStream"), ") error {")
 | 
				
			||||||
 | 
						if !method.Desc.IsStreamingClient() {
 | 
				
			||||||
 | 
							g.P("m := new(", method.Input.GoIdent, ")")
 | 
				
			||||||
 | 
							g.P("if err := stream.RecvMsg(m); err != nil { return err }")
 | 
				
			||||||
 | 
							g.P("return srv.(", service.GoName, "Server).", method.GoName, "(m, &", streamType, "{stream})")
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							g.P("return srv.(", service.GoName, "Server).", method.GoName, "(&", streamType, "{stream})")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						genSend := method.Desc.IsStreamingServer()
 | 
				
			||||||
 | 
						genSendAndClose := !method.Desc.IsStreamingServer()
 | 
				
			||||||
 | 
						genRecv := method.Desc.IsStreamingClient()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Stream auxiliary types and methods.
 | 
				
			||||||
 | 
						g.P("type ", service.GoName, "_", method.GoName, "Server interface {")
 | 
				
			||||||
 | 
						if genSend {
 | 
				
			||||||
 | 
							g.P("Send(*", method.Output.GoIdent, ") error")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genSendAndClose {
 | 
				
			||||||
 | 
							g.P("SendAndClose(*", method.Output.GoIdent, ") error")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genRecv {
 | 
				
			||||||
 | 
							g.P("Recv() (*", method.Input.GoIdent, ", error)")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P(grpcPackage.Ident("ServerStream"))
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("type ", streamType, " struct {")
 | 
				
			||||||
 | 
						g.P(grpcPackage.Ident("ServerStream"))
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if genSend {
 | 
				
			||||||
 | 
							g.P("func (x *", streamType, ") Send(m *", method.Output.GoIdent, ") error {")
 | 
				
			||||||
 | 
							g.P("return x.ServerStream.SendMsg(m)")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genSendAndClose {
 | 
				
			||||||
 | 
							g.P("func (x *", streamType, ") SendAndClose(m *", method.Output.GoIdent, ") error {")
 | 
				
			||||||
 | 
							g.P("return x.ServerStream.SendMsg(m)")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if genRecv {
 | 
				
			||||||
 | 
							g.P("func (x *", streamType, ") Recv() (*", method.Input.GoIdent, ", error) {")
 | 
				
			||||||
 | 
							g.P("m := new(", method.Input.GoIdent, ")")
 | 
				
			||||||
 | 
							g.P("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }")
 | 
				
			||||||
 | 
							g.P("return m, nil")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return hname
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const deprecationComment = "// Deprecated: Do not use."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func unexport(s string) string { return strings.ToLower(s[:1]) + s[1:] }
 | 
				
			||||||
@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					// Copyright 2010 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// protoc-gen-go is a plugin for the Google protocol buffer compiler to generate
 | 
				
			||||||
 | 
					// Go code. Install it by building this program and making it accessible within
 | 
				
			||||||
 | 
					// your PATH with the name:
 | 
				
			||||||
 | 
					//	protoc-gen-go
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The 'go' suffix becomes part of the argument for the protocol compiler,
 | 
				
			||||||
 | 
					// such that it can be invoked as:
 | 
				
			||||||
 | 
					//	protoc --go_out=paths=source_relative:. path/to/file.proto
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This generates Go bindings for the protocol buffer defined by file.proto.
 | 
				
			||||||
 | 
					// With that input, the output will be written to:
 | 
				
			||||||
 | 
					//	path/to/file.pb.go
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See the README and documentation for protocol buffers to learn more:
 | 
				
			||||||
 | 
					//	https://developers.google.com/protocol-buffers/
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"flag"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/golang/protobuf/internal/gengogrpc"
 | 
				
			||||||
 | 
						gengo "google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/compiler/protogen"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							flags        flag.FlagSet
 | 
				
			||||||
 | 
							plugins      = flags.String("plugins", "", "list of plugins to enable (supported values: grpc)")
 | 
				
			||||||
 | 
							importPrefix = flags.String("import_prefix", "", "prefix to prepend to import paths")
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						importRewriteFunc := func(importPath protogen.GoImportPath) protogen.GoImportPath {
 | 
				
			||||||
 | 
							switch importPath {
 | 
				
			||||||
 | 
							case "context", "fmt", "math":
 | 
				
			||||||
 | 
								return importPath
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if *importPrefix != "" {
 | 
				
			||||||
 | 
								return protogen.GoImportPath(*importPrefix) + importPath
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return importPath
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						protogen.Options{
 | 
				
			||||||
 | 
							ParamFunc:         flags.Set,
 | 
				
			||||||
 | 
							ImportRewriteFunc: importRewriteFunc,
 | 
				
			||||||
 | 
						}.Run(func(gen *protogen.Plugin) error {
 | 
				
			||||||
 | 
							grpc := false
 | 
				
			||||||
 | 
							for _, plugin := range strings.Split(*plugins, ",") {
 | 
				
			||||||
 | 
								switch plugin {
 | 
				
			||||||
 | 
								case "grpc":
 | 
				
			||||||
 | 
									grpc = true
 | 
				
			||||||
 | 
								case "":
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									return fmt.Errorf("protoc-gen-go: unknown plugin %q", plugin)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for _, f := range gen.Files {
 | 
				
			||||||
 | 
								if !f.Generate {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								g := gengo.GenerateFile(gen, f)
 | 
				
			||||||
 | 
								if grpc {
 | 
				
			||||||
 | 
									gengogrpc.GenerateFileContent(gen, f, g)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							gen.SupportedFeatures = gengo.SupportedFeatures
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,168 @@
 | 
				
			|||||||
 | 
					// Copyright 2019 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package internal_gengo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"unicode"
 | 
				
			||||||
 | 
						"unicode/utf8"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/compiler/protogen"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/encoding/protowire"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/descriptorpb"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type fileInfo struct {
 | 
				
			||||||
 | 
						*protogen.File
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allEnums      []*enumInfo
 | 
				
			||||||
 | 
						allMessages   []*messageInfo
 | 
				
			||||||
 | 
						allExtensions []*extensionInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allEnumsByPtr         map[*enumInfo]int    // value is index into allEnums
 | 
				
			||||||
 | 
						allMessagesByPtr      map[*messageInfo]int // value is index into allMessages
 | 
				
			||||||
 | 
						allMessageFieldsByPtr map[*messageInfo]*structFields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// needRawDesc specifies whether the generator should emit logic to provide
 | 
				
			||||||
 | 
						// the legacy raw descriptor in GZIP'd form.
 | 
				
			||||||
 | 
						// This is updated by enum and message generation logic as necessary,
 | 
				
			||||||
 | 
						// and checked at the end of file generation.
 | 
				
			||||||
 | 
						needRawDesc bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type structFields struct {
 | 
				
			||||||
 | 
						count      int
 | 
				
			||||||
 | 
						unexported map[int]string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (sf *structFields) append(name string) {
 | 
				
			||||||
 | 
						if r, _ := utf8.DecodeRuneInString(name); !unicode.IsUpper(r) {
 | 
				
			||||||
 | 
							if sf.unexported == nil {
 | 
				
			||||||
 | 
								sf.unexported = make(map[int]string)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							sf.unexported[sf.count] = name
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sf.count++
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newFileInfo(file *protogen.File) *fileInfo {
 | 
				
			||||||
 | 
						f := &fileInfo{File: file}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Collect all enums, messages, and extensions in "flattened ordering".
 | 
				
			||||||
 | 
						// See filetype.TypeBuilder.
 | 
				
			||||||
 | 
						var walkMessages func([]*protogen.Message, func(*protogen.Message))
 | 
				
			||||||
 | 
						walkMessages = func(messages []*protogen.Message, f func(*protogen.Message)) {
 | 
				
			||||||
 | 
							for _, m := range messages {
 | 
				
			||||||
 | 
								f(m)
 | 
				
			||||||
 | 
								walkMessages(m.Messages, f)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						initEnumInfos := func(enums []*protogen.Enum) {
 | 
				
			||||||
 | 
							for _, enum := range enums {
 | 
				
			||||||
 | 
								f.allEnums = append(f.allEnums, newEnumInfo(f, enum))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						initMessageInfos := func(messages []*protogen.Message) {
 | 
				
			||||||
 | 
							for _, message := range messages {
 | 
				
			||||||
 | 
								f.allMessages = append(f.allMessages, newMessageInfo(f, message))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						initExtensionInfos := func(extensions []*protogen.Extension) {
 | 
				
			||||||
 | 
							for _, extension := range extensions {
 | 
				
			||||||
 | 
								f.allExtensions = append(f.allExtensions, newExtensionInfo(f, extension))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						initEnumInfos(f.Enums)
 | 
				
			||||||
 | 
						initMessageInfos(f.Messages)
 | 
				
			||||||
 | 
						initExtensionInfos(f.Extensions)
 | 
				
			||||||
 | 
						walkMessages(f.Messages, func(m *protogen.Message) {
 | 
				
			||||||
 | 
							initEnumInfos(m.Enums)
 | 
				
			||||||
 | 
							initMessageInfos(m.Messages)
 | 
				
			||||||
 | 
							initExtensionInfos(m.Extensions)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Derive a reverse mapping of enum and message pointers to their index
 | 
				
			||||||
 | 
						// in allEnums and allMessages.
 | 
				
			||||||
 | 
						if len(f.allEnums) > 0 {
 | 
				
			||||||
 | 
							f.allEnumsByPtr = make(map[*enumInfo]int)
 | 
				
			||||||
 | 
							for i, e := range f.allEnums {
 | 
				
			||||||
 | 
								f.allEnumsByPtr[e] = i
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(f.allMessages) > 0 {
 | 
				
			||||||
 | 
							f.allMessagesByPtr = make(map[*messageInfo]int)
 | 
				
			||||||
 | 
							f.allMessageFieldsByPtr = make(map[*messageInfo]*structFields)
 | 
				
			||||||
 | 
							for i, m := range f.allMessages {
 | 
				
			||||||
 | 
								f.allMessagesByPtr[m] = i
 | 
				
			||||||
 | 
								f.allMessageFieldsByPtr[m] = new(structFields)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return f
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type enumInfo struct {
 | 
				
			||||||
 | 
						*protogen.Enum
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						genJSONMethod    bool
 | 
				
			||||||
 | 
						genRawDescMethod bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newEnumInfo(f *fileInfo, enum *protogen.Enum) *enumInfo {
 | 
				
			||||||
 | 
						e := &enumInfo{Enum: enum}
 | 
				
			||||||
 | 
						e.genJSONMethod = true
 | 
				
			||||||
 | 
						e.genRawDescMethod = true
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type messageInfo struct {
 | 
				
			||||||
 | 
						*protogen.Message
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						genRawDescMethod  bool
 | 
				
			||||||
 | 
						genExtRangeMethod bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						isTracked bool
 | 
				
			||||||
 | 
						hasWeak   bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newMessageInfo(f *fileInfo, message *protogen.Message) *messageInfo {
 | 
				
			||||||
 | 
						m := &messageInfo{Message: message}
 | 
				
			||||||
 | 
						m.genRawDescMethod = true
 | 
				
			||||||
 | 
						m.genExtRangeMethod = true
 | 
				
			||||||
 | 
						m.isTracked = isTrackedMessage(m)
 | 
				
			||||||
 | 
						for _, field := range m.Fields {
 | 
				
			||||||
 | 
							m.hasWeak = m.hasWeak || field.Desc.IsWeak()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return m
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// isTrackedMessage reports whether field tracking is enabled on the message.
 | 
				
			||||||
 | 
					func isTrackedMessage(m *messageInfo) (tracked bool) {
 | 
				
			||||||
 | 
						const trackFieldUse_fieldNumber = 37383685
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Decode the option from unknown fields to avoid a dependency on the
 | 
				
			||||||
 | 
						// annotation proto from protoc-gen-go.
 | 
				
			||||||
 | 
						b := m.Desc.Options().(*descriptorpb.MessageOptions).ProtoReflect().GetUnknown()
 | 
				
			||||||
 | 
						for len(b) > 0 {
 | 
				
			||||||
 | 
							num, typ, n := protowire.ConsumeTag(b)
 | 
				
			||||||
 | 
							b = b[n:]
 | 
				
			||||||
 | 
							if num == trackFieldUse_fieldNumber && typ == protowire.VarintType {
 | 
				
			||||||
 | 
								v, _ := protowire.ConsumeVarint(b)
 | 
				
			||||||
 | 
								tracked = protowire.DecodeBool(v)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							m := protowire.ConsumeFieldValue(num, typ, b)
 | 
				
			||||||
 | 
							b = b[m:]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return tracked
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type extensionInfo struct {
 | 
				
			||||||
 | 
						*protogen.Extension
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newExtensionInfo(f *fileInfo, extension *protogen.Extension) *extensionInfo {
 | 
				
			||||||
 | 
						x := &extensionInfo{Extension: extension}
 | 
				
			||||||
 | 
						return x
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,884 @@
 | 
				
			|||||||
 | 
					// Copyright 2018 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Package internal_gengo is internal to the protobuf module.
 | 
				
			||||||
 | 
					package internal_gengo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"go/ast"
 | 
				
			||||||
 | 
						"go/parser"
 | 
				
			||||||
 | 
						"go/token"
 | 
				
			||||||
 | 
						"math"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"unicode"
 | 
				
			||||||
 | 
						"unicode/utf8"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/compiler/protogen"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/internal/encoding/tag"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/internal/genid"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/internal/version"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/reflect/protoreflect"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/runtime/protoimpl"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/descriptorpb"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/pluginpb"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SupportedFeatures reports the set of supported protobuf language features.
 | 
				
			||||||
 | 
					var SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GenerateVersionMarkers specifies whether to generate version markers.
 | 
				
			||||||
 | 
					var GenerateVersionMarkers = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Standard library dependencies.
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						base64Package  = protogen.GoImportPath("encoding/base64")
 | 
				
			||||||
 | 
						mathPackage    = protogen.GoImportPath("math")
 | 
				
			||||||
 | 
						reflectPackage = protogen.GoImportPath("reflect")
 | 
				
			||||||
 | 
						sortPackage    = protogen.GoImportPath("sort")
 | 
				
			||||||
 | 
						stringsPackage = protogen.GoImportPath("strings")
 | 
				
			||||||
 | 
						syncPackage    = protogen.GoImportPath("sync")
 | 
				
			||||||
 | 
						timePackage    = protogen.GoImportPath("time")
 | 
				
			||||||
 | 
						utf8Package    = protogen.GoImportPath("unicode/utf8")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Protobuf library dependencies.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// These are declared as an interface type so that they can be more easily
 | 
				
			||||||
 | 
					// patched to support unique build environments that impose restrictions
 | 
				
			||||||
 | 
					// on the dependencies of generated source code.
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						protoPackage         goImportPath = protogen.GoImportPath("google.golang.org/protobuf/proto")
 | 
				
			||||||
 | 
						protoifacePackage    goImportPath = protogen.GoImportPath("google.golang.org/protobuf/runtime/protoiface")
 | 
				
			||||||
 | 
						protoimplPackage     goImportPath = protogen.GoImportPath("google.golang.org/protobuf/runtime/protoimpl")
 | 
				
			||||||
 | 
						protojsonPackage     goImportPath = protogen.GoImportPath("google.golang.org/protobuf/encoding/protojson")
 | 
				
			||||||
 | 
						protoreflectPackage  goImportPath = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoreflect")
 | 
				
			||||||
 | 
						protoregistryPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoregistry")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type goImportPath interface {
 | 
				
			||||||
 | 
						String() string
 | 
				
			||||||
 | 
						Ident(string) protogen.GoIdent
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GenerateFile generates the contents of a .pb.go file.
 | 
				
			||||||
 | 
					func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile {
 | 
				
			||||||
 | 
						filename := file.GeneratedFilenamePrefix + ".pb.go"
 | 
				
			||||||
 | 
						g := gen.NewGeneratedFile(filename, file.GoImportPath)
 | 
				
			||||||
 | 
						f := newFileInfo(file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						genStandaloneComments(g, f, int32(genid.FileDescriptorProto_Syntax_field_number))
 | 
				
			||||||
 | 
						genGeneratedHeader(gen, g, f)
 | 
				
			||||||
 | 
						genStandaloneComments(g, f, int32(genid.FileDescriptorProto_Package_field_number))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						packageDoc := genPackageKnownComment(f)
 | 
				
			||||||
 | 
						g.P(packageDoc, "package ", f.GoPackageName)
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Emit a static check that enforces a minimum version of the proto package.
 | 
				
			||||||
 | 
						if GenerateVersionMarkers {
 | 
				
			||||||
 | 
							g.P("const (")
 | 
				
			||||||
 | 
							g.P("// Verify that this generated code is sufficiently up-to-date.")
 | 
				
			||||||
 | 
							g.P("_ = ", protoimplPackage.Ident("EnforceVersion"), "(", protoimpl.GenVersion, " - ", protoimplPackage.Ident("MinVersion"), ")")
 | 
				
			||||||
 | 
							g.P("// Verify that runtime/protoimpl is sufficiently up-to-date.")
 | 
				
			||||||
 | 
							g.P("_ = ", protoimplPackage.Ident("EnforceVersion"), "(", protoimplPackage.Ident("MaxVersion"), " - ", protoimpl.GenVersion, ")")
 | 
				
			||||||
 | 
							g.P(")")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i, imps := 0, f.Desc.Imports(); i < imps.Len(); i++ {
 | 
				
			||||||
 | 
							genImport(gen, g, f, imps.Get(i))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, enum := range f.allEnums {
 | 
				
			||||||
 | 
							genEnum(g, f, enum)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, message := range f.allMessages {
 | 
				
			||||||
 | 
							genMessage(g, f, message)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						genExtensions(g, f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						genReflectFileDescriptor(gen, g, f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return g
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// genStandaloneComments prints all leading comments for a FileDescriptorProto
 | 
				
			||||||
 | 
					// location identified by the field number n.
 | 
				
			||||||
 | 
					func genStandaloneComments(g *protogen.GeneratedFile, f *fileInfo, n int32) {
 | 
				
			||||||
 | 
						loc := f.Desc.SourceLocations().ByPath(protoreflect.SourcePath{n})
 | 
				
			||||||
 | 
						for _, s := range loc.LeadingDetachedComments {
 | 
				
			||||||
 | 
							g.P(protogen.Comments(s))
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if s := loc.LeadingComments; s != "" {
 | 
				
			||||||
 | 
							g.P(protogen.Comments(s))
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genGeneratedHeader(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) {
 | 
				
			||||||
 | 
						g.P("// Code generated by protoc-gen-go. DO NOT EDIT.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if GenerateVersionMarkers {
 | 
				
			||||||
 | 
							g.P("// versions:")
 | 
				
			||||||
 | 
							protocGenGoVersion := version.String()
 | 
				
			||||||
 | 
							protocVersion := "(unknown)"
 | 
				
			||||||
 | 
							if v := gen.Request.GetCompilerVersion(); v != nil {
 | 
				
			||||||
 | 
								protocVersion = fmt.Sprintf("v%v.%v.%v", v.GetMajor(), v.GetMinor(), v.GetPatch())
 | 
				
			||||||
 | 
								if s := v.GetSuffix(); s != "" {
 | 
				
			||||||
 | 
									protocVersion += "-" + s
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P("// \tprotoc-gen-go ", protocGenGoVersion)
 | 
				
			||||||
 | 
							g.P("// \tprotoc        ", protocVersion)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if f.Proto.GetOptions().GetDeprecated() {
 | 
				
			||||||
 | 
							g.P("// ", f.Desc.Path(), " is a deprecated file.")
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							g.P("// source: ", f.Desc.Path())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genImport(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, imp protoreflect.FileImport) {
 | 
				
			||||||
 | 
						impFile, ok := gen.FilesByPath[imp.Path()]
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if impFile.GoImportPath == f.GoImportPath {
 | 
				
			||||||
 | 
							// Don't generate imports or aliases for types in the same Go package.
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Generate imports for all non-weak dependencies, even if they are not
 | 
				
			||||||
 | 
						// referenced, because other code and tools depend on having the
 | 
				
			||||||
 | 
						// full transitive closure of protocol buffer types in the binary.
 | 
				
			||||||
 | 
						if !imp.IsWeak {
 | 
				
			||||||
 | 
							g.Import(impFile.GoImportPath)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !imp.IsPublic {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Generate public imports by generating the imported file, parsing it,
 | 
				
			||||||
 | 
						// and extracting every symbol that should receive a forwarding declaration.
 | 
				
			||||||
 | 
						impGen := GenerateFile(gen, impFile)
 | 
				
			||||||
 | 
						impGen.Skip()
 | 
				
			||||||
 | 
						b, err := impGen.Content()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							gen.Error(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fset := token.NewFileSet()
 | 
				
			||||||
 | 
						astFile, err := parser.ParseFile(fset, "", b, parser.ParseComments)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							gen.Error(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						genForward := func(tok token.Token, name string, expr ast.Expr) {
 | 
				
			||||||
 | 
							// Don't import unexported symbols.
 | 
				
			||||||
 | 
							r, _ := utf8.DecodeRuneInString(name)
 | 
				
			||||||
 | 
							if !unicode.IsUpper(r) {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// Don't import the FileDescriptor.
 | 
				
			||||||
 | 
							if name == impFile.GoDescriptorIdent.GoName {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// Don't import decls referencing a symbol defined in another package.
 | 
				
			||||||
 | 
							// i.e., don't import decls which are themselves public imports:
 | 
				
			||||||
 | 
							//
 | 
				
			||||||
 | 
							//	type T = somepackage.T
 | 
				
			||||||
 | 
							if _, ok := expr.(*ast.SelectorExpr); ok {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P(tok, " ", name, " = ", impFile.GoImportPath.Ident(name))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("// Symbols defined in public import of ", imp.Path(), ".")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
						for _, decl := range astFile.Decls {
 | 
				
			||||||
 | 
							switch decl := decl.(type) {
 | 
				
			||||||
 | 
							case *ast.GenDecl:
 | 
				
			||||||
 | 
								for _, spec := range decl.Specs {
 | 
				
			||||||
 | 
									switch spec := spec.(type) {
 | 
				
			||||||
 | 
									case *ast.TypeSpec:
 | 
				
			||||||
 | 
										genForward(decl.Tok, spec.Name.Name, spec.Type)
 | 
				
			||||||
 | 
									case *ast.ValueSpec:
 | 
				
			||||||
 | 
										for i, name := range spec.Names {
 | 
				
			||||||
 | 
											var expr ast.Expr
 | 
				
			||||||
 | 
											if i < len(spec.Values) {
 | 
				
			||||||
 | 
												expr = spec.Values[i]
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											genForward(decl.Tok, name.Name, expr)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									case *ast.ImportSpec:
 | 
				
			||||||
 | 
									default:
 | 
				
			||||||
 | 
										panic(fmt.Sprintf("can't generate forward for spec type %T", spec))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genEnum(g *protogen.GeneratedFile, f *fileInfo, e *enumInfo) {
 | 
				
			||||||
 | 
						// Enum type declaration.
 | 
				
			||||||
 | 
						g.Annotate(e.GoIdent.GoName, e.Location)
 | 
				
			||||||
 | 
						leadingComments := appendDeprecationSuffix(e.Comments.Leading,
 | 
				
			||||||
 | 
							e.Desc.Options().(*descriptorpb.EnumOptions).GetDeprecated())
 | 
				
			||||||
 | 
						g.P(leadingComments,
 | 
				
			||||||
 | 
							"type ", e.GoIdent, " int32")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Enum value constants.
 | 
				
			||||||
 | 
						g.P("const (")
 | 
				
			||||||
 | 
						for _, value := range e.Values {
 | 
				
			||||||
 | 
							g.Annotate(value.GoIdent.GoName, value.Location)
 | 
				
			||||||
 | 
							leadingComments := appendDeprecationSuffix(value.Comments.Leading,
 | 
				
			||||||
 | 
								value.Desc.Options().(*descriptorpb.EnumValueOptions).GetDeprecated())
 | 
				
			||||||
 | 
							g.P(leadingComments,
 | 
				
			||||||
 | 
								value.GoIdent, " ", e.GoIdent, " = ", value.Desc.Number(),
 | 
				
			||||||
 | 
								trailingComment(value.Comments.Trailing))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P(")")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Enum value maps.
 | 
				
			||||||
 | 
						g.P("// Enum value maps for ", e.GoIdent, ".")
 | 
				
			||||||
 | 
						g.P("var (")
 | 
				
			||||||
 | 
						g.P(e.GoIdent.GoName+"_name", " = map[int32]string{")
 | 
				
			||||||
 | 
						for _, value := range e.Values {
 | 
				
			||||||
 | 
							duplicate := ""
 | 
				
			||||||
 | 
							if value.Desc != e.Desc.Values().ByNumber(value.Desc.Number()) {
 | 
				
			||||||
 | 
								duplicate = "// Duplicate value: "
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P(duplicate, value.Desc.Number(), ": ", strconv.Quote(string(value.Desc.Name())), ",")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P(e.GoIdent.GoName+"_value", " = map[string]int32{")
 | 
				
			||||||
 | 
						for _, value := range e.Values {
 | 
				
			||||||
 | 
							g.P(strconv.Quote(string(value.Desc.Name())), ": ", value.Desc.Number(), ",")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P(")")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Enum method.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// NOTE: A pointer value is needed to represent presence in proto2.
 | 
				
			||||||
 | 
						// Since a proto2 message can reference a proto3 enum, it is useful to
 | 
				
			||||||
 | 
						// always generate this method (even on proto3 enums) to support that case.
 | 
				
			||||||
 | 
						g.P("func (x ", e.GoIdent, ") Enum() *", e.GoIdent, " {")
 | 
				
			||||||
 | 
						g.P("p := new(", e.GoIdent, ")")
 | 
				
			||||||
 | 
						g.P("*p = x")
 | 
				
			||||||
 | 
						g.P("return p")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// String method.
 | 
				
			||||||
 | 
						g.P("func (x ", e.GoIdent, ") String() string {")
 | 
				
			||||||
 | 
						g.P("return ", protoimplPackage.Ident("X"), ".EnumStringOf(x.Descriptor(), ", protoreflectPackage.Ident("EnumNumber"), "(x))")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						genEnumReflectMethods(g, f, e)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// UnmarshalJSON method.
 | 
				
			||||||
 | 
						if e.genJSONMethod && e.Desc.Syntax() == protoreflect.Proto2 {
 | 
				
			||||||
 | 
							g.P("// Deprecated: Do not use.")
 | 
				
			||||||
 | 
							g.P("func (x *", e.GoIdent, ") UnmarshalJSON(b []byte) error {")
 | 
				
			||||||
 | 
							g.P("num, err := ", protoimplPackage.Ident("X"), ".UnmarshalJSONEnum(x.Descriptor(), b)")
 | 
				
			||||||
 | 
							g.P("if err != nil {")
 | 
				
			||||||
 | 
							g.P("return err")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P("*x = ", e.GoIdent, "(num)")
 | 
				
			||||||
 | 
							g.P("return nil")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// EnumDescriptor method.
 | 
				
			||||||
 | 
						if e.genRawDescMethod {
 | 
				
			||||||
 | 
							var indexes []string
 | 
				
			||||||
 | 
							for i := 1; i < len(e.Location.Path); i += 2 {
 | 
				
			||||||
 | 
								indexes = append(indexes, strconv.Itoa(int(e.Location.Path[i])))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P("// Deprecated: Use ", e.GoIdent, ".Descriptor instead.")
 | 
				
			||||||
 | 
							g.P("func (", e.GoIdent, ") EnumDescriptor() ([]byte, []int) {")
 | 
				
			||||||
 | 
							g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
							f.needRawDesc = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genMessage(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
 | 
				
			||||||
 | 
						if m.Desc.IsMapEntry() {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Message type declaration.
 | 
				
			||||||
 | 
						g.Annotate(m.GoIdent.GoName, m.Location)
 | 
				
			||||||
 | 
						leadingComments := appendDeprecationSuffix(m.Comments.Leading,
 | 
				
			||||||
 | 
							m.Desc.Options().(*descriptorpb.MessageOptions).GetDeprecated())
 | 
				
			||||||
 | 
						g.P(leadingComments,
 | 
				
			||||||
 | 
							"type ", m.GoIdent, " struct {")
 | 
				
			||||||
 | 
						genMessageFields(g, f, m)
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						genMessageKnownFunctions(g, f, m)
 | 
				
			||||||
 | 
						genMessageDefaultDecls(g, f, m)
 | 
				
			||||||
 | 
						genMessageMethods(g, f, m)
 | 
				
			||||||
 | 
						genMessageOneofWrapperTypes(g, f, m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genMessageFields(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
 | 
				
			||||||
 | 
						sf := f.allMessageFieldsByPtr[m]
 | 
				
			||||||
 | 
						genMessageInternalFields(g, f, m, sf)
 | 
				
			||||||
 | 
						for _, field := range m.Fields {
 | 
				
			||||||
 | 
							genMessageField(g, f, m, field, sf)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genMessageInternalFields(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, sf *structFields) {
 | 
				
			||||||
 | 
						g.P(genid.State_goname, " ", protoimplPackage.Ident("MessageState"))
 | 
				
			||||||
 | 
						sf.append(genid.State_goname)
 | 
				
			||||||
 | 
						g.P(genid.SizeCache_goname, " ", protoimplPackage.Ident("SizeCache"))
 | 
				
			||||||
 | 
						sf.append(genid.SizeCache_goname)
 | 
				
			||||||
 | 
						if m.hasWeak {
 | 
				
			||||||
 | 
							g.P(genid.WeakFields_goname, " ", protoimplPackage.Ident("WeakFields"))
 | 
				
			||||||
 | 
							sf.append(genid.WeakFields_goname)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P(genid.UnknownFields_goname, " ", protoimplPackage.Ident("UnknownFields"))
 | 
				
			||||||
 | 
						sf.append(genid.UnknownFields_goname)
 | 
				
			||||||
 | 
						if m.Desc.ExtensionRanges().Len() > 0 {
 | 
				
			||||||
 | 
							g.P(genid.ExtensionFields_goname, " ", protoimplPackage.Ident("ExtensionFields"))
 | 
				
			||||||
 | 
							sf.append(genid.ExtensionFields_goname)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if sf.count > 0 {
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genMessageField(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, field *protogen.Field, sf *structFields) {
 | 
				
			||||||
 | 
						if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
 | 
				
			||||||
 | 
							// It would be a bit simpler to iterate over the oneofs below,
 | 
				
			||||||
 | 
							// but generating the field here keeps the contents of the Go
 | 
				
			||||||
 | 
							// struct in the same order as the contents of the source
 | 
				
			||||||
 | 
							// .proto file.
 | 
				
			||||||
 | 
							if oneof.Fields[0] != field {
 | 
				
			||||||
 | 
								return // only generate for first appearance
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							tags := structTags{
 | 
				
			||||||
 | 
								{"protobuf_oneof", string(oneof.Desc.Name())},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if m.isTracked {
 | 
				
			||||||
 | 
								tags = append(tags, gotrackTags...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							g.Annotate(m.GoIdent.GoName+"."+oneof.GoName, oneof.Location)
 | 
				
			||||||
 | 
							leadingComments := oneof.Comments.Leading
 | 
				
			||||||
 | 
							if leadingComments != "" {
 | 
				
			||||||
 | 
								leadingComments += "\n"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ss := []string{fmt.Sprintf(" Types that are assignable to %s:\n", oneof.GoName)}
 | 
				
			||||||
 | 
							for _, field := range oneof.Fields {
 | 
				
			||||||
 | 
								ss = append(ss, "\t*"+field.GoIdent.GoName+"\n")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							leadingComments += protogen.Comments(strings.Join(ss, ""))
 | 
				
			||||||
 | 
							g.P(leadingComments,
 | 
				
			||||||
 | 
								oneof.GoName, " ", oneofInterfaceName(oneof), tags)
 | 
				
			||||||
 | 
							sf.append(oneof.GoName)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						goType, pointer := fieldGoType(g, f, field)
 | 
				
			||||||
 | 
						if pointer {
 | 
				
			||||||
 | 
							goType = "*" + goType
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tags := structTags{
 | 
				
			||||||
 | 
							{"protobuf", fieldProtobufTagValue(field)},
 | 
				
			||||||
 | 
							{"json", fieldJSONTagValue(field)},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if field.Desc.IsMap() {
 | 
				
			||||||
 | 
							key := field.Message.Fields[0]
 | 
				
			||||||
 | 
							val := field.Message.Fields[1]
 | 
				
			||||||
 | 
							tags = append(tags, structTags{
 | 
				
			||||||
 | 
								{"protobuf_key", fieldProtobufTagValue(key)},
 | 
				
			||||||
 | 
								{"protobuf_val", fieldProtobufTagValue(val)},
 | 
				
			||||||
 | 
							}...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if m.isTracked {
 | 
				
			||||||
 | 
							tags = append(tags, gotrackTags...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						name := field.GoName
 | 
				
			||||||
 | 
						if field.Desc.IsWeak() {
 | 
				
			||||||
 | 
							name = genid.WeakFieldPrefix_goname + name
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.Annotate(m.GoIdent.GoName+"."+name, field.Location)
 | 
				
			||||||
 | 
						leadingComments := appendDeprecationSuffix(field.Comments.Leading,
 | 
				
			||||||
 | 
							field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
 | 
				
			||||||
 | 
						g.P(leadingComments,
 | 
				
			||||||
 | 
							name, " ", goType, tags,
 | 
				
			||||||
 | 
							trailingComment(field.Comments.Trailing))
 | 
				
			||||||
 | 
						sf.append(field.GoName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// genMessageDefaultDecls generates consts and vars holding the default
 | 
				
			||||||
 | 
					// values of fields.
 | 
				
			||||||
 | 
					func genMessageDefaultDecls(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
 | 
				
			||||||
 | 
						var consts, vars []string
 | 
				
			||||||
 | 
						for _, field := range m.Fields {
 | 
				
			||||||
 | 
							if !field.Desc.HasDefault() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							name := "Default_" + m.GoIdent.GoName + "_" + field.GoName
 | 
				
			||||||
 | 
							goType, _ := fieldGoType(g, f, field)
 | 
				
			||||||
 | 
							defVal := field.Desc.Default()
 | 
				
			||||||
 | 
							switch field.Desc.Kind() {
 | 
				
			||||||
 | 
							case protoreflect.StringKind:
 | 
				
			||||||
 | 
								consts = append(consts, fmt.Sprintf("%s = %s(%q)", name, goType, defVal.String()))
 | 
				
			||||||
 | 
							case protoreflect.BytesKind:
 | 
				
			||||||
 | 
								vars = append(vars, fmt.Sprintf("%s = %s(%q)", name, goType, defVal.Bytes()))
 | 
				
			||||||
 | 
							case protoreflect.EnumKind:
 | 
				
			||||||
 | 
								idx := field.Desc.DefaultEnumValue().Index()
 | 
				
			||||||
 | 
								val := field.Enum.Values[idx]
 | 
				
			||||||
 | 
								if val.GoIdent.GoImportPath == f.GoImportPath {
 | 
				
			||||||
 | 
									consts = append(consts, fmt.Sprintf("%s = %s", name, g.QualifiedGoIdent(val.GoIdent)))
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									// If the enum value is declared in a different Go package,
 | 
				
			||||||
 | 
									// reference it by number since the name may not be correct.
 | 
				
			||||||
 | 
									// See https://github.com/golang/protobuf/issues/513.
 | 
				
			||||||
 | 
									consts = append(consts, fmt.Sprintf("%s = %s(%d) // %s",
 | 
				
			||||||
 | 
										name, g.QualifiedGoIdent(field.Enum.GoIdent), val.Desc.Number(), g.QualifiedGoIdent(val.GoIdent)))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							case protoreflect.FloatKind, protoreflect.DoubleKind:
 | 
				
			||||||
 | 
								if f := defVal.Float(); math.IsNaN(f) || math.IsInf(f, 0) {
 | 
				
			||||||
 | 
									var fn, arg string
 | 
				
			||||||
 | 
									switch f := defVal.Float(); {
 | 
				
			||||||
 | 
									case math.IsInf(f, -1):
 | 
				
			||||||
 | 
										fn, arg = g.QualifiedGoIdent(mathPackage.Ident("Inf")), "-1"
 | 
				
			||||||
 | 
									case math.IsInf(f, +1):
 | 
				
			||||||
 | 
										fn, arg = g.QualifiedGoIdent(mathPackage.Ident("Inf")), "+1"
 | 
				
			||||||
 | 
									case math.IsNaN(f):
 | 
				
			||||||
 | 
										fn, arg = g.QualifiedGoIdent(mathPackage.Ident("NaN")), ""
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									vars = append(vars, fmt.Sprintf("%s = %s(%s(%s))", name, goType, fn, arg))
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									consts = append(consts, fmt.Sprintf("%s = %s(%v)", name, goType, f))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								consts = append(consts, fmt.Sprintf("%s = %s(%v)", name, goType, defVal.Interface()))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(consts) > 0 {
 | 
				
			||||||
 | 
							g.P("// Default values for ", m.GoIdent, " fields.")
 | 
				
			||||||
 | 
							g.P("const (")
 | 
				
			||||||
 | 
							for _, s := range consts {
 | 
				
			||||||
 | 
								g.P(s)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P(")")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(vars) > 0 {
 | 
				
			||||||
 | 
							g.P("// Default values for ", m.GoIdent, " fields.")
 | 
				
			||||||
 | 
							g.P("var (")
 | 
				
			||||||
 | 
							for _, s := range vars {
 | 
				
			||||||
 | 
								g.P(s)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P(")")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genMessageMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
 | 
				
			||||||
 | 
						genMessageBaseMethods(g, f, m)
 | 
				
			||||||
 | 
						genMessageGetterMethods(g, f, m)
 | 
				
			||||||
 | 
						genMessageSetterMethods(g, f, m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genMessageBaseMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
 | 
				
			||||||
 | 
						// Reset method.
 | 
				
			||||||
 | 
						g.P("func (x *", m.GoIdent, ") Reset() {")
 | 
				
			||||||
 | 
						g.P("*x = ", m.GoIdent, "{}")
 | 
				
			||||||
 | 
						g.P("if ", protoimplPackage.Ident("UnsafeEnabled"), " {")
 | 
				
			||||||
 | 
						g.P("mi := &", messageTypesVarName(f), "[", f.allMessagesByPtr[m], "]")
 | 
				
			||||||
 | 
						g.P("ms := ", protoimplPackage.Ident("X"), ".MessageStateOf(", protoimplPackage.Ident("Pointer"), "(x))")
 | 
				
			||||||
 | 
						g.P("ms.StoreMessageInfo(mi)")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// String method.
 | 
				
			||||||
 | 
						g.P("func (x *", m.GoIdent, ") String() string {")
 | 
				
			||||||
 | 
						g.P("return ", protoimplPackage.Ident("X"), ".MessageStringOf(x)")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ProtoMessage method.
 | 
				
			||||||
 | 
						g.P("func (*", m.GoIdent, ") ProtoMessage() {}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ProtoReflect method.
 | 
				
			||||||
 | 
						genMessageReflectMethods(g, f, m)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Descriptor method.
 | 
				
			||||||
 | 
						if m.genRawDescMethod {
 | 
				
			||||||
 | 
							var indexes []string
 | 
				
			||||||
 | 
							for i := 1; i < len(m.Location.Path); i += 2 {
 | 
				
			||||||
 | 
								indexes = append(indexes, strconv.Itoa(int(m.Location.Path[i])))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P("// Deprecated: Use ", m.GoIdent, ".ProtoReflect.Descriptor instead.")
 | 
				
			||||||
 | 
							g.P("func (*", m.GoIdent, ") Descriptor() ([]byte, []int) {")
 | 
				
			||||||
 | 
							g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
							f.needRawDesc = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genMessageGetterMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
 | 
				
			||||||
 | 
						for _, field := range m.Fields {
 | 
				
			||||||
 | 
							genNoInterfacePragma(g, m.isTracked)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Getter for parent oneof.
 | 
				
			||||||
 | 
							if oneof := field.Oneof; oneof != nil && oneof.Fields[0] == field && !oneof.Desc.IsSynthetic() {
 | 
				
			||||||
 | 
								g.Annotate(m.GoIdent.GoName+".Get"+oneof.GoName, oneof.Location)
 | 
				
			||||||
 | 
								g.P("func (m *", m.GoIdent.GoName, ") Get", oneof.GoName, "() ", oneofInterfaceName(oneof), " {")
 | 
				
			||||||
 | 
								g.P("if m != nil {")
 | 
				
			||||||
 | 
								g.P("return m.", oneof.GoName)
 | 
				
			||||||
 | 
								g.P("}")
 | 
				
			||||||
 | 
								g.P("return nil")
 | 
				
			||||||
 | 
								g.P("}")
 | 
				
			||||||
 | 
								g.P()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Getter for message field.
 | 
				
			||||||
 | 
							goType, pointer := fieldGoType(g, f, field)
 | 
				
			||||||
 | 
							defaultValue := fieldDefaultValue(g, f, m, field)
 | 
				
			||||||
 | 
							g.Annotate(m.GoIdent.GoName+".Get"+field.GoName, field.Location)
 | 
				
			||||||
 | 
							leadingComments := appendDeprecationSuffix("",
 | 
				
			||||||
 | 
								field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
 | 
				
			||||||
 | 
							switch {
 | 
				
			||||||
 | 
							case field.Desc.IsWeak():
 | 
				
			||||||
 | 
								g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", protoPackage.Ident("Message"), "{")
 | 
				
			||||||
 | 
								g.P("var w ", protoimplPackage.Ident("WeakFields"))
 | 
				
			||||||
 | 
								g.P("if x != nil {")
 | 
				
			||||||
 | 
								g.P("w = x.", genid.WeakFields_goname)
 | 
				
			||||||
 | 
								if m.isTracked {
 | 
				
			||||||
 | 
									g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								g.P("}")
 | 
				
			||||||
 | 
								g.P("return ", protoimplPackage.Ident("X"), ".GetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ")")
 | 
				
			||||||
 | 
								g.P("}")
 | 
				
			||||||
 | 
							case field.Oneof != nil && !field.Oneof.Desc.IsSynthetic():
 | 
				
			||||||
 | 
								g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", goType, " {")
 | 
				
			||||||
 | 
								g.P("if x, ok := x.Get", field.Oneof.GoName, "().(*", field.GoIdent, "); ok {")
 | 
				
			||||||
 | 
								g.P("return x.", field.GoName)
 | 
				
			||||||
 | 
								g.P("}")
 | 
				
			||||||
 | 
								g.P("return ", defaultValue)
 | 
				
			||||||
 | 
								g.P("}")
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", goType, " {")
 | 
				
			||||||
 | 
								if !field.Desc.HasPresence() || defaultValue == "nil" {
 | 
				
			||||||
 | 
									g.P("if x != nil {")
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									g.P("if x != nil && x.", field.GoName, " != nil {")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								star := ""
 | 
				
			||||||
 | 
								if pointer {
 | 
				
			||||||
 | 
									star = "*"
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								g.P("return ", star, " x.", field.GoName)
 | 
				
			||||||
 | 
								g.P("}")
 | 
				
			||||||
 | 
								g.P("return ", defaultValue)
 | 
				
			||||||
 | 
								g.P("}")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genMessageSetterMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
 | 
				
			||||||
 | 
						for _, field := range m.Fields {
 | 
				
			||||||
 | 
							if !field.Desc.IsWeak() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							genNoInterfacePragma(g, m.isTracked)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							g.Annotate(m.GoIdent.GoName+".Set"+field.GoName, field.Location)
 | 
				
			||||||
 | 
							leadingComments := appendDeprecationSuffix("",
 | 
				
			||||||
 | 
								field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
 | 
				
			||||||
 | 
							g.P(leadingComments, "func (x *", m.GoIdent, ") Set", field.GoName, "(v ", protoPackage.Ident("Message"), ") {")
 | 
				
			||||||
 | 
							g.P("var w *", protoimplPackage.Ident("WeakFields"))
 | 
				
			||||||
 | 
							g.P("if x != nil {")
 | 
				
			||||||
 | 
							g.P("w = &x.", genid.WeakFields_goname)
 | 
				
			||||||
 | 
							if m.isTracked {
 | 
				
			||||||
 | 
								g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P(protoimplPackage.Ident("X"), ".SetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ", v)")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// fieldGoType returns the Go type used for a field.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If it returns pointer=true, the struct field is a pointer to the type.
 | 
				
			||||||
 | 
					func fieldGoType(g *protogen.GeneratedFile, f *fileInfo, field *protogen.Field) (goType string, pointer bool) {
 | 
				
			||||||
 | 
						if field.Desc.IsWeak() {
 | 
				
			||||||
 | 
							return "struct{}", false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pointer = field.Desc.HasPresence()
 | 
				
			||||||
 | 
						switch field.Desc.Kind() {
 | 
				
			||||||
 | 
						case protoreflect.BoolKind:
 | 
				
			||||||
 | 
							goType = "bool"
 | 
				
			||||||
 | 
						case protoreflect.EnumKind:
 | 
				
			||||||
 | 
							goType = g.QualifiedGoIdent(field.Enum.GoIdent)
 | 
				
			||||||
 | 
						case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
 | 
				
			||||||
 | 
							goType = "int32"
 | 
				
			||||||
 | 
						case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
 | 
				
			||||||
 | 
							goType = "uint32"
 | 
				
			||||||
 | 
						case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
 | 
				
			||||||
 | 
							goType = "int64"
 | 
				
			||||||
 | 
						case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
 | 
				
			||||||
 | 
							goType = "uint64"
 | 
				
			||||||
 | 
						case protoreflect.FloatKind:
 | 
				
			||||||
 | 
							goType = "float32"
 | 
				
			||||||
 | 
						case protoreflect.DoubleKind:
 | 
				
			||||||
 | 
							goType = "float64"
 | 
				
			||||||
 | 
						case protoreflect.StringKind:
 | 
				
			||||||
 | 
							goType = "string"
 | 
				
			||||||
 | 
						case protoreflect.BytesKind:
 | 
				
			||||||
 | 
							goType = "[]byte"
 | 
				
			||||||
 | 
							pointer = false // rely on nullability of slices for presence
 | 
				
			||||||
 | 
						case protoreflect.MessageKind, protoreflect.GroupKind:
 | 
				
			||||||
 | 
							goType = "*" + g.QualifiedGoIdent(field.Message.GoIdent)
 | 
				
			||||||
 | 
							pointer = false // pointer captured as part of the type
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						switch {
 | 
				
			||||||
 | 
						case field.Desc.IsList():
 | 
				
			||||||
 | 
							return "[]" + goType, false
 | 
				
			||||||
 | 
						case field.Desc.IsMap():
 | 
				
			||||||
 | 
							keyType, _ := fieldGoType(g, f, field.Message.Fields[0])
 | 
				
			||||||
 | 
							valType, _ := fieldGoType(g, f, field.Message.Fields[1])
 | 
				
			||||||
 | 
							return fmt.Sprintf("map[%v]%v", keyType, valType), false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return goType, pointer
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func fieldProtobufTagValue(field *protogen.Field) string {
 | 
				
			||||||
 | 
						var enumName string
 | 
				
			||||||
 | 
						if field.Desc.Kind() == protoreflect.EnumKind {
 | 
				
			||||||
 | 
							enumName = protoimpl.X.LegacyEnumName(field.Enum.Desc)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return tag.Marshal(field.Desc, enumName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func fieldDefaultValue(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, field *protogen.Field) string {
 | 
				
			||||||
 | 
						if field.Desc.IsList() {
 | 
				
			||||||
 | 
							return "nil"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if field.Desc.HasDefault() {
 | 
				
			||||||
 | 
							defVarName := "Default_" + m.GoIdent.GoName + "_" + field.GoName
 | 
				
			||||||
 | 
							if field.Desc.Kind() == protoreflect.BytesKind {
 | 
				
			||||||
 | 
								return "append([]byte(nil), " + defVarName + "...)"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return defVarName
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						switch field.Desc.Kind() {
 | 
				
			||||||
 | 
						case protoreflect.BoolKind:
 | 
				
			||||||
 | 
							return "false"
 | 
				
			||||||
 | 
						case protoreflect.StringKind:
 | 
				
			||||||
 | 
							return `""`
 | 
				
			||||||
 | 
						case protoreflect.MessageKind, protoreflect.GroupKind, protoreflect.BytesKind:
 | 
				
			||||||
 | 
							return "nil"
 | 
				
			||||||
 | 
						case protoreflect.EnumKind:
 | 
				
			||||||
 | 
							val := field.Enum.Values[0]
 | 
				
			||||||
 | 
							if val.GoIdent.GoImportPath == f.GoImportPath {
 | 
				
			||||||
 | 
								return g.QualifiedGoIdent(val.GoIdent)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								// If the enum value is declared in a different Go package,
 | 
				
			||||||
 | 
								// reference it by number since the name may not be correct.
 | 
				
			||||||
 | 
								// See https://github.com/golang/protobuf/issues/513.
 | 
				
			||||||
 | 
								return g.QualifiedGoIdent(field.Enum.GoIdent) + "(" + strconv.FormatInt(int64(val.Desc.Number()), 10) + ")"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return "0"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func fieldJSONTagValue(field *protogen.Field) string {
 | 
				
			||||||
 | 
						return string(field.Desc.Name()) + ",omitempty"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genExtensions(g *protogen.GeneratedFile, f *fileInfo) {
 | 
				
			||||||
 | 
						if len(f.allExtensions) == 0 {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("var ", extensionTypesVarName(f), " = []", protoimplPackage.Ident("ExtensionInfo"), "{")
 | 
				
			||||||
 | 
						for _, x := range f.allExtensions {
 | 
				
			||||||
 | 
							g.P("{")
 | 
				
			||||||
 | 
							g.P("ExtendedType: (*", x.Extendee.GoIdent, ")(nil),")
 | 
				
			||||||
 | 
							goType, pointer := fieldGoType(g, f, x.Extension)
 | 
				
			||||||
 | 
							if pointer {
 | 
				
			||||||
 | 
								goType = "*" + goType
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P("ExtensionType: (", goType, ")(nil),")
 | 
				
			||||||
 | 
							g.P("Field: ", x.Desc.Number(), ",")
 | 
				
			||||||
 | 
							g.P("Name: ", strconv.Quote(string(x.Desc.FullName())), ",")
 | 
				
			||||||
 | 
							g.P("Tag: ", strconv.Quote(fieldProtobufTagValue(x.Extension)), ",")
 | 
				
			||||||
 | 
							g.P("Filename: ", strconv.Quote(f.Desc.Path()), ",")
 | 
				
			||||||
 | 
							g.P("},")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Group extensions by the target message.
 | 
				
			||||||
 | 
						var orderedTargets []protogen.GoIdent
 | 
				
			||||||
 | 
						allExtensionsByTarget := make(map[protogen.GoIdent][]*extensionInfo)
 | 
				
			||||||
 | 
						allExtensionsByPtr := make(map[*extensionInfo]int)
 | 
				
			||||||
 | 
						for i, x := range f.allExtensions {
 | 
				
			||||||
 | 
							target := x.Extendee.GoIdent
 | 
				
			||||||
 | 
							if len(allExtensionsByTarget[target]) == 0 {
 | 
				
			||||||
 | 
								orderedTargets = append(orderedTargets, target)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							allExtensionsByTarget[target] = append(allExtensionsByTarget[target], x)
 | 
				
			||||||
 | 
							allExtensionsByPtr[x] = i
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, target := range orderedTargets {
 | 
				
			||||||
 | 
							g.P("// Extension fields to ", target, ".")
 | 
				
			||||||
 | 
							g.P("var (")
 | 
				
			||||||
 | 
							for _, x := range allExtensionsByTarget[target] {
 | 
				
			||||||
 | 
								xd := x.Desc
 | 
				
			||||||
 | 
								typeName := xd.Kind().String()
 | 
				
			||||||
 | 
								switch xd.Kind() {
 | 
				
			||||||
 | 
								case protoreflect.EnumKind:
 | 
				
			||||||
 | 
									typeName = string(xd.Enum().FullName())
 | 
				
			||||||
 | 
								case protoreflect.MessageKind, protoreflect.GroupKind:
 | 
				
			||||||
 | 
									typeName = string(xd.Message().FullName())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								fieldName := string(xd.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								leadingComments := x.Comments.Leading
 | 
				
			||||||
 | 
								if leadingComments != "" {
 | 
				
			||||||
 | 
									leadingComments += "\n"
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								leadingComments += protogen.Comments(fmt.Sprintf(" %v %v %v = %v;\n",
 | 
				
			||||||
 | 
									xd.Cardinality(), typeName, fieldName, xd.Number()))
 | 
				
			||||||
 | 
								leadingComments = appendDeprecationSuffix(leadingComments,
 | 
				
			||||||
 | 
									x.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
 | 
				
			||||||
 | 
								g.P(leadingComments,
 | 
				
			||||||
 | 
									"E_", x.GoIdent, " = &", extensionTypesVarName(f), "[", allExtensionsByPtr[x], "]",
 | 
				
			||||||
 | 
									trailingComment(x.Comments.Trailing))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P(")")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// genMessageOneofWrapperTypes generates the oneof wrapper types and
 | 
				
			||||||
 | 
					// associates the types with the parent message type.
 | 
				
			||||||
 | 
					func genMessageOneofWrapperTypes(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
 | 
				
			||||||
 | 
						for _, oneof := range m.Oneofs {
 | 
				
			||||||
 | 
							if oneof.Desc.IsSynthetic() {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ifName := oneofInterfaceName(oneof)
 | 
				
			||||||
 | 
							g.P("type ", ifName, " interface {")
 | 
				
			||||||
 | 
							g.P(ifName, "()")
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
							for _, field := range oneof.Fields {
 | 
				
			||||||
 | 
								g.Annotate(field.GoIdent.GoName, field.Location)
 | 
				
			||||||
 | 
								g.Annotate(field.GoIdent.GoName+"."+field.GoName, field.Location)
 | 
				
			||||||
 | 
								g.P("type ", field.GoIdent, " struct {")
 | 
				
			||||||
 | 
								goType, _ := fieldGoType(g, f, field)
 | 
				
			||||||
 | 
								tags := structTags{
 | 
				
			||||||
 | 
									{"protobuf", fieldProtobufTagValue(field)},
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if m.isTracked {
 | 
				
			||||||
 | 
									tags = append(tags, gotrackTags...)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								leadingComments := appendDeprecationSuffix(field.Comments.Leading,
 | 
				
			||||||
 | 
									field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
 | 
				
			||||||
 | 
								g.P(leadingComments,
 | 
				
			||||||
 | 
									field.GoName, " ", goType, tags,
 | 
				
			||||||
 | 
									trailingComment(field.Comments.Trailing))
 | 
				
			||||||
 | 
								g.P("}")
 | 
				
			||||||
 | 
								g.P()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for _, field := range oneof.Fields {
 | 
				
			||||||
 | 
								g.P("func (*", field.GoIdent, ") ", ifName, "() {}")
 | 
				
			||||||
 | 
								g.P()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// oneofInterfaceName returns the name of the interface type implemented by
 | 
				
			||||||
 | 
					// the oneof field value types.
 | 
				
			||||||
 | 
					func oneofInterfaceName(oneof *protogen.Oneof) string {
 | 
				
			||||||
 | 
						return "is" + oneof.GoIdent.GoName
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// genNoInterfacePragma generates a standalone "nointerface" pragma to
 | 
				
			||||||
 | 
					// decorate methods with field-tracking support.
 | 
				
			||||||
 | 
					func genNoInterfacePragma(g *protogen.GeneratedFile, tracked bool) {
 | 
				
			||||||
 | 
						if tracked {
 | 
				
			||||||
 | 
							g.P("//go:nointerface")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var gotrackTags = structTags{{"go", "track"}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// structTags is a data structure for build idiomatic Go struct tags.
 | 
				
			||||||
 | 
					// Each [2]string is a key-value pair, where value is the unescaped string.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Example: structTags{{"key", "value"}}.String() -> `key:"value"`
 | 
				
			||||||
 | 
					type structTags [][2]string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (tags structTags) String() string {
 | 
				
			||||||
 | 
						if len(tags) == 0 {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var ss []string
 | 
				
			||||||
 | 
						for _, tag := range tags {
 | 
				
			||||||
 | 
							// NOTE: When quoting the value, we need to make sure the backtick
 | 
				
			||||||
 | 
							// character does not appear. Convert all cases to the escaped hex form.
 | 
				
			||||||
 | 
							key := tag[0]
 | 
				
			||||||
 | 
							val := strings.Replace(strconv.Quote(tag[1]), "`", `\x60`, -1)
 | 
				
			||||||
 | 
							ss = append(ss, fmt.Sprintf("%s:%s", key, val))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "`" + strings.Join(ss, " ") + "`"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// appendDeprecationSuffix optionally appends a deprecation notice as a suffix.
 | 
				
			||||||
 | 
					func appendDeprecationSuffix(prefix protogen.Comments, deprecated bool) protogen.Comments {
 | 
				
			||||||
 | 
						if !deprecated {
 | 
				
			||||||
 | 
							return prefix
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if prefix != "" {
 | 
				
			||||||
 | 
							prefix += "\n"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return prefix + " Deprecated: Do not use.\n"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// trailingComment is like protogen.Comments, but lacks a trailing newline.
 | 
				
			||||||
 | 
					type trailingComment protogen.Comments
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c trailingComment) String() string {
 | 
				
			||||||
 | 
						s := strings.TrimSuffix(protogen.Comments(c).String(), "\n")
 | 
				
			||||||
 | 
						if strings.Contains(s, "\n") {
 | 
				
			||||||
 | 
							// We don't support multi-lined trailing comments as it is unclear
 | 
				
			||||||
 | 
							// how to best render them in the generated code.
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return s
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
								
									
										
											
										
									
									
										
											351
										
									
									vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/reflect.go
									
										generated
									
									
										vendored
									
								
								
							
							
										
											351
										
									
									vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/reflect.go
									
										generated
									
									
										vendored
									
								@ -0,0 +1,351 @@
 | 
				
			|||||||
 | 
					// Copyright 2018 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package internal_gengo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"math"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"unicode/utf8"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/compiler/protogen"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/proto"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/reflect/protoreflect"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/descriptorpb"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genReflectFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) {
 | 
				
			||||||
 | 
						g.P("var ", f.GoDescriptorIdent, " ", protoreflectPackage.Ident("FileDescriptor"))
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						genFileDescriptor(gen, g, f)
 | 
				
			||||||
 | 
						if len(f.allEnums) > 0 {
 | 
				
			||||||
 | 
							g.P("var ", enumTypesVarName(f), " = make([]", protoimplPackage.Ident("EnumInfo"), ",", len(f.allEnums), ")")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(f.allMessages) > 0 {
 | 
				
			||||||
 | 
							g.P("var ", messageTypesVarName(f), " = make([]", protoimplPackage.Ident("MessageInfo"), ",", len(f.allMessages), ")")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Generate a unique list of Go types for all declarations and dependencies,
 | 
				
			||||||
 | 
						// and the associated index into the type list for all dependencies.
 | 
				
			||||||
 | 
						var goTypes []string
 | 
				
			||||||
 | 
						var depIdxs []string
 | 
				
			||||||
 | 
						seen := map[protoreflect.FullName]int{}
 | 
				
			||||||
 | 
						genDep := func(name protoreflect.FullName, depSource string) {
 | 
				
			||||||
 | 
							if depSource != "" {
 | 
				
			||||||
 | 
								line := fmt.Sprintf("%d, // %d: %s -> %s", seen[name], len(depIdxs), depSource, name)
 | 
				
			||||||
 | 
								depIdxs = append(depIdxs, line)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						genEnum := func(e *protogen.Enum, depSource string) {
 | 
				
			||||||
 | 
							if e != nil {
 | 
				
			||||||
 | 
								name := e.Desc.FullName()
 | 
				
			||||||
 | 
								if _, ok := seen[name]; !ok {
 | 
				
			||||||
 | 
									line := fmt.Sprintf("(%s)(0), // %d: %s", g.QualifiedGoIdent(e.GoIdent), len(goTypes), name)
 | 
				
			||||||
 | 
									goTypes = append(goTypes, line)
 | 
				
			||||||
 | 
									seen[name] = len(seen)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if depSource != "" {
 | 
				
			||||||
 | 
									genDep(name, depSource)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						genMessage := func(m *protogen.Message, depSource string) {
 | 
				
			||||||
 | 
							if m != nil {
 | 
				
			||||||
 | 
								name := m.Desc.FullName()
 | 
				
			||||||
 | 
								if _, ok := seen[name]; !ok {
 | 
				
			||||||
 | 
									line := fmt.Sprintf("(*%s)(nil), // %d: %s", g.QualifiedGoIdent(m.GoIdent), len(goTypes), name)
 | 
				
			||||||
 | 
									if m.Desc.IsMapEntry() {
 | 
				
			||||||
 | 
										// Map entry messages have no associated Go type.
 | 
				
			||||||
 | 
										line = fmt.Sprintf("nil, // %d: %s", len(goTypes), name)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									goTypes = append(goTypes, line)
 | 
				
			||||||
 | 
									seen[name] = len(seen)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if depSource != "" {
 | 
				
			||||||
 | 
									genDep(name, depSource)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This ordering is significant.
 | 
				
			||||||
 | 
						// See filetype.TypeBuilder.DependencyIndexes.
 | 
				
			||||||
 | 
						type offsetEntry struct {
 | 
				
			||||||
 | 
							start int
 | 
				
			||||||
 | 
							name  string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var depOffsets []offsetEntry
 | 
				
			||||||
 | 
						for _, enum := range f.allEnums {
 | 
				
			||||||
 | 
							genEnum(enum.Enum, "")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, message := range f.allMessages {
 | 
				
			||||||
 | 
							genMessage(message.Message, "")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "field type_name"})
 | 
				
			||||||
 | 
						for _, message := range f.allMessages {
 | 
				
			||||||
 | 
							for _, field := range message.Fields {
 | 
				
			||||||
 | 
								if field.Desc.IsWeak() {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								source := string(field.Desc.FullName())
 | 
				
			||||||
 | 
								genEnum(field.Enum, source+":type_name")
 | 
				
			||||||
 | 
								genMessage(field.Message, source+":type_name")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "extension extendee"})
 | 
				
			||||||
 | 
						for _, extension := range f.allExtensions {
 | 
				
			||||||
 | 
							source := string(extension.Desc.FullName())
 | 
				
			||||||
 | 
							genMessage(extension.Extendee, source+":extendee")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "extension type_name"})
 | 
				
			||||||
 | 
						for _, extension := range f.allExtensions {
 | 
				
			||||||
 | 
							source := string(extension.Desc.FullName())
 | 
				
			||||||
 | 
							genEnum(extension.Enum, source+":type_name")
 | 
				
			||||||
 | 
							genMessage(extension.Message, source+":type_name")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "method input_type"})
 | 
				
			||||||
 | 
						for _, service := range f.Services {
 | 
				
			||||||
 | 
							for _, method := range service.Methods {
 | 
				
			||||||
 | 
								source := string(method.Desc.FullName())
 | 
				
			||||||
 | 
								genMessage(method.Input, source+":input_type")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "method output_type"})
 | 
				
			||||||
 | 
						for _, service := range f.Services {
 | 
				
			||||||
 | 
							for _, method := range service.Methods {
 | 
				
			||||||
 | 
								source := string(method.Desc.FullName())
 | 
				
			||||||
 | 
								genMessage(method.Output, source+":output_type")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						depOffsets = append(depOffsets, offsetEntry{len(depIdxs), ""})
 | 
				
			||||||
 | 
						for i := len(depOffsets) - 2; i >= 0; i-- {
 | 
				
			||||||
 | 
							curr, next := depOffsets[i], depOffsets[i+1]
 | 
				
			||||||
 | 
							depIdxs = append(depIdxs, fmt.Sprintf("%d, // [%d:%d] is the sub-list for %s",
 | 
				
			||||||
 | 
								curr.start, curr.start, next.start, curr.name))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(depIdxs) > math.MaxInt32 {
 | 
				
			||||||
 | 
							panic("too many dependencies") // sanity check
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("var ", goTypesVarName(f), " = []interface{}{")
 | 
				
			||||||
 | 
						for _, s := range goTypes {
 | 
				
			||||||
 | 
							g.P(s)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("var ", depIdxsVarName(f), " = []int32{")
 | 
				
			||||||
 | 
						for _, s := range depIdxs {
 | 
				
			||||||
 | 
							g.P(s)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("func init() { ", initFuncName(f.File), "() }")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("func ", initFuncName(f.File), "() {")
 | 
				
			||||||
 | 
						g.P("if ", f.GoDescriptorIdent, " != nil {")
 | 
				
			||||||
 | 
						g.P("return")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Ensure that initialization functions for different files in the same Go
 | 
				
			||||||
 | 
						// package run in the correct order: Call the init funcs for every .proto file
 | 
				
			||||||
 | 
						// imported by this one that is in the same Go package.
 | 
				
			||||||
 | 
						for i, imps := 0, f.Desc.Imports(); i < imps.Len(); i++ {
 | 
				
			||||||
 | 
							impFile := gen.FilesByPath[imps.Get(i).Path()]
 | 
				
			||||||
 | 
							if impFile.GoImportPath != f.GoImportPath {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P(initFuncName(impFile), "()")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(f.allMessages) > 0 {
 | 
				
			||||||
 | 
							// Populate MessageInfo.Exporters.
 | 
				
			||||||
 | 
							g.P("if !", protoimplPackage.Ident("UnsafeEnabled"), " {")
 | 
				
			||||||
 | 
							for _, message := range f.allMessages {
 | 
				
			||||||
 | 
								if sf := f.allMessageFieldsByPtr[message]; len(sf.unexported) > 0 {
 | 
				
			||||||
 | 
									idx := f.allMessagesByPtr[message]
 | 
				
			||||||
 | 
									typesVar := messageTypesVarName(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									g.P(typesVar, "[", idx, "].Exporter = func(v interface{}, i int) interface{} {")
 | 
				
			||||||
 | 
									g.P("switch v := v.(*", message.GoIdent, "); i {")
 | 
				
			||||||
 | 
									for i := 0; i < sf.count; i++ {
 | 
				
			||||||
 | 
										if name := sf.unexported[i]; name != "" {
 | 
				
			||||||
 | 
											g.P("case ", i, ": return &v.", name)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									g.P("default: return nil")
 | 
				
			||||||
 | 
									g.P("}")
 | 
				
			||||||
 | 
									g.P("}")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Populate MessageInfo.OneofWrappers.
 | 
				
			||||||
 | 
							for _, message := range f.allMessages {
 | 
				
			||||||
 | 
								if len(message.Oneofs) > 0 {
 | 
				
			||||||
 | 
									idx := f.allMessagesByPtr[message]
 | 
				
			||||||
 | 
									typesVar := messageTypesVarName(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Associate the wrapper types by directly passing them to the MessageInfo.
 | 
				
			||||||
 | 
									g.P(typesVar, "[", idx, "].OneofWrappers = []interface{} {")
 | 
				
			||||||
 | 
									for _, oneof := range message.Oneofs {
 | 
				
			||||||
 | 
										if !oneof.Desc.IsSynthetic() {
 | 
				
			||||||
 | 
											for _, field := range oneof.Fields {
 | 
				
			||||||
 | 
												g.P("(*", field.GoIdent, ")(nil),")
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									g.P("}")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("type x struct{}")
 | 
				
			||||||
 | 
						g.P("out := ", protoimplPackage.Ident("TypeBuilder"), "{")
 | 
				
			||||||
 | 
						g.P("File: ", protoimplPackage.Ident("DescBuilder"), "{")
 | 
				
			||||||
 | 
						g.P("GoPackagePath: ", reflectPackage.Ident("TypeOf"), "(x{}).PkgPath(),")
 | 
				
			||||||
 | 
						g.P("RawDescriptor: ", rawDescVarName(f), ",")
 | 
				
			||||||
 | 
						g.P("NumEnums: ", len(f.allEnums), ",")
 | 
				
			||||||
 | 
						g.P("NumMessages: ", len(f.allMessages), ",")
 | 
				
			||||||
 | 
						g.P("NumExtensions: ", len(f.allExtensions), ",")
 | 
				
			||||||
 | 
						g.P("NumServices: ", len(f.Services), ",")
 | 
				
			||||||
 | 
						g.P("},")
 | 
				
			||||||
 | 
						g.P("GoTypes: ", goTypesVarName(f), ",")
 | 
				
			||||||
 | 
						g.P("DependencyIndexes: ", depIdxsVarName(f), ",")
 | 
				
			||||||
 | 
						if len(f.allEnums) > 0 {
 | 
				
			||||||
 | 
							g.P("EnumInfos: ", enumTypesVarName(f), ",")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(f.allMessages) > 0 {
 | 
				
			||||||
 | 
							g.P("MessageInfos: ", messageTypesVarName(f), ",")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(f.allExtensions) > 0 {
 | 
				
			||||||
 | 
							g.P("ExtensionInfos: ", extensionTypesVarName(f), ",")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("}.Build()")
 | 
				
			||||||
 | 
						g.P(f.GoDescriptorIdent, " = out.File")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set inputs to nil to allow GC to reclaim resources.
 | 
				
			||||||
 | 
						g.P(rawDescVarName(f), " = nil")
 | 
				
			||||||
 | 
						g.P(goTypesVarName(f), " = nil")
 | 
				
			||||||
 | 
						g.P(depIdxsVarName(f), " = nil")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) {
 | 
				
			||||||
 | 
						descProto := proto.Clone(f.Proto).(*descriptorpb.FileDescriptorProto)
 | 
				
			||||||
 | 
						descProto.SourceCodeInfo = nil // drop source code information
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b, err := proto.MarshalOptions{AllowPartial: true, Deterministic: true}.Marshal(descProto)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							gen.Error(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.P("var ", rawDescVarName(f), " = []byte{")
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							g.P(s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							b = b[n:]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if f.needRawDesc {
 | 
				
			||||||
 | 
							onceVar := rawDescVarName(f) + "Once"
 | 
				
			||||||
 | 
							dataVar := rawDescVarName(f) + "Data"
 | 
				
			||||||
 | 
							g.P("var (")
 | 
				
			||||||
 | 
							g.P(onceVar, " ", syncPackage.Ident("Once"))
 | 
				
			||||||
 | 
							g.P(dataVar, " = ", rawDescVarName(f))
 | 
				
			||||||
 | 
							g.P(")")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							g.P("func ", rawDescVarName(f), "GZIP() []byte {")
 | 
				
			||||||
 | 
							g.P(onceVar, ".Do(func() {")
 | 
				
			||||||
 | 
							g.P(dataVar, " = ", protoimplPackage.Ident("X"), ".CompressGZIP(", dataVar, ")")
 | 
				
			||||||
 | 
							g.P("})")
 | 
				
			||||||
 | 
							g.P("return ", dataVar)
 | 
				
			||||||
 | 
							g.P("}")
 | 
				
			||||||
 | 
							g.P()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genEnumReflectMethods(g *protogen.GeneratedFile, f *fileInfo, e *enumInfo) {
 | 
				
			||||||
 | 
						idx := f.allEnumsByPtr[e]
 | 
				
			||||||
 | 
						typesVar := enumTypesVarName(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Descriptor method.
 | 
				
			||||||
 | 
						g.P("func (", e.GoIdent, ") Descriptor() ", protoreflectPackage.Ident("EnumDescriptor"), " {")
 | 
				
			||||||
 | 
						g.P("return ", typesVar, "[", idx, "].Descriptor()")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Type method.
 | 
				
			||||||
 | 
						g.P("func (", e.GoIdent, ") Type() ", protoreflectPackage.Ident("EnumType"), " {")
 | 
				
			||||||
 | 
						g.P("return &", typesVar, "[", idx, "]")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Number method.
 | 
				
			||||||
 | 
						g.P("func (x ", e.GoIdent, ") Number() ", protoreflectPackage.Ident("EnumNumber"), " {")
 | 
				
			||||||
 | 
						g.P("return ", protoreflectPackage.Ident("EnumNumber"), "(x)")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func genMessageReflectMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
 | 
				
			||||||
 | 
						idx := f.allMessagesByPtr[m]
 | 
				
			||||||
 | 
						typesVar := messageTypesVarName(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ProtoReflect method.
 | 
				
			||||||
 | 
						g.P("func (x *", m.GoIdent, ") ProtoReflect() ", protoreflectPackage.Ident("Message"), " {")
 | 
				
			||||||
 | 
						g.P("mi := &", typesVar, "[", idx, "]")
 | 
				
			||||||
 | 
						g.P("if ", protoimplPackage.Ident("UnsafeEnabled"), " && x != nil {")
 | 
				
			||||||
 | 
						g.P("ms := ", protoimplPackage.Ident("X"), ".MessageStateOf(", protoimplPackage.Ident("Pointer"), "(x))")
 | 
				
			||||||
 | 
						g.P("if ms.LoadMessageInfo() == nil {")
 | 
				
			||||||
 | 
						g.P("ms.StoreMessageInfo(mi)")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P("return ms")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P("return mi.MessageOf(x)")
 | 
				
			||||||
 | 
						g.P("}")
 | 
				
			||||||
 | 
						g.P()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func fileVarName(f *protogen.File, suffix string) string {
 | 
				
			||||||
 | 
						prefix := f.GoDescriptorIdent.GoName
 | 
				
			||||||
 | 
						_, n := utf8.DecodeRuneInString(prefix)
 | 
				
			||||||
 | 
						prefix = strings.ToLower(prefix[:n]) + prefix[n:]
 | 
				
			||||||
 | 
						return prefix + "_" + suffix
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func rawDescVarName(f *fileInfo) string {
 | 
				
			||||||
 | 
						return fileVarName(f.File, "rawDesc")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func goTypesVarName(f *fileInfo) string {
 | 
				
			||||||
 | 
						return fileVarName(f.File, "goTypes")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func depIdxsVarName(f *fileInfo) string {
 | 
				
			||||||
 | 
						return fileVarName(f.File, "depIdxs")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func enumTypesVarName(f *fileInfo) string {
 | 
				
			||||||
 | 
						return fileVarName(f.File, "enumTypes")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func messageTypesVarName(f *fileInfo) string {
 | 
				
			||||||
 | 
						return fileVarName(f.File, "msgTypes")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func extensionTypesVarName(f *fileInfo) string {
 | 
				
			||||||
 | 
						return fileVarName(f.File, "extTypes")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func initFuncName(f *protogen.File) string {
 | 
				
			||||||
 | 
						return fileVarName(f, "init")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
								
									
										
											
										
									
									
										
											1080
										
									
									vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/well_known_types.go
									
										generated
									
									
										vendored
									
								
								
							
							
										
											1080
										
									
									vendor/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/well_known_types.go
									
										generated
									
									
										vendored
									
								
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								@ -0,0 +1,653 @@
 | 
				
			|||||||
 | 
					// Protocol Buffers - Google's data interchange format
 | 
				
			||||||
 | 
					// Copyright 2008 Google Inc.  All rights reserved.
 | 
				
			||||||
 | 
					// https://developers.google.com/protocol-buffers/
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					// modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					// met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					// notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//     * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					// copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					// in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					// distribution.
 | 
				
			||||||
 | 
					//     * Neither the name of Google Inc. nor the names of its
 | 
				
			||||||
 | 
					// contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 | 
					// this software without specific prior written permission.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Author: kenton@google.com (Kenton Varda)
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// WARNING:  The plugin interface is currently EXPERIMENTAL and is subject to
 | 
				
			||||||
 | 
					//   change.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// protoc (aka the Protocol Compiler) can be extended via plugins.  A plugin is
 | 
				
			||||||
 | 
					// just a program that reads a CodeGeneratorRequest from stdin and writes a
 | 
				
			||||||
 | 
					// CodeGeneratorResponse to stdout.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead
 | 
				
			||||||
 | 
					// of dealing with the raw protocol defined here.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// A plugin executable needs only to be placed somewhere in the path.  The
 | 
				
			||||||
 | 
					// plugin should be named "protoc-gen-$NAME", and will then be used when the
 | 
				
			||||||
 | 
					// flag "--${NAME}_out" is passed to protoc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Code generated by protoc-gen-go. DO NOT EDIT.
 | 
				
			||||||
 | 
					// source: google/protobuf/compiler/plugin.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package pluginpb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Sync with code_generator.h.
 | 
				
			||||||
 | 
					type CodeGeneratorResponse_Feature int32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						CodeGeneratorResponse_FEATURE_NONE            CodeGeneratorResponse_Feature = 0
 | 
				
			||||||
 | 
						CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL CodeGeneratorResponse_Feature = 1
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Enum value maps for CodeGeneratorResponse_Feature.
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						CodeGeneratorResponse_Feature_name = map[int32]string{
 | 
				
			||||||
 | 
							0: "FEATURE_NONE",
 | 
				
			||||||
 | 
							1: "FEATURE_PROTO3_OPTIONAL",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						CodeGeneratorResponse_Feature_value = map[string]int32{
 | 
				
			||||||
 | 
							"FEATURE_NONE":            0,
 | 
				
			||||||
 | 
							"FEATURE_PROTO3_OPTIONAL": 1,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x CodeGeneratorResponse_Feature) Enum() *CodeGeneratorResponse_Feature {
 | 
				
			||||||
 | 
						p := new(CodeGeneratorResponse_Feature)
 | 
				
			||||||
 | 
						*p = x
 | 
				
			||||||
 | 
						return p
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x CodeGeneratorResponse_Feature) String() string {
 | 
				
			||||||
 | 
						return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (CodeGeneratorResponse_Feature) Descriptor() protoreflect.EnumDescriptor {
 | 
				
			||||||
 | 
						return file_google_protobuf_compiler_plugin_proto_enumTypes[0].Descriptor()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (CodeGeneratorResponse_Feature) Type() protoreflect.EnumType {
 | 
				
			||||||
 | 
						return &file_google_protobuf_compiler_plugin_proto_enumTypes[0]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x CodeGeneratorResponse_Feature) Number() protoreflect.EnumNumber {
 | 
				
			||||||
 | 
						return protoreflect.EnumNumber(x)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Deprecated: Do not use.
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse_Feature) UnmarshalJSON(b []byte) error {
 | 
				
			||||||
 | 
						num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*x = CodeGeneratorResponse_Feature(num)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Deprecated: Use CodeGeneratorResponse_Feature.Descriptor instead.
 | 
				
			||||||
 | 
					func (CodeGeneratorResponse_Feature) EnumDescriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2, 0}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The version number of protocol compiler.
 | 
				
			||||||
 | 
					type Version struct {
 | 
				
			||||||
 | 
						state         protoimpl.MessageState
 | 
				
			||||||
 | 
						sizeCache     protoimpl.SizeCache
 | 
				
			||||||
 | 
						unknownFields protoimpl.UnknownFields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Major *int32 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"`
 | 
				
			||||||
 | 
						Minor *int32 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"`
 | 
				
			||||||
 | 
						Patch *int32 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"`
 | 
				
			||||||
 | 
						// A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
 | 
				
			||||||
 | 
						// be empty for mainline stable releases.
 | 
				
			||||||
 | 
						Suffix *string `protobuf:"bytes,4,opt,name=suffix" json:"suffix,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *Version) Reset() {
 | 
				
			||||||
 | 
						*x = Version{}
 | 
				
			||||||
 | 
						if protoimpl.UnsafeEnabled {
 | 
				
			||||||
 | 
							mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[0]
 | 
				
			||||||
 | 
							ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 | 
				
			||||||
 | 
							ms.StoreMessageInfo(mi)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *Version) String() string {
 | 
				
			||||||
 | 
						return protoimpl.X.MessageStringOf(x)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (*Version) ProtoMessage() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *Version) ProtoReflect() protoreflect.Message {
 | 
				
			||||||
 | 
						mi := &file_google_protobuf_compiler_plugin_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 Version.ProtoReflect.Descriptor instead.
 | 
				
			||||||
 | 
					func (*Version) Descriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{0}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *Version) GetMajor() int32 {
 | 
				
			||||||
 | 
						if x != nil && x.Major != nil {
 | 
				
			||||||
 | 
							return *x.Major
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *Version) GetMinor() int32 {
 | 
				
			||||||
 | 
						if x != nil && x.Minor != nil {
 | 
				
			||||||
 | 
							return *x.Minor
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *Version) GetPatch() int32 {
 | 
				
			||||||
 | 
						if x != nil && x.Patch != nil {
 | 
				
			||||||
 | 
							return *x.Patch
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *Version) GetSuffix() string {
 | 
				
			||||||
 | 
						if x != nil && x.Suffix != nil {
 | 
				
			||||||
 | 
							return *x.Suffix
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// An encoded CodeGeneratorRequest is written to the plugin's stdin.
 | 
				
			||||||
 | 
					type CodeGeneratorRequest struct {
 | 
				
			||||||
 | 
						state         protoimpl.MessageState
 | 
				
			||||||
 | 
						sizeCache     protoimpl.SizeCache
 | 
				
			||||||
 | 
						unknownFields protoimpl.UnknownFields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The .proto files that were explicitly listed on the command-line.  The
 | 
				
			||||||
 | 
						// code generator should generate code only for these files.  Each file's
 | 
				
			||||||
 | 
						// descriptor will be included in proto_file, below.
 | 
				
			||||||
 | 
						FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate,json=fileToGenerate" json:"file_to_generate,omitempty"`
 | 
				
			||||||
 | 
						// The generator parameter passed on the command-line.
 | 
				
			||||||
 | 
						Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"`
 | 
				
			||||||
 | 
						// FileDescriptorProtos for all files in files_to_generate and everything
 | 
				
			||||||
 | 
						// they import.  The files will appear in topological order, so each file
 | 
				
			||||||
 | 
						// appears before any file that imports it.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// protoc guarantees that all proto_files will be written after
 | 
				
			||||||
 | 
						// the fields above, even though this is not technically guaranteed by the
 | 
				
			||||||
 | 
						// protobuf wire format.  This theoretically could allow a plugin to stream
 | 
				
			||||||
 | 
						// in the FileDescriptorProtos and handle them one by one rather than read
 | 
				
			||||||
 | 
						// the entire set into memory at once.  However, as of this writing, this
 | 
				
			||||||
 | 
						// is not similarly optimized on protoc's end -- it will store all fields in
 | 
				
			||||||
 | 
						// memory at once before sending them to the plugin.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Type names of fields and extensions in the FileDescriptorProto are always
 | 
				
			||||||
 | 
						// fully qualified.
 | 
				
			||||||
 | 
						ProtoFile []*descriptorpb.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file,json=protoFile" json:"proto_file,omitempty"`
 | 
				
			||||||
 | 
						// The version number of protocol compiler.
 | 
				
			||||||
 | 
						CompilerVersion *Version `protobuf:"bytes,3,opt,name=compiler_version,json=compilerVersion" json:"compiler_version,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorRequest) Reset() {
 | 
				
			||||||
 | 
						*x = CodeGeneratorRequest{}
 | 
				
			||||||
 | 
						if protoimpl.UnsafeEnabled {
 | 
				
			||||||
 | 
							mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[1]
 | 
				
			||||||
 | 
							ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 | 
				
			||||||
 | 
							ms.StoreMessageInfo(mi)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorRequest) String() string {
 | 
				
			||||||
 | 
						return protoimpl.X.MessageStringOf(x)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (*CodeGeneratorRequest) ProtoMessage() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorRequest) ProtoReflect() protoreflect.Message {
 | 
				
			||||||
 | 
						mi := &file_google_protobuf_compiler_plugin_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 CodeGeneratorRequest.ProtoReflect.Descriptor instead.
 | 
				
			||||||
 | 
					func (*CodeGeneratorRequest) Descriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{1}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorRequest) GetFileToGenerate() []string {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.FileToGenerate
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorRequest) GetParameter() string {
 | 
				
			||||||
 | 
						if x != nil && x.Parameter != nil {
 | 
				
			||||||
 | 
							return *x.Parameter
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorRequest) GetProtoFile() []*descriptorpb.FileDescriptorProto {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.ProtoFile
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorRequest) GetCompilerVersion() *Version {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.CompilerVersion
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The plugin writes an encoded CodeGeneratorResponse to stdout.
 | 
				
			||||||
 | 
					type CodeGeneratorResponse struct {
 | 
				
			||||||
 | 
						state         protoimpl.MessageState
 | 
				
			||||||
 | 
						sizeCache     protoimpl.SizeCache
 | 
				
			||||||
 | 
						unknownFields protoimpl.UnknownFields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Error message.  If non-empty, code generation failed.  The plugin process
 | 
				
			||||||
 | 
						// should exit with status code zero even if it reports an error in this way.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// This should be used to indicate errors in .proto files which prevent the
 | 
				
			||||||
 | 
						// code generator from generating correct code.  Errors which indicate a
 | 
				
			||||||
 | 
						// problem in protoc itself -- such as the input CodeGeneratorRequest being
 | 
				
			||||||
 | 
						// unparseable -- should be reported by writing a message to stderr and
 | 
				
			||||||
 | 
						// exiting with a non-zero status code.
 | 
				
			||||||
 | 
						Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"`
 | 
				
			||||||
 | 
						// A bitmask of supported features that the code generator supports.
 | 
				
			||||||
 | 
						// This is a bitwise "or" of values from the Feature enum.
 | 
				
			||||||
 | 
						SupportedFeatures *uint64                       `protobuf:"varint,2,opt,name=supported_features,json=supportedFeatures" json:"supported_features,omitempty"`
 | 
				
			||||||
 | 
						File              []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse) Reset() {
 | 
				
			||||||
 | 
						*x = CodeGeneratorResponse{}
 | 
				
			||||||
 | 
						if protoimpl.UnsafeEnabled {
 | 
				
			||||||
 | 
							mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[2]
 | 
				
			||||||
 | 
							ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 | 
				
			||||||
 | 
							ms.StoreMessageInfo(mi)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse) String() string {
 | 
				
			||||||
 | 
						return protoimpl.X.MessageStringOf(x)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (*CodeGeneratorResponse) ProtoMessage() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse) ProtoReflect() protoreflect.Message {
 | 
				
			||||||
 | 
						mi := &file_google_protobuf_compiler_plugin_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 CodeGeneratorResponse.ProtoReflect.Descriptor instead.
 | 
				
			||||||
 | 
					func (*CodeGeneratorResponse) Descriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse) GetError() string {
 | 
				
			||||||
 | 
						if x != nil && x.Error != nil {
 | 
				
			||||||
 | 
							return *x.Error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse) GetSupportedFeatures() uint64 {
 | 
				
			||||||
 | 
						if x != nil && x.SupportedFeatures != nil {
 | 
				
			||||||
 | 
							return *x.SupportedFeatures
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse) GetFile() []*CodeGeneratorResponse_File {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.File
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Represents a single generated file.
 | 
				
			||||||
 | 
					type CodeGeneratorResponse_File struct {
 | 
				
			||||||
 | 
						state         protoimpl.MessageState
 | 
				
			||||||
 | 
						sizeCache     protoimpl.SizeCache
 | 
				
			||||||
 | 
						unknownFields protoimpl.UnknownFields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The file name, relative to the output directory.  The name must not
 | 
				
			||||||
 | 
						// contain "." or ".." components and must be relative, not be absolute (so,
 | 
				
			||||||
 | 
						// the file cannot lie outside the output directory).  "/" must be used as
 | 
				
			||||||
 | 
						// the path separator, not "\".
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// If the name is omitted, the content will be appended to the previous
 | 
				
			||||||
 | 
						// file.  This allows the generator to break large files into small chunks,
 | 
				
			||||||
 | 
						// and allows the generated text to be streamed back to protoc so that large
 | 
				
			||||||
 | 
						// files need not reside completely in memory at one time.  Note that as of
 | 
				
			||||||
 | 
						// this writing protoc does not optimize for this -- it will read the entire
 | 
				
			||||||
 | 
						// CodeGeneratorResponse before writing files to disk.
 | 
				
			||||||
 | 
						Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
 | 
				
			||||||
 | 
						// If non-empty, indicates that the named file should already exist, and the
 | 
				
			||||||
 | 
						// content here is to be inserted into that file at a defined insertion
 | 
				
			||||||
 | 
						// point.  This feature allows a code generator to extend the output
 | 
				
			||||||
 | 
						// produced by another code generator.  The original generator may provide
 | 
				
			||||||
 | 
						// insertion points by placing special annotations in the file that look
 | 
				
			||||||
 | 
						// like:
 | 
				
			||||||
 | 
						//   @@protoc_insertion_point(NAME)
 | 
				
			||||||
 | 
						// The annotation can have arbitrary text before and after it on the line,
 | 
				
			||||||
 | 
						// which allows it to be placed in a comment.  NAME should be replaced with
 | 
				
			||||||
 | 
						// an identifier naming the point -- this is what other generators will use
 | 
				
			||||||
 | 
						// as the insertion_point.  Code inserted at this point will be placed
 | 
				
			||||||
 | 
						// immediately above the line containing the insertion point (thus multiple
 | 
				
			||||||
 | 
						// insertions to the same point will come out in the order they were added).
 | 
				
			||||||
 | 
						// The double-@ is intended to make it unlikely that the generated code
 | 
				
			||||||
 | 
						// could contain things that look like insertion points by accident.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// For example, the C++ code generator places the following line in the
 | 
				
			||||||
 | 
						// .pb.h files that it generates:
 | 
				
			||||||
 | 
						//   // @@protoc_insertion_point(namespace_scope)
 | 
				
			||||||
 | 
						// This line appears within the scope of the file's package namespace, but
 | 
				
			||||||
 | 
						// outside of any particular class.  Another plugin can then specify the
 | 
				
			||||||
 | 
						// insertion_point "namespace_scope" to generate additional classes or
 | 
				
			||||||
 | 
						// other declarations that should be placed in this scope.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Note that if the line containing the insertion point begins with
 | 
				
			||||||
 | 
						// whitespace, the same whitespace will be added to every line of the
 | 
				
			||||||
 | 
						// inserted text.  This is useful for languages like Python, where
 | 
				
			||||||
 | 
						// indentation matters.  In these languages, the insertion point comment
 | 
				
			||||||
 | 
						// should be indented the same amount as any inserted code will need to be
 | 
				
			||||||
 | 
						// in order to work correctly in that context.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// The code generator that generates the initial file and the one which
 | 
				
			||||||
 | 
						// inserts into it must both run as part of a single invocation of protoc.
 | 
				
			||||||
 | 
						// Code generators are executed in the order in which they appear on the
 | 
				
			||||||
 | 
						// command line.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// If |insertion_point| is present, |name| must also be present.
 | 
				
			||||||
 | 
						InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point,json=insertionPoint" json:"insertion_point,omitempty"`
 | 
				
			||||||
 | 
						// The file contents.
 | 
				
			||||||
 | 
						Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"`
 | 
				
			||||||
 | 
						// Information describing the file content being inserted. If an insertion
 | 
				
			||||||
 | 
						// point is used, this information will be appropriately offset and inserted
 | 
				
			||||||
 | 
						// into the code generation metadata for the generated files.
 | 
				
			||||||
 | 
						GeneratedCodeInfo *descriptorpb.GeneratedCodeInfo `protobuf:"bytes,16,opt,name=generated_code_info,json=generatedCodeInfo" json:"generated_code_info,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse_File) Reset() {
 | 
				
			||||||
 | 
						*x = CodeGeneratorResponse_File{}
 | 
				
			||||||
 | 
						if protoimpl.UnsafeEnabled {
 | 
				
			||||||
 | 
							mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[3]
 | 
				
			||||||
 | 
							ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 | 
				
			||||||
 | 
							ms.StoreMessageInfo(mi)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse_File) String() string {
 | 
				
			||||||
 | 
						return protoimpl.X.MessageStringOf(x)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (*CodeGeneratorResponse_File) ProtoMessage() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse_File) ProtoReflect() protoreflect.Message {
 | 
				
			||||||
 | 
						mi := &file_google_protobuf_compiler_plugin_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 CodeGeneratorResponse_File.ProtoReflect.Descriptor instead.
 | 
				
			||||||
 | 
					func (*CodeGeneratorResponse_File) Descriptor() ([]byte, []int) {
 | 
				
			||||||
 | 
						return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2, 0}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse_File) GetName() string {
 | 
				
			||||||
 | 
						if x != nil && x.Name != nil {
 | 
				
			||||||
 | 
							return *x.Name
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse_File) GetInsertionPoint() string {
 | 
				
			||||||
 | 
						if x != nil && x.InsertionPoint != nil {
 | 
				
			||||||
 | 
							return *x.InsertionPoint
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse_File) GetContent() string {
 | 
				
			||||||
 | 
						if x != nil && x.Content != nil {
 | 
				
			||||||
 | 
							return *x.Content
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *CodeGeneratorResponse_File) GetGeneratedCodeInfo() *descriptorpb.GeneratedCodeInfo {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.GeneratedCodeInfo
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var File_google_protobuf_compiler_plugin_proto protoreflect.FileDescriptor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var file_google_protobuf_compiler_plugin_proto_rawDesc = []byte{
 | 
				
			||||||
 | 
						0x0a, 0x25, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
 | 
				
			||||||
 | 
						0x66, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69,
 | 
				
			||||||
 | 
						0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x18, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
 | 
				
			||||||
 | 
						0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
 | 
				
			||||||
 | 
						0x72, 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, 0x63, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14,
 | 
				
			||||||
 | 
						0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d,
 | 
				
			||||||
 | 
						0x61, 0x6a, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x02, 0x20,
 | 
				
			||||||
 | 
						0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61,
 | 
				
			||||||
 | 
						0x74, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68,
 | 
				
			||||||
 | 
						0x12, 0x16, 0x0a, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
 | 
				
			||||||
 | 
						0x52, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x22, 0xf1, 0x01, 0x0a, 0x14, 0x43, 0x6f, 0x64,
 | 
				
			||||||
 | 
						0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
 | 
				
			||||||
 | 
						0x74, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x67, 0x65, 0x6e,
 | 
				
			||||||
 | 
						0x65, 0x72, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x69, 0x6c,
 | 
				
			||||||
 | 
						0x65, 0x54, 0x6f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70,
 | 
				
			||||||
 | 
						0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
 | 
				
			||||||
 | 
						0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x43, 0x0a, 0x0a, 0x70, 0x72, 0x6f,
 | 
				
			||||||
 | 
						0x74, 0x6f, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
 | 
				
			||||||
 | 
						0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
 | 
				
			||||||
 | 
						0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72,
 | 
				
			||||||
 | 
						0x6f, 0x74, 0x6f, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x4c,
 | 
				
			||||||
 | 
						0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69,
 | 
				
			||||||
 | 
						0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
 | 
				
			||||||
 | 
						0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69,
 | 
				
			||||||
 | 
						0x6c, 0x65, 0x72, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x63, 0x6f, 0x6d,
 | 
				
			||||||
 | 
						0x70, 0x69, 0x6c, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x94, 0x03, 0x0a,
 | 
				
			||||||
 | 
						0x15, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65,
 | 
				
			||||||
 | 
						0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18,
 | 
				
			||||||
 | 
						0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2d, 0x0a, 0x12,
 | 
				
			||||||
 | 
						0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72,
 | 
				
			||||||
 | 
						0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72,
 | 
				
			||||||
 | 
						0x74, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x04, 0x66,
 | 
				
			||||||
 | 
						0x69, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
 | 
				
			||||||
 | 
						0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70,
 | 
				
			||||||
 | 
						0x69, 0x6c, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
 | 
				
			||||||
 | 
						0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x52,
 | 
				
			||||||
 | 
						0x04, 0x66, 0x69, 0x6c, 0x65, 0x1a, 0xb1, 0x01, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12,
 | 
				
			||||||
 | 
						0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
 | 
				
			||||||
 | 
						0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
 | 
				
			||||||
 | 
						0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x73,
 | 
				
			||||||
 | 
						0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63,
 | 
				
			||||||
 | 
						0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f,
 | 
				
			||||||
 | 
						0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x52, 0x0a, 0x13, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
 | 
				
			||||||
 | 
						0x65, 0x64, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x10, 0x20, 0x01,
 | 
				
			||||||
 | 
						0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
 | 
				
			||||||
 | 
						0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f,
 | 
				
			||||||
 | 
						0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65,
 | 
				
			||||||
 | 
						0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x38, 0x0a, 0x07, 0x46, 0x65, 0x61,
 | 
				
			||||||
 | 
						0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f,
 | 
				
			||||||
 | 
						0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52,
 | 
				
			||||||
 | 
						0x45, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x33, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41,
 | 
				
			||||||
 | 
						0x4c, 0x10, 0x01, 0x42, 0x57, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
 | 
				
			||||||
 | 
						0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69,
 | 
				
			||||||
 | 
						0x6c, 0x65, 0x72, 0x42, 0x0c, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f,
 | 
				
			||||||
 | 
						0x73, 0x5a, 0x29, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67,
 | 
				
			||||||
 | 
						0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79,
 | 
				
			||||||
 | 
						0x70, 0x65, 0x73, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x70, 0x62,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						file_google_protobuf_compiler_plugin_proto_rawDescOnce sync.Once
 | 
				
			||||||
 | 
						file_google_protobuf_compiler_plugin_proto_rawDescData = file_google_protobuf_compiler_plugin_proto_rawDesc
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func file_google_protobuf_compiler_plugin_proto_rawDescGZIP() []byte {
 | 
				
			||||||
 | 
						file_google_protobuf_compiler_plugin_proto_rawDescOnce.Do(func() {
 | 
				
			||||||
 | 
							file_google_protobuf_compiler_plugin_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_protobuf_compiler_plugin_proto_rawDescData)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return file_google_protobuf_compiler_plugin_proto_rawDescData
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var file_google_protobuf_compiler_plugin_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
 | 
				
			||||||
 | 
					var file_google_protobuf_compiler_plugin_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
 | 
				
			||||||
 | 
					var file_google_protobuf_compiler_plugin_proto_goTypes = []interface{}{
 | 
				
			||||||
 | 
						(CodeGeneratorResponse_Feature)(0),       // 0: google.protobuf.compiler.CodeGeneratorResponse.Feature
 | 
				
			||||||
 | 
						(*Version)(nil),                          // 1: google.protobuf.compiler.Version
 | 
				
			||||||
 | 
						(*CodeGeneratorRequest)(nil),             // 2: google.protobuf.compiler.CodeGeneratorRequest
 | 
				
			||||||
 | 
						(*CodeGeneratorResponse)(nil),            // 3: google.protobuf.compiler.CodeGeneratorResponse
 | 
				
			||||||
 | 
						(*CodeGeneratorResponse_File)(nil),       // 4: google.protobuf.compiler.CodeGeneratorResponse.File
 | 
				
			||||||
 | 
						(*descriptorpb.FileDescriptorProto)(nil), // 5: google.protobuf.FileDescriptorProto
 | 
				
			||||||
 | 
						(*descriptorpb.GeneratedCodeInfo)(nil),   // 6: google.protobuf.GeneratedCodeInfo
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					var file_google_protobuf_compiler_plugin_proto_depIdxs = []int32{
 | 
				
			||||||
 | 
						5, // 0: google.protobuf.compiler.CodeGeneratorRequest.proto_file:type_name -> google.protobuf.FileDescriptorProto
 | 
				
			||||||
 | 
						1, // 1: google.protobuf.compiler.CodeGeneratorRequest.compiler_version:type_name -> google.protobuf.compiler.Version
 | 
				
			||||||
 | 
						4, // 2: google.protobuf.compiler.CodeGeneratorResponse.file:type_name -> google.protobuf.compiler.CodeGeneratorResponse.File
 | 
				
			||||||
 | 
						6, // 3: google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info:type_name -> google.protobuf.GeneratedCodeInfo
 | 
				
			||||||
 | 
						4, // [4:4] is the sub-list for method output_type
 | 
				
			||||||
 | 
						4, // [4:4] is the sub-list for method input_type
 | 
				
			||||||
 | 
						4, // [4:4] is the sub-list for extension type_name
 | 
				
			||||||
 | 
						4, // [4:4] is the sub-list for extension extendee
 | 
				
			||||||
 | 
						0, // [0:4] is the sub-list for field type_name
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() { file_google_protobuf_compiler_plugin_proto_init() }
 | 
				
			||||||
 | 
					func file_google_protobuf_compiler_plugin_proto_init() {
 | 
				
			||||||
 | 
						if File_google_protobuf_compiler_plugin_proto != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !protoimpl.UnsafeEnabled {
 | 
				
			||||||
 | 
							file_google_protobuf_compiler_plugin_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
 | 
				
			||||||
 | 
								switch v := v.(*Version); i {
 | 
				
			||||||
 | 
								case 0:
 | 
				
			||||||
 | 
									return &v.state
 | 
				
			||||||
 | 
								case 1:
 | 
				
			||||||
 | 
									return &v.sizeCache
 | 
				
			||||||
 | 
								case 2:
 | 
				
			||||||
 | 
									return &v.unknownFields
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							file_google_protobuf_compiler_plugin_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
 | 
				
			||||||
 | 
								switch v := v.(*CodeGeneratorRequest); i {
 | 
				
			||||||
 | 
								case 0:
 | 
				
			||||||
 | 
									return &v.state
 | 
				
			||||||
 | 
								case 1:
 | 
				
			||||||
 | 
									return &v.sizeCache
 | 
				
			||||||
 | 
								case 2:
 | 
				
			||||||
 | 
									return &v.unknownFields
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							file_google_protobuf_compiler_plugin_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
 | 
				
			||||||
 | 
								switch v := v.(*CodeGeneratorResponse); i {
 | 
				
			||||||
 | 
								case 0:
 | 
				
			||||||
 | 
									return &v.state
 | 
				
			||||||
 | 
								case 1:
 | 
				
			||||||
 | 
									return &v.sizeCache
 | 
				
			||||||
 | 
								case 2:
 | 
				
			||||||
 | 
									return &v.unknownFields
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							file_google_protobuf_compiler_plugin_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
 | 
				
			||||||
 | 
								switch v := v.(*CodeGeneratorResponse_File); 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_google_protobuf_compiler_plugin_proto_rawDesc,
 | 
				
			||||||
 | 
								NumEnums:      1,
 | 
				
			||||||
 | 
								NumMessages:   4,
 | 
				
			||||||
 | 
								NumExtensions: 0,
 | 
				
			||||||
 | 
								NumServices:   0,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							GoTypes:           file_google_protobuf_compiler_plugin_proto_goTypes,
 | 
				
			||||||
 | 
							DependencyIndexes: file_google_protobuf_compiler_plugin_proto_depIdxs,
 | 
				
			||||||
 | 
							EnumInfos:         file_google_protobuf_compiler_plugin_proto_enumTypes,
 | 
				
			||||||
 | 
							MessageInfos:      file_google_protobuf_compiler_plugin_proto_msgTypes,
 | 
				
			||||||
 | 
						}.Build()
 | 
				
			||||||
 | 
						File_google_protobuf_compiler_plugin_proto = out.File
 | 
				
			||||||
 | 
						file_google_protobuf_compiler_plugin_proto_rawDesc = nil
 | 
				
			||||||
 | 
						file_google_protobuf_compiler_plugin_proto_goTypes = nil
 | 
				
			||||||
 | 
						file_google_protobuf_compiler_plugin_proto_depIdxs = nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
					Loading…
					
					
				
		Reference in New Issue