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