switch to new cli package and update generated files and deps

Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
This commit is contained in:
Jess Frazelle 2018-07-15 17:48:35 -04:00
parent d97dc5dbd8
commit 58cebbaa58
No known key found for this signature in database
GPG key ID: 18F3685C0022BFF3
405 changed files with 84680 additions and 51000 deletions

View file

@ -19,30 +19,39 @@ jobs:
deploy:
provider: releases
file:
- cross/reg-linux-amd64.md5
- cross/reg-windows-386.sha256
- cross/reg-linux-arm
- cross/reg-darwin-amd64.md5
- cross/reg-darwin-amd64
- cross/reg-linux-arm64.sha256
- cross/reg-linux-arm.sha256
- cross/reg-linux-386.sha256
- cross/reg-darwin-amd64.md5
- cross/reg-darwin-amd64.sha256
- cross/reg-darwin-386
- cross/reg-darwin-386.md5
- cross/reg-windows-386.md5
- cross/reg-linux-arm64.md5
- cross/reg-darwin-386.sha256
- cross/reg-freebsd-amd64
- cross/reg-freebsd-amd64.md5
- cross/reg-freebsd-amd64.sha256
- cross/reg-freebsd-386
- cross/reg-freebsd-386.md5
- cross/reg-freebsd-386.sha256
- cross/reg-linux-arm
- cross/reg-linux-arm.md5
- cross/reg-linux-arm.sha256
- cross/reg-linux-arm64
- cross/reg-linux-arm64.md5
- cross/reg-linux-arm64.sha256
- cross/reg-linux-amd64
- cross/reg-linux-amd64.md5
- cross/reg-linux-amd64.sha256
- cross/reg-linux-386
- cross/reg-linux-386.md5
- cross/reg-linux-386.sha256
- cross/reg-solaris-amd64
- cross/reg-solaris-amd64.md5
- cross/reg-solaris-amd64.sha256
- cross/reg-windows-amd64
- cross/reg-windows-amd64.md5
- cross/reg-windows-amd64.sha256
- cross/reg-linux-arm.md5
- cross/reg-darwin-386.sha256
- cross/reg-darwin-amd64.sha256
- cross/reg-windows-386
- cross/reg-darwin-386
- cross/reg-linux-386
- cross/reg-linux-amd64
- cross/reg-windows-386.md5
- cross/reg-windows-386.sha256
skip_cleanup: true
on:
tags: true

1
.traviskey Normal file
View file

@ -0,0 +1 @@
xz4uJ+vrF5+u3zucCPdnoXR/a0i8/oUzzDABuKiaB9AFFjrM8obLYo2AgMlP5zj/YHpGgTP51m/sx/qwJKfNvCoR2alBb2taYzJnhCfXzOuviZ0RZbM2LqA72lutdAzZ5eyMPCXcqvOjf6INnCmqQeJjDWo8UzGKSlWP2cqU/Qovs1vzurImME86DjqQ4EDaYlZS3tVc5BtEqmhylT2q0aO7gNJcMunDJpIEwb3vo8bbOoS6heQO2DVFf553lnZTSheEOERiF8r/O3vdMBCIqq7Xr2WIzJ4WGoNqzCk4sVcOZYP1yWa4Je/J09TaM8Uam+SZCG8p2lG+lr9toNv9jDHAA3Z986hAj+1NhRXTbwtRYM/KfL38UegvGfFCRvOAc+3AQhQaw1p2hX599in4zl/IcSVjF6IytJGj+JrCHU1p5Bd9qphFQKlXAXQKZwH+TKt3QTnrUQIUOn0QwcfgbvDUaA2XMsR9f0BWNshILvz79JJZmwXY7C7ufVSKdL+T+9dNn/5N7dMn6fWb7ZruwK3N6gLyVSulMinSYyNIHGiEH3mdoBr020KYD1w1+cfK4Ov6B8vf9k7atzHDPRklm2X0hvda2T0UXOv5+hr+OlvdhpqZKDB2HkVOUQUUfk7cL88u+FpU6pktlhJVLSCl292jWS05I1AYOiHChEFONeE=

27
Gopkg.lock generated
View file

@ -46,7 +46,7 @@
[[projects]]
branch = "master"
digest = "1:72dac224fa5dd9b1d9f8c46e29e09d36795f69bdb58e0819202ed455495fa260"
digest = "1:5ec21a936ab720c1b8c2c99936145b84325e874baa931cdf764a2eded70d8fd8"
name = "github.com/coreos/clair"
packages = [
"api/v3/clairpb",
@ -54,7 +54,7 @@
"ext/versionfmt",
]
pruneopts = ""
revision = "158bb31b77159f8628186f6113f53e2dcb273189"
revision = "9a9b1f7a13fa1cb796fe6dfb45ed241f39ce9f01"
[[projects]]
branch = "master"
@ -95,7 +95,7 @@
[[projects]]
branch = "master"
digest = "1:05c805e26044b46bcfeb5c9dcfdf6bc60589d2c66483ddd828ae1219c876af0e"
digest = "1:05ba5fe7a103a0cdb94d0310ab50aaac47a2ccb98baa210c72f4f317e7a72830"
name = "github.com/docker/docker"
packages = [
"api",
@ -131,7 +131,7 @@
"registry/resumable",
]
pruneopts = ""
revision = "a2a1d04bcae54129b5c4ddad4e4f68458fb5ef3d"
revision = "17dc10123f001d1481e4047de211c8aec7ed9d34"
[[projects]]
branch = "master"
@ -189,12 +189,20 @@
revision = "aabc10ec26b754e797f9028f4589c5b7bd90dc20"
[[projects]]
digest = "1:602c5827bcd5eca47c041a39aff7b626dda114da57a0334a9230bdc5cf8ed3ed"
branch = "master"
digest = "1:4edb8bcf6d6f1e8e8b5832406517dd187f5b79d8c620d627d39d5f2fef548bf2"
name = "github.com/genuinetools/pkg"
packages = ["cli"]
pruneopts = ""
revision = "cd7da1bd30dc725ffb0bababc615633f23654e0c"
[[projects]]
digest = "1:4af93c2cfd4bb238817e74254c231b568d06bbfe508507198eb0f6487b83c46c"
name = "github.com/gogo/protobuf"
packages = ["proto"]
pruneopts = ""
revision = "1adfc126b41513cc696b209667c8656ea7aac67c"
version = "v1.0.0"
revision = "7d68e886eac4f7e34d0d82241a6273d6c304c5cf"
version = "v1.1.0"
[[projects]]
digest = "1:b1d3041d568e065ab4d76f7477844458e9209c0bb241eaccdc0770bf0a13b120"
@ -402,14 +410,14 @@
[[projects]]
branch = "master"
digest = "1:880f5ae3ffdd8741fe179f0f70b46df57fcdd746f3a0e9d0e189bb6a241535e4"
digest = "1:a8944db88149e7ecbea4b760c625b9ccf455fceae21387bc8890c3589d28b623"
name = "golang.org/x/sys"
packages = [
"unix",
"windows",
]
pruneopts = ""
revision = "1b2967e3c290b7c545b3db0deeda16e9be4f98a2"
revision = "ac767d655b305d4e9612f5f6e33120b9176c4ad4"
[[projects]]
digest = "1:af9bfca4298ef7502c52b1459df274eed401a4f5498b900e9a92d28d3d87ac5a"
@ -495,6 +503,7 @@
"github.com/docker/docker/client",
"github.com/docker/docker/pkg/jsonmessage",
"github.com/docker/docker/pkg/term",
"github.com/genuinetools/pkg/cli",
"github.com/google/go-cmp/cmp",
"github.com/gorilla/mux",
"github.com/mitchellh/go-wordwrap",

View file

@ -19,6 +19,10 @@
# name = "github.com/x/y"
# version = "2.4.0"
[prune]
non-go = true
go-tests = true
unused-packages = true
[[override]]
name = "github.com/Sirupsen/logrus"
@ -62,4 +66,4 @@
[[override]]
name = "github.com/prometheus/client_golang"
branch = "master"
branch = "master"

View file

@ -27,7 +27,7 @@ GO_LDFLAGS_STATIC=-ldflags "-w $(CTIMEVAR) -extldflags -static"
GO := go
# List the GOOS and GOARCH to build
GOOSARCHES = darwin/amd64 darwin/386 linux/arm linux/arm64 linux/amd64 linux/386 windows/amd64 windows/386
GOOSARCHES = $(shell cat .goosarch)
.PHONY: build
build: $(NAME) ## Builds a dynamic executable or package

View file

@ -1,6 +1,8 @@
# reg
[![Travis CI](https://travis-ci.org/genuinetools/reg.svg?branch=master)](https://travis-ci.org/genuinetools/reg)
[![Travis CI](https://img.shields.io/travis/genuinetools/reg.svg?style=for-the-badge)](https://travis-ci.org/genuinetools/reg)
[![GoDoc](https://img.shields.io/badge/godoc-reference-5272B4.svg?style=for-the-badge)](https://godoc.org/github.com/genuinetools/reg)
[![Github All Releases](https://img.shields.io/github/downloads/genuinetools/reg/total.svg?style=for-the-badge)](https://github.com/genuinetools/reg/releases)
Docker registry v2 command line client.
@ -22,6 +24,8 @@ Docker registry v2 command line client.
#### Binaries
For installation instructions from binaries please visit the [Releases Page](https://github.com/genuinetools/reg/releases).
- **darwin** [386](https://github.com/genuinetools/reg/releases/download/v0.14.2/reg-darwin-386) / [amd64](https://github.com/genuinetools/reg/releases/download/v0.14.2/reg-darwin-amd64)
- **linux** [386](https://github.com/genuinetools/reg/releases/download/v0.14.2/reg-linux-386) / [amd64](https://github.com/genuinetools/reg/releases/download/v0.14.2/reg-linux-amd64) / [arm](https://github.com/genuinetools/reg/releases/download/v0.14.2/reg-linux-arm) / [arm64](https://github.com/genuinetools/reg/releases/download/v0.14.2/reg-linux-arm64)
- **windows** [386](https://github.com/genuinetools/reg/releases/download/v0.14.2/reg-windows-386) / [amd64](https://github.com/genuinetools/reg/releases/download/v0.14.2/reg-windows-amd64)

View file

@ -1,48 +0,0 @@
package main
import (
"fmt"
"github.com/genuinetools/reg/registry"
"github.com/urfave/cli"
)
var deleteCommand = cli.Command{
Name: "delete",
Aliases: []string{"rm"},
Usage: "delete a specific reference of a repository",
Action: func(c *cli.Context) error {
if len(c.Args()) < 1 {
return fmt.Errorf("pass the name of the repository")
}
image, err := registry.ParseImage(c.Args().First())
if err != nil {
return err
}
// Create the registry client.
r, err := createRegistryClient(c, image.Domain)
if err != nil {
return err
}
// Get the digest.
digest, err := r.Digest(image)
if err != nil {
return err
}
if err := image.WithDigest(digest); err != nil {
return err
}
// Delete the reference.
if err := r.Delete(image.Path, digest); err != nil {
return err
}
fmt.Printf("Deleted %s\n", image.String())
return nil
},
}

View file

@ -1,39 +1,48 @@
package main
import (
"context"
"flag"
"fmt"
"github.com/genuinetools/reg/registry"
"github.com/urfave/cli"
)
var digestCommand = cli.Command{
Name: "digest",
Usage: "get the digest",
Action: func(c *cli.Context) error {
if len(c.Args()) < 1 {
return fmt.Errorf("pass the name of the repository")
}
const digestHelp = `Get the digest for a repository.`
image, err := registry.ParseImage(c.Args().First())
if err != nil {
return err
}
func (cmd *digestCommand) Name() string { return "digest" }
func (cmd *digestCommand) Args() string { return "[OPTIONS] NAME[:TAG]" }
func (cmd *digestCommand) ShortHelp() string { return digestHelp }
func (cmd *digestCommand) LongHelp() string { return digestHelp }
func (cmd *digestCommand) Hidden() bool { return false }
// Create the registry client.
r, err := createRegistryClient(c, image.Domain)
if err != nil {
return err
}
func (cmd *digestCommand) Register(fs *flag.FlagSet) {}
// Get the digest.
digest, err := r.Digest(image)
if err != nil {
return err
}
type digestCommand struct{}
fmt.Println(digest.String())
func (cmd *digestCommand) Run(ctx context.Context, args []string) error {
if len(args) < 1 {
return fmt.Errorf("pass the name of the repository")
}
return nil
},
image, err := registry.ParseImage(args[0])
if err != nil {
return err
}
// Create the registry client.
r, err := createRegistryClient(image.Domain)
if err != nil {
return err
}
// Get the digest.
digest, err := r.Digest(image)
if err != nil {
return err
}
fmt.Println(digest.String())
return nil
}

109
layer.go
View file

@ -1,64 +1,71 @@
package main
import (
"context"
"flag"
"fmt"
"io/ioutil"
"os"
"github.com/genuinetools/reg/registry"
"github.com/urfave/cli"
)
var layerCommand = cli.Command{
Name: "layer",
Aliases: []string{"download"},
Usage: "download a layer for the specific reference of a repository",
Flags: []cli.Flag{
cli.StringFlag{
Name: "output, o",
Usage: "output file, default to stdout",
},
},
Action: func(c *cli.Context) error {
if len(c.Args()) < 1 {
return fmt.Errorf("pass the name of the repository")
}
const layerHelp = `Download a layer for a repository.`
image, err := registry.ParseImage(c.Args().First())
if err != nil {
return err
}
func (cmd *layerCommand) Name() string { return "layer" }
func (cmd *layerCommand) Args() string { return "[OPTIONS] NAME[:TAG|@DIGEST]" }
func (cmd *layerCommand) ShortHelp() string { return layerHelp }
func (cmd *layerCommand) LongHelp() string { return layerHelp }
func (cmd *layerCommand) Hidden() bool { return false }
// Create the registry client.
r, err := createRegistryClient(c, image.Domain)
if err != nil {
return err
}
// Get the digest.
digest, err := r.Digest(image)
if err != nil {
return err
}
// Download the layer.
layer, err := r.DownloadLayer(image.Path, digest)
if err != nil {
return err
}
defer layer.Close()
b, err := ioutil.ReadAll(layer)
if err != nil {
return err
}
if c.String("output") != "" {
return ioutil.WriteFile(c.String("output"), b, 0644)
}
fmt.Fprint(os.Stdout, string(b))
return nil
},
func (cmd *layerCommand) Register(fs *flag.FlagSet) {
fs.StringVar(&cmd.output, "output", "", "output file, defaults to stdout")
fs.StringVar(&cmd.output, "o", "", "output file, defaults to stdout")
}
type layerCommand struct {
output string
}
func (cmd *layerCommand) Run(ctx context.Context, args []string) error {
if len(args) < 1 {
return fmt.Errorf("pass the name of the repository")
}
image, err := registry.ParseImage(args[0])
if err != nil {
return err
}
// Create the registry client.
r, err := createRegistryClient(image.Domain)
if err != nil {
return err
}
// Get the digest.
digest, err := r.Digest(image)
if err != nil {
return err
}
// Download the layer.
layer, err := r.DownloadLayer(image.Path, digest)
if err != nil {
return err
}
defer layer.Close()
b, err := ioutil.ReadAll(layer)
if err != nil {
return err
}
if len(cmd.output) > 0 {
return ioutil.WriteFile(cmd.output, b, 0644)
}
fmt.Fprint(os.Stdout, string(b))
return nil
}

118
list.go
View file

@ -1,80 +1,86 @@
package main
import (
"context"
"flag"
"fmt"
"os"
"sort"
"strings"
"sync"
"text/tabwriter"
"github.com/urfave/cli"
)
var listCommand = cli.Command{
Name: "list",
Aliases: []string{"ls"},
Usage: "list all repositories",
Action: func(c *cli.Context) error {
if len(c.Args()) < 1 {
return fmt.Errorf("pass the domain of the registry")
}
const listHelp = `List all repositories.`
// Create the registry client.
r, err := createRegistryClient(c, c.Args().First())
if err != nil {
return err
}
func (cmd *listCommand) Name() string { return "ls" }
func (cmd *listCommand) Args() string { return "[OPTIONS] REGISTRY_DOMAIN" }
func (cmd *listCommand) ShortHelp() string { return listHelp }
func (cmd *listCommand) LongHelp() string { return listHelp }
func (cmd *listCommand) Hidden() bool { return false }
// Get the repositories via catalog.
repos, err := r.Catalog("")
if err != nil {
return err
}
sort.Strings(repos)
func (cmd *listCommand) Register(fs *flag.FlagSet) {}
fmt.Printf("Repositories for %s\n", r.Domain)
type listCommand struct{}
var (
l sync.Mutex
wg sync.WaitGroup
repoTags = map[string][]string{}
)
func (cmd *listCommand) Run(ctx context.Context, args []string) error {
if len(args) < 1 {
return fmt.Errorf("pass the domain of the registry")
}
wg.Add(len(repos))
for _, repo := range repos {
go func(repo string) {
// Get the tags.
tags, err := r.Tags(repo)
if err != nil {
fmt.Printf("Get tags of [%s] error: %s", repo, err)
}
// Sort the tags
sort.Strings(tags)
// Create the registry client.
r, err := createRegistryClient(args[0])
if err != nil {
return err
}
// Get the repositories via catalog.
repos, err := r.Catalog("")
if err != nil {
return err
}
sort.Strings(repos)
// Lock on the write to the map.
l.Lock()
repoTags[repo] = tags
l.Unlock()
fmt.Printf("Repositories for %s\n", r.Domain)
wg.Done()
}(repo)
}
wg.Wait()
var (
l sync.Mutex
wg sync.WaitGroup
repoTags = map[string][]string{}
)
// Setup the tab writer.
w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
wg.Add(len(repos))
for _, repo := range repos {
go func(repo string) {
// Get the tags.
tags, err := r.Tags(repo)
if err != nil {
fmt.Printf("Get tags of [%s] error: %s", repo, err)
}
// Sort the tags
sort.Strings(tags)
// Print header.
fmt.Fprintln(w, "REPO\tTAGS")
// Lock on the write to the map.
l.Lock()
repoTags[repo] = tags
l.Unlock()
// Sort the repos.
for _, repo := range repos {
w.Write([]byte(fmt.Sprintf("%s\t%s\n", repo, strings.Join(repoTags[repo], ", "))))
}
wg.Done()
}(repo)
}
wg.Wait()
w.Flush()
// Setup the tab writer.
w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
return nil
},
// Print header.
fmt.Fprintln(w, "REPO\tTAGS")
// Sort the repos.
for _, repo := range repos {
w.Write([]byte(fmt.Sprintf("%s\t%s\n", repo, strings.Join(repoTags[repo], ", "))))
}
w.Flush()
return nil
}

141
main.go
View file

@ -1,113 +1,102 @@
package main
import (
"context"
"flag"
"fmt"
"os"
"strings"
"time"
"github.com/genuinetools/pkg/cli"
"github.com/genuinetools/reg/registry"
"github.com/genuinetools/reg/repoutils"
"github.com/genuinetools/reg/version"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
var (
insecure bool
forceNonSSL bool
skipPing bool
timeout time.Duration
username string
password string
debug bool
)
func main() {
app := cli.NewApp()
app.Name = "reg"
app.Version = fmt.Sprintf("version %s, build %s", version.VERSION, version.GITCOMMIT)
app.Author = "The Genuinetools Authors"
app.Email = "no-reply@butts.com"
app.Usage = "Docker registry v2 client."
// Create a new cli program.
p := cli.NewProgram()
p.Name = "reg"
p.Description = "Docker registry v2 client"
// Set the GitCommit and Version.
p.GitCommit = version.GITCOMMIT
p.Version = version.VERSION
app.Flags = []cli.Flag{
cli.BoolFlag{
Name: "debug, d",
Usage: "run in debug mode",
},
cli.BoolFlag{
Name: "insecure, k",
Usage: "do not verify tls certificates",
},
cli.BoolFlag{
Name: "force-non-ssl, f",
Usage: "force allow use of non-ssl",
},
cli.StringFlag{
Name: "username, u",
Usage: "username for the registry",
},
cli.StringFlag{
Name: "password, p",
Usage: "password for the registry",
},
cli.StringFlag{
Name: "timeout",
Value: "1m",
Usage: "timeout for HTTP requests",
},
cli.BoolFlag{
Name: "skip-ping",
Usage: "skip pinging the registry while establishing connection",
},
// Build the list of available commands.
p.Commands = []cli.Command{
&digestCommand{},
&layerCommand{},
&listCommand{},
&manifestCommand{},
&removeCommand{},
&tagsCommand{},
&vulnsCommand{},
}
app.Commands = []cli.Command{
deleteCommand,
digestCommand,
layerCommand,
listCommand,
manifestCommand,
tagsCommand,
vulnsCommand,
}
// Setup the global flags.
p.FlagSet = flag.NewFlagSet("global", flag.ExitOnError)
p.FlagSet.BoolVar(&insecure, "insecure", false, "do not verify tls certificates")
p.FlagSet.BoolVar(&insecure, "k", false, "do not verify tls certificates")
app.Before = func(c *cli.Context) (err error) {
// Preload initializes any global options and configuration
// before the main or sub commands are run.
if c.GlobalBool("debug") {
p.FlagSet.BoolVar(&forceNonSSL, "force-non-ssl", false, "force allow use of non-ssl")
p.FlagSet.BoolVar(&forceNonSSL, "f", false, "force allow use of non-ssl")
p.FlagSet.BoolVar(&skipPing, "skip-ping", false, "skip pinging the registry while establishing connection")
p.FlagSet.DurationVar(&timeout, "timeout", time.Minute, "timeout for HTTP requests")
p.FlagSet.StringVar(&username, "username", "", "username for the registry")
p.FlagSet.StringVar(&username, "u", "", "username for the registry")
p.FlagSet.StringVar(&password, "password", "", "password for the registry")
p.FlagSet.StringVar(&password, "p", "", "password for the registry")
p.FlagSet.BoolVar(&debug, "d", false, "enable debug logging")
// Set the before function.
p.Before = func(ctx context.Context) error {
// Set the log level.
if debug {
logrus.SetLevel(logrus.DebugLevel)
}
if len(c.Args()) == 0 {
return
}
if c.Args()[0] == "help" {
return
}
return
return nil
}
if err := app.Run(os.Args); err != nil {
logrus.Fatal(err)
}
// Run our program.
p.Run()
}
func createRegistryClient(c *cli.Context, domain string) (*registry.Registry, error) {
auth, err := repoutils.GetAuthConfig(c.GlobalString("username"), c.GlobalString("password"), domain)
func createRegistryClient(domain string) (*registry.Registry, error) {
auth, err := repoutils.GetAuthConfig(username, password, domain)
if err != nil {
return nil, err
}
// Prevent non-ssl unless explicitly forced
if !c.GlobalBool("force-non-ssl") && strings.HasPrefix(auth.ServerAddress, "http:") {
return nil, fmt.Errorf("Attempt to use insecure protocol! Use non-ssl option to force")
}
// Parse the timeout.
timeout, err := time.ParseDuration(c.GlobalString("timeout"))
if err != nil {
return nil, fmt.Errorf("parsing %s as duration failed: %v", c.GlobalString("timeout"), err)
if !forceNonSSL && strings.HasPrefix(auth.ServerAddress, "http:") {
return nil, fmt.Errorf("Attempted to use insecure protocol! Use force-non-ssl option to force")
}
// Create the registry client.
return registry.New(auth, registry.Opt{
Insecure: c.GlobalBool("insecure"),
Debug: c.GlobalBool("debug"),
SkipPing: c.GlobalBool("skip-ping"),
Insecure: insecure,
Debug: debug,
SkipPing: skipPing,
Timeout: timeout,
})
}

View file

@ -1,60 +1,66 @@
package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"github.com/genuinetools/reg/registry"
"github.com/urfave/cli"
)
var manifestCommand = cli.Command{
Name: "manifest",
Usage: "get the json manifest for the specific reference of a repository",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "v1",
Usage: "force the version of the manifest retrieved to v1",
},
},
Action: func(c *cli.Context) error {
if len(c.Args()) < 1 {
return fmt.Errorf("pass the name of the repository")
}
const manifestHelp = `Get the json manifest for a repository.`
image, err := registry.ParseImage(c.Args().First())
if err != nil {
return err
}
func (cmd *manifestCommand) Name() string { return "manifest" }
func (cmd *manifestCommand) Args() string { return "[OPTIONS] NAME[:TAG|@DIGEST]" }
func (cmd *manifestCommand) ShortHelp() string { return manifestHelp }
func (cmd *manifestCommand) LongHelp() string { return manifestHelp }
func (cmd *manifestCommand) Hidden() bool { return false }
// Create the registry client.
r, err := createRegistryClient(c, image.Domain)
if err != nil {
return err
}
var manifest interface{}
if c.Bool("v1") {
// Get the v1 manifest if it was explicitly asked for.
manifest, err = r.ManifestV1(image.Path, image.Reference())
if err != nil {
return err
}
} else {
// Get the v2 manifest.
manifest, err = r.Manifest(image.Path, image.Reference())
if err != nil {
return err
}
}
b, err := json.MarshalIndent(manifest, " ", " ")
if err != nil {
return err
}
fmt.Println(string(b))
return nil
},
func (cmd *manifestCommand) Register(fs *flag.FlagSet) {
fs.BoolVar(&cmd.v1, "v1", false, "force the version of the manifest retrieved to v1")
}
type manifestCommand struct {
v1 bool
}
func (cmd *manifestCommand) Run(ctx context.Context, args []string) error {
if len(args) < 1 {
return fmt.Errorf("pass the name of the repository")
}
image, err := registry.ParseImage(args[0])
if err != nil {
return err
}
// Create the registry client.
r, err := createRegistryClient(image.Domain)
if err != nil {
return err
}
var manifest interface{}
if cmd.v1 {
// Get the v1 manifest if it was explicitly asked for.
manifest, err = r.ManifestV1(image.Path, image.Reference())
if err != nil {
return err
}
} else {
// Get the v2 manifest.
manifest, err = r.Manifest(image.Path, image.Reference())
if err != nil {
return err
}
}
b, err := json.MarshalIndent(manifest, " ", " ")
if err != nil {
return err
}
fmt.Println(string(b))
return nil
}

56
remove.go Normal file
View file

@ -0,0 +1,56 @@
package main
import (
"context"
"flag"
"fmt"
"github.com/genuinetools/reg/registry"
)
const removeHelp = `Delete a specific reference of a repository.`
func (cmd *removeCommand) Name() string { return "rm" }
func (cmd *removeCommand) Args() string { return "[OPTIONS] NAME[:TAG|@DIGEST]" }
func (cmd *removeCommand) ShortHelp() string { return removeHelp }
func (cmd *removeCommand) LongHelp() string { return removeHelp }
func (cmd *removeCommand) Hidden() bool { return false }
func (cmd *removeCommand) Register(fs *flag.FlagSet) {}
type removeCommand struct{}
func (cmd *removeCommand) Run(ctx context.Context, args []string) error {
if len(args) < 1 {
return fmt.Errorf("pass the name of the repository")
}
image, err := registry.ParseImage(args[0])
if err != nil {
return err
}
// Create the registry client.
r, err := createRegistryClient(image.Domain)
if err != nil {
return err
}
// Get the digest.
digest, err := r.Digest(image)
if err != nil {
return err
}
if err := image.WithDigest(digest); err != nil {
return err
}
// Delete the reference.
if err := r.Delete(image.Path, digest); err != nil {
return err
}
fmt.Printf("Deleted %s\n", image.String())
return nil
}

View file

@ -6,7 +6,7 @@ import (
"testing"
)
func TestDelete(t *testing.T) {
func TestRemove(t *testing.T) {
// Make sure we have busybox in list.
out, err := run("ls", domain)
if err != nil {

61
tags.go
View file

@ -1,42 +1,51 @@
package main
import (
"context"
"flag"
"fmt"
"sort"
"strings"
"github.com/genuinetools/reg/registry"
"github.com/urfave/cli"
)
var tagsCommand = cli.Command{
Name: "tags",
Usage: "get the tags for a repository",
Action: func(c *cli.Context) error {
if len(c.Args()) < 1 {
return fmt.Errorf("pass the name of the repository")
}
const tagsHelp = `Get the tags for a repository.`
image, err := registry.ParseImage(c.Args().First())
if err != nil {
return err
}
func (cmd *tagsCommand) Name() string { return "tags" }
func (cmd *tagsCommand) Args() string { return "[OPTIONS] NAME[:TAG|@DIGEST]" }
func (cmd *tagsCommand) ShortHelp() string { return tagsHelp }
func (cmd *tagsCommand) LongHelp() string { return tagsHelp }
func (cmd *tagsCommand) Hidden() bool { return false }
// Create the registry client.
r, err := createRegistryClient(c, image.Domain)
if err != nil {
return err
}
func (cmd *tagsCommand) Register(fs *flag.FlagSet) {}
tags, err := r.Tags(image.Path)
if err != nil {
return err
}
sort.Strings(tags)
type tagsCommand struct{}
// Print the tags.
fmt.Println(strings.Join(tags, "\n"))
func (cmd *tagsCommand) Run(ctx context.Context, args []string) error {
if len(args) < 1 {
return fmt.Errorf("pass the name of the repository")
}
return nil
},
image, err := registry.ParseImage(args[0])
if err != nil {
return err
}
// Create the registry client.
r, err := createRegistryClient(image.Domain)
if err != nil {
return err
}
tags, err := r.Tags(image.Path)
if err != nil {
return err
}
sort.Strings(tags)
// Print the tags.
fmt.Println(strings.Join(tags, "\n"))
return nil
}

View file

@ -12,18 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FROM golang:1.10-alpine
VOLUME /config
EXPOSE 6060 6061
FROM golang:1.10-alpine AS build
ADD . /go/src/github.com/coreos/clair/
WORKDIR /go/src/github.com/coreos/clair/
RUN go build github.com/coreos/clair/cmd/clair
RUN apk add --no-cache git rpm xz dumb-init && \
go install -v github.com/coreos/clair/cmd/clair && \
mv /go/bin/clair /clair && \
rm -rf /go /usr/local/go
FROM alpine:3.8
COPY --from=build /go/src/github.com/coreos/clair/clair /clair
RUN apk add --no-cache git rpm xz ca-certificates dumb-init
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/clair"]
VOLUME /config
EXPOSE 6060 6061

View file

@ -5922,7 +5922,7 @@ paths:
headers:
X-Docker-Container-Path-Stat:
type: "string"
description: "TODO"
description: "A base64 - encoded JSON object with some filesystem header information about the path"
400:
description: "Bad parameter"
schema:
@ -7589,6 +7589,7 @@ paths:
schema:
type: "object"
title: "VolumeListResponse"
description: "Volume list response"
required: [Volumes, Warnings]
properties:
Volumes:
@ -7665,6 +7666,8 @@ paths:
description: "Volume configuration"
schema:
type: "object"
description: "Volume configuration"
title: "VolumeConfig"
properties:
Name:
description: "The new volume's name. If not specified, Docker generates a name."

View file

@ -8,10 +8,8 @@ package {{ .Package }}
// ----------------------------------------------------------------------------
import (
"context"
"net/http"
context "golang.org/x/net/context"
{{ range .DefaultImports }}{{ printf "%q" . }}
{{ end }}
{{ range $key, $value := .Imports }}{{ $key }} {{ printf "%q" $value }}

View file

@ -7,7 +7,7 @@ package volume
// See hack/generate-swagger-api.sh
// ----------------------------------------------------------------------------
// VolumeCreateBody
// VolumeCreateBody Volume configuration
// swagger:model VolumeCreateBody
type VolumeCreateBody struct {

View file

@ -9,7 +9,7 @@ package volume
import "github.com/docker/docker/api/types"
// VolumeListOKBody
// VolumeListOKBody Volume list response
// swagger:model VolumeListOKBody
type VolumeListOKBody struct {

View file

@ -1,9 +1,8 @@
package client // import "github.com/docker/docker/client"
import (
"context"
"net/url"
"golang.org/x/net/context"
)
// BuildCancel requests the daemon to cancel ongoing build request

View file

@ -1,6 +1,7 @@
package client
import (
"context"
"fmt"
"io/ioutil"
"net"
@ -12,7 +13,6 @@ import (
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/api/types"
"github.com/pkg/errors"
"golang.org/x/net/context"
"gotest.tools/assert"
)

50
vendor/github.com/genuinetools/pkg/.gitignore generated vendored Normal file
View file

@ -0,0 +1,50 @@
###Go###
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
###OSX###
.DS_Store
.AppleDouble
.LSOverride
# Icon must ends with two \r.
Icon
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes
pkg
cross/
# Go coverage results
coverage.txt
profile.out

13
vendor/github.com/genuinetools/pkg/.travis.yml generated vendored Normal file
View file

@ -0,0 +1,13 @@
language: go
sudo: false
go:
- 1.10.x
before_install:
- go get github.com/golang/lint/golint
- go get honnef.co/go/tools/cmd/staticcheck
jobs:
include:
- script: make all
- stage: Run Test Coverage
script: make cover
after_success: bash <(curl -s https://codecov.io/bash)

9
vendor/github.com/genuinetools/pkg/Gopkg.lock generated vendored Normal file
View file

@ -0,0 +1,9 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = []
solver-name = "gps-cdcl"
solver-version = 1

25
vendor/github.com/genuinetools/pkg/Gopkg.toml generated vendored Normal file
View file

@ -0,0 +1,25 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[prune]
non-go = true
go-tests = true
unused-packages = true

21
vendor/github.com/genuinetools/pkg/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018 The Genuinetools Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

150
vendor/github.com/genuinetools/pkg/Makefile generated vendored Normal file
View file

@ -0,0 +1,150 @@
# Set an output prefix, which is the local directory if not specified
PREFIX?=$(shell pwd)
# Setup name variables for the package/tool
NAME := pkg
PKG := github.com/genuinetools/$(NAME)
# Set any default go build tags
BUILDTAGS :=
# Set the build dir, where built cross-compiled binaries will be output
BUILDDIR := ${PREFIX}/cross
# Populate version variables
# Add to compile time flags
VERSION := $(shell cat VERSION.txt)
GITCOMMIT := $(shell git rev-parse --short HEAD)
GITUNTRACKEDCHANGES := $(shell git status --porcelain --untracked-files=no)
ifneq ($(GITUNTRACKEDCHANGES),)
GITCOMMIT := $(GITCOMMIT)-dirty
endif
CTIMEVAR=-X $(PKG)/version.GITCOMMIT=$(GITCOMMIT) -X $(PKG)/version.VERSION=$(VERSION)
GO_LDFLAGS=-ldflags "-w $(CTIMEVAR)"
GO_LDFLAGS_STATIC=-ldflags "-w $(CTIMEVAR) -extldflags -static"
# Set our default go compiler
GO := go
# List the GOOS and GOARCH to build
GOOSARCHES = darwin/amd64 darwin/386 freebsd/amd64 freebsd/386 linux/arm linux/arm64 linux/amd64 linux/386 solaris/amd64 windows/amd64 windows/386
.PHONY: build
build: $(NAME) ## Builds a dynamic executable or package
$(NAME): $(wildcard *.go) $(wildcard */*.go) VERSION.txt
@echo "+ $@"
$(GO) build -tags "$(BUILDTAGS)" ${GO_LDFLAGS} ./...
.PHONY: static
static: ## Builds a static executable
@echo "+ $@"
CGO_ENABLED=0 $(GO) build \
-tags "$(BUILDTAGS) static_build" \
${GO_LDFLAGS_STATIC} ./...
all: clean build fmt lint test staticcheck vet install ## Runs a clean, build, fmt, lint, test, staticcheck, vet and install
.PHONY: fmt
fmt: ## Verifies all files have been `gofmt`ed
@echo "+ $@"
@gofmt -s -l . | grep -v '.pb.go:' | grep -v vendor | tee /dev/stderr
.PHONY: lint
lint: ## Verifies `golint` passes
@echo "+ $@"
@golint ./... | grep -v '.pb.go:' | grep -v vendor | tee /dev/stderr
.PHONY: test
test: ## Runs the go tests
@echo "+ $@"
@$(GO) test -v -tags "$(BUILDTAGS) cgo" $(shell $(GO) list ./... | grep -v vendor)
.PHONY: vet
vet: ## Verifies `go vet` passes
@echo "+ $@"
@$(GO) vet $(shell $(GO) list ./... | grep -v vendor) | grep -v '.pb.go:' | tee /dev/stderr
.PHONY: staticcheck
staticcheck: ## Verifies `staticcheck` passes
@echo "+ $@"
@staticcheck $(shell $(GO) list ./... | grep -v vendor) | grep -v '.pb.go:' | tee /dev/stderr
.PHONY: cover
cover: ## Runs go test with coverage
@echo "" > coverage.txt
@for d in $(shell $(GO) list ./... | grep -v vendor); do \
$(GO) test -race -coverprofile=profile.out -covermode=atomic "$$d"; \
if [ -f profile.out ]; then \
cat profile.out >> coverage.txt; \
rm profile.out; \
fi; \
done;
.PHONY: install
install: ## Installs the executable or package
@echo "+ $@"
$(GO) install -a -tags "$(BUILDTAGS)" ${GO_LDFLAGS} ./...
define buildpretty
mkdir -p $(BUILDDIR)/$(1)/$(2);
GOOS=$(1) GOARCH=$(2) CGO_ENABLED=0 $(GO) build \
-o $(BUILDDIR)/$(1)/$(2)/$(NAME) \
-a -tags "$(BUILDTAGS) static_build netgo" \
-installsuffix netgo ${GO_LDFLAGS_STATIC} .;
md5sum $(BUILDDIR)/$(1)/$(2)/$(NAME) > $(BUILDDIR)/$(1)/$(2)/$(NAME).md5;
sha256sum $(BUILDDIR)/$(1)/$(2)/$(NAME) > $(BUILDDIR)/$(1)/$(2)/$(NAME).sha256;
endef
.PHONY: cross
cross: *.go VERSION.txt ## Builds the cross-compiled binaries, creating a clean directory structure (eg. GOOS/GOARCH/binary)
@echo "+ $@"
$(foreach GOOSARCH,$(GOOSARCHES), $(call buildpretty,$(subst /,,$(dir $(GOOSARCH))),$(notdir $(GOOSARCH))))
define buildrelease
GOOS=$(1) GOARCH=$(2) CGO_ENABLED=0 $(GO) build \
-o $(BUILDDIR)/$(NAME)-$(1)-$(2) \
-a -tags "$(BUILDTAGS) static_build netgo" \
-installsuffix netgo ${GO_LDFLAGS_STATIC} .;
md5sum $(BUILDDIR)/$(NAME)-$(1)-$(2) > $(BUILDDIR)/$(NAME)-$(1)-$(2).md5;
sha256sum $(BUILDDIR)/$(NAME)-$(1)-$(2) > $(BUILDDIR)/$(NAME)-$(1)-$(2).sha256;
endef
.PHONY: release
release: *.go VERSION.txt ## Builds the cross-compiled binaries, naming them in such a way for release (eg. binary-GOOS-GOARCH)
@echo "+ $@"
$(foreach GOOSARCH,$(GOOSARCHES), $(call buildrelease,$(subst /,,$(dir $(GOOSARCH))),$(notdir $(GOOSARCH))))
.PHONY: bump-version
BUMP := patch
bump-version: ## Bump the version in the version file. Set BUMP to [ patch | major | minor ]
@$(GO) get -u github.com/jessfraz/junk/sembump # update sembump tool
$(eval NEW_VERSION = $(shell sembump --kind $(BUMP) $(VERSION)))
@echo "Bumping VERSION.txt from $(VERSION) to $(NEW_VERSION)"
echo $(NEW_VERSION) > VERSION.txt
@echo "Updating links to download binaries in README.md"
sed -i s/$(VERSION)/$(NEW_VERSION)/g README.md
git add VERSION.txt README.md
git commit -vsam "Bump version to $(NEW_VERSION)"
@echo "Run make tag to create and push the tag for new version $(NEW_VERSION)"
.PHONY: tag
tag: ## Create a new git tag to prepare to build a release
git tag -sa $(VERSION) -m "$(VERSION)"
@echo "Run git push origin $(VERSION) to push your new tag to GitHub and trigger a travis build."
.PHONY: AUTHORS
AUTHORS:
@$(file >$@,# This file lists all individuals having contributed content to the repository.)
@$(file >>$@,# For how it is generated, see `make AUTHORS`.)
@echo "$(shell git log --format='\n%aN <%aE>' | LC_ALL=C.UTF-8 sort -uf)" >> $@
.PHONY: clean
clean: ## Cleanup any build binaries or packages
@echo "+ $@"
$(RM) $(NAME)
$(RM) -r $(BUILDDIR)
.PHONY: help
help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

7
vendor/github.com/genuinetools/pkg/README.md generated vendored Normal file
View file

@ -0,0 +1,7 @@
# pkg
[![Travis CI](https://img.shields.io/travis/genuinetools/pkg.svg?style=for-the-badge)](https://travis-ci.org/genuinetools/pkg)
[![GoDoc](https://img.shields.io/badge/godoc-reference-5272B4.svg?style=for-the-badge)](https://godoc.org/github.com/genuinetools/pkg)
A home for various Go packages to be imported by other projects.

1
vendor/github.com/genuinetools/pkg/VERSION.txt generated vendored Normal file
View file

@ -0,0 +1 @@
v0.0.0

269
vendor/github.com/genuinetools/pkg/cli/cli.go generated vendored Normal file
View file

@ -0,0 +1,269 @@
package cli
import (
"bytes"
"context"
"flag"
"fmt"
"os"
"path/filepath"
"strings"
"text/tabwriter"
)
const (
// GitCommitKey is the key for the program's GitCommit data.
GitCommitKey ContextKey = "program.GitCommit"
// VersionKey is the key for the program's Version data.
VersionKey ContextKey = "program.Version"
)
// ContextKey defines the type for holding keys in the context.
type ContextKey string
// Program defines the struct for holding information about the program.
type Program struct {
// Name of the program. Defaults to path.Base(os.Args[0]).
Name string
// Description of the program.
Description string
// Version of the program.
Version string
// GitCommit information for the program.
GitCommit string
// Commands in the program.
Commands []Command
// FlagSet holds the common/global flags for the program.
FlagSet *flag.FlagSet
// Before defines a function to execute before any subcommands are run,
// but after the context is ready.
// If a non-nil error is returned, no subcommands are run.
Before func(context.Context) error
// After defines a function to execute after any subcommands are run,
// but after the subcommand has finished.
// It is run even if the subcommand returns an error.
After func(context.Context) error
// Action is the function to execute when no subcommands are specified.
Action func(context.Context) error
}
// Command defines the interface for each command in a program.
type Command interface {
Name() string // "foobar"
Args() string // "<baz> [quux...]"
ShortHelp() string // "Foo the first bar"
LongHelp() string // "Foo the first bar meeting the following conditions..."
// Hidden indicates whether the command should be hidden from the help output.
Hidden() bool
// Register command specific flags.
Register(*flag.FlagSet)
// Run executes the function for the command with a context and the command arguments.
Run(context.Context, []string) error
}
// NewProgram creates a new Program with some reasonable defaults for Name,
// Description, and Version.
func NewProgram() *Program {
return &Program{
Name: filepath.Base(os.Args[0]),
Description: "A new command line program.",
Version: "0.0.0",
}
}
// Run is the entry point for the program. It parses the arguments and executes
// the commands.
func (p *Program) Run() {
// Create the context with the values we need to pass to the version command.
ctx := context.WithValue(context.Background(), GitCommitKey, p.GitCommit)
ctx = context.WithValue(ctx, VersionKey, p.Version)
// Append the version command to the list of commands by default.
p.Commands = append(p.Commands, &versionCommand{})
// TODO(jessfraz): Find a better way to tell that they passed -h through as a flag.
if len(os.Args) > 1 &&
(strings.Contains(strings.ToLower(os.Args[1]), "help") ||
strings.ToLower(os.Args[1]) == "-h") {
p.usage(ctx)
os.Exit(1)
}
// Set the default action to print the usage if it is undefined.
if p.Action == nil {
p.Action = p.usage
}
// If we are not running commands then automatically run the main action of
// the program instead.
if len(p.Commands) <= 1 {
// Set the default flagset if our flagset is undefined.
if p.FlagSet == nil {
p.FlagSet = defaultFlagSet(p.Name)
}
// Override the usage text to something nicer.
p.FlagSet.Usage = func() {
p.usage(ctx)
}
// Parse the flags the user gave us.
if err := p.FlagSet.Parse(os.Args[1:]); err != nil {
p.usage(ctx)
os.Exit(1)
}
// Run the main action _if_ we are not in the loop for the version command
// that is added by default.
if p.FlagSet.NArg() < 1 || p.FlagSet.Arg(0) != "version" {
if p.Before != nil {
if err := p.Before(ctx); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
}
if err := p.Action(ctx); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
// Done.
return
}
}
// Iterate over the commands in the program.
for _, command := range p.Commands {
if name := command.Name(); os.Args[1] == name {
// Set the default flagset if our flagset is undefined.
if p.FlagSet == nil {
p.FlagSet = defaultFlagSet(p.Name)
}
// Register the subcommand flags in with the common/global flags.
command.Register(p.FlagSet)
// Override the usage text to something nicer.
p.resetCommandUsage(command)
// Parse the flags the user gave us.
if err := p.FlagSet.Parse(os.Args[2:]); err != nil {
p.FlagSet.Usage()
os.Exit(1)
}
if p.Before != nil {
if err := p.Before(ctx); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
}
// Run the command with the context and post-flag-processing args.
if err := command.Run(ctx, p.FlagSet.Args()); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
if p.After != nil {
if err := p.After(ctx); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
}
}
os.Exit(1)
}
// Run the after function.
if p.After != nil {
if err := p.After(ctx); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
}
// Done.
return
}
}
fmt.Fprintf(os.Stderr, "%s: no such command\n\n", os.Args[1])
p.usage(ctx)
os.Exit(1)
}
func (p *Program) usage(ctx context.Context) error {
fmt.Fprintf(os.Stderr, "%s - %s.\n\n", p.Name, strings.TrimSuffix(strings.TrimSpace(p.Description), "."))
fmt.Fprintf(os.Stderr, "Usage: %s <command>\n", p.Name)
fmt.Fprintln(os.Stderr)
// Print information about the common/global flags.
if p.FlagSet != nil {
resetFlagUsage(p.FlagSet)
}
// Print information about the commands.
fmt.Fprintln(os.Stderr, "Commands:")
fmt.Fprintln(os.Stderr)
w := tabwriter.NewWriter(os.Stderr, 0, 4, 2, ' ', 0)
for _, command := range p.Commands {
if !command.Hidden() {
fmt.Fprintf(w, "\t%s\t%s\n", command.Name(), command.ShortHelp())
}
}
w.Flush()
fmt.Fprintln(os.Stderr)
return nil
}
func (p *Program) resetCommandUsage(command Command) {
p.FlagSet.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s %s %s\n", p.Name, command.Name(), command.Args())
fmt.Fprintln(os.Stderr)
fmt.Fprintln(os.Stderr, strings.TrimSpace(command.LongHelp()))
fmt.Fprintln(os.Stderr)
resetFlagUsage(p.FlagSet)
}
}
func resetFlagUsage(fs *flag.FlagSet) {
var (
hasFlags bool
flagBlock bytes.Buffer
flagWriter = tabwriter.NewWriter(&flagBlock, 0, 4, 2, ' ', 0)
)
fs.VisitAll(func(f *flag.Flag) {
hasFlags = true
// Default-empty string vars should read "(default: <none>)"
// rather than the comparatively ugly "(default: )".
defValue := f.DefValue
if defValue == "" {
defValue = "<none>"
}
fmt.Fprintf(flagWriter, "\t-%s\t%s (default: %s)\n", f.Name, f.Usage, defValue)
})
flagWriter.Flush()
if !hasFlags {
return // Return early.
}
fmt.Fprintln(os.Stderr, "Flags:")
fmt.Fprintln(os.Stderr)
fmt.Fprintln(os.Stderr, flagBlock.String())
}
func defaultFlagSet(n string) *flag.FlagSet {
// Create the default flagset with a debug flag.
return flag.NewFlagSet(n, flag.ExitOnError)
}

3
vendor/github.com/genuinetools/pkg/cli/doc.go generated vendored Normal file
View file

@ -0,0 +1,3 @@
// Package cli provides a minimal framework for creating and organizing command line
// Go programs. It is designed to be easy to understand and write.
package cli

32
vendor/github.com/genuinetools/pkg/cli/version.go generated vendored Normal file
View file

@ -0,0 +1,32 @@
package cli
import (
"context"
"flag"
"fmt"
"runtime"
)
const versionHelp = `Show the version information.`
func (cmd *versionCommand) Name() string { return "version" }
func (cmd *versionCommand) Args() string { return "" }
func (cmd *versionCommand) ShortHelp() string { return versionHelp }
func (cmd *versionCommand) LongHelp() string { return versionHelp }
func (cmd *versionCommand) Hidden() bool { return false }
func (cmd *versionCommand) Register(fs *flag.FlagSet) {}
type versionCommand struct{}
func (cmd *versionCommand) Run(ctx context.Context, args []string) error {
fmt.Printf(`%s:
version : %s
git hash : %s
go version : %s
go compiler : %s
platform : %s/%s
`, "ship", ctx.Value(VersionKey).(string), ctx.Value(GitCommitKey).(string),
runtime.Version(), runtime.Compiler, runtime.GOOS, runtime.GOARCH)
return nil
}

2
vendor/github.com/genuinetools/pkg/doc.go generated vendored Normal file
View file

@ -0,0 +1,2 @@
// Package pkg is just the root directory for the subpackages under it.
package pkg

View file

@ -1,3 +1,6 @@
._*
*.js
*.js.map
# Conformance test output and transient files.
conformance/failing_tests.txt

View file

@ -1,3 +1,6 @@
apt:
update: true
env:
- PROTOBUF_VERSION=2.6.1
- PROTOBUF_VERSION=3.0.2
@ -10,11 +13,10 @@ before_install:
script:
- PATH=/home/travis/bin:$PATH make buildserverall
- echo $TRAVIS_GO_VERSION
- if [[ "$PROTOBUF_VERSION" == "3.5.1" ]] && [[ "$TRAVIS_GO_VERSION" =~ ^1\.9\.[0-9]+$ ]]; then ! git status --porcelain | read || (git status; git diff; exit 1); fi
- if [[ "$PROTOBUF_VERSION" == "3.5.1" ]] && [[ "$TRAVIS_GO_VERSION" == "1.10.x" ]]; then ! git status --porcelain | read || (git status; git diff; exit 1); fi
language: go
go:
- 1.8.x
- 1.9.x
- 1.10beta1
- 1.10.x

View file

@ -58,14 +58,13 @@ gofmt:
gofmt -l -s -w .
regenerate:
make -C protoc-gen-gogo/descriptor regenerate
make -C protoc-gen-gogo/plugin regenerate
make -C protoc-gen-gogo/testdata regenerate
make -C protoc-gen-gogo regenerate
make -C gogoproto regenerate
make -C proto/testdata regenerate
make -C proto/test_proto regenerate
make -C proto/proto3_proto regenerate
make -C jsonpb/jsonpb_test_proto regenerate
make -C _conformance regenerate
make -C types regenerate
make -C conformance regenerate
make -C protobuf regenerate
make -C test regenerate
make -C test/example regenerate
make -C test/unrecognized regenerate
@ -118,6 +117,10 @@ regenerate:
make -C test/int64support regenerate
make -C test/issue322 regenerate
make -C test/issue330 regenerate
make -C test/importcustom-issue389 regenerate
make -C test/merge regenerate
make -C test/cachedsize regenerate
make -C test/deterministic regenerate
make gofmt
tests:
@ -139,9 +142,10 @@ drone:
testall:
go get -u github.com/golang/protobuf/proto
make -C protoc-gen-gogo/testdata test
make -C protoc-gen-gogo test
make -C vanity/test test
make -C test/registration test
make -C conformance test
make tests
bench:
@ -153,7 +157,7 @@ contributors:
git log --format='%aN <%aE>' | sort -fu > CONTRIBUTORS
js:
ifeq (go1.9, $(findstring go1.9, $(GO_VERSION)))
ifeq (go1.10, $(findstring go1.10, $(GO_VERSION)))
go get -u github.com/gopherjs/gopherjs
gopherjs build github.com/gogo/protobuf/protoc-gen-gogo
endif

View file

@ -7,7 +7,7 @@ Google's data interchange format.
Copyright 2010 The Go Authors.
https://github.com/golang/protobuf
This package and the code it generates requires at least Go 1.4.
This package and the code it generates requires at least Go 1.6.
This software implements Go bindings for protocol buffers. For
information about protocol buffers themselves, see
@ -58,6 +58,45 @@ parameter set to the directory you want to output the Go code to.
The generated files will be suffixed .pb.go. See the Test code below
for an example using such a file.
## Packages and input paths ##
The protocol buffer language has a concept of "packages" which does not
correspond well to the Go notion of packages. In generated Go code,
each source `.proto` file is associated with a single Go package. The
name and import path for this package is specified with the `go_package`
proto option:
option go_package = "github.com/gogo/protobuf/types";
The protocol buffer compiler will attempt to derive a package name and
import path if a `go_package` option is not present, but it is
best to always specify one explicitly.
There is a one-to-one relationship between source `.proto` files and
generated `.pb.go` files, but any number of `.pb.go` files may be
contained in the same Go package.
The output name of a generated file is produced by replacing the
`.proto` suffix with `.pb.go` (e.g., `foo.proto` produces `foo.pb.go`).
However, the output directory is selected in one of two ways. Let
us say we have `inputs/x.proto` with a `go_package` option of
`github.com/golang/protobuf/p`. The corresponding output file may
be:
- Relative to the import path:
protoc --gogo_out=. inputs/x.proto
# writes ./github.com/gogo/protobuf/p/x.pb.go
(This can work well with `--gogo_out=$GOPATH`.)
- Relative to the input file:
protoc --gogo_out=paths=source_relative:. inputs/x.proto
# generate ./inputs/x.pb.go
## Generated code ##
The package comment for the proto library contains text describing
the interface provided in Go for protocol buffers. Here is an edited
version.
@ -185,19 +224,23 @@ parameter list separated from the output directory by a colon:
protoc --gogo_out=plugins=grpc,import_path=mypackage:. *.proto
- `import_prefix=xxx` - a prefix that is added onto the beginning of
all imports. Useful for things like generating protos in a
subdirectory, or regenerating vendored protobufs in-place.
- `import_path=foo/bar` - used as the package if no input files
declare `go_package`. If it contains slashes, everything up to the
rightmost slash is ignored.
- `paths=(import | source_relative)` - specifies how the paths of
generated files are structured. See the "Packages and imports paths"
section above. The default is `import`.
- `plugins=plugin1+plugin2` - specifies the list of sub-plugins to
load. The only plugin in this repo is `grpc`.
- `Mfoo/bar.proto=quux/shme` - declares that foo/bar.proto is
associated with Go package quux/shme. This is subject to the
import_prefix parameter.
The following parameters are deprecated and should not be used:
- `import_prefix=xxx` - a prefix that is added onto the beginning of
all imports.
- `import_path=foo/bar` - used as the package if no input files
declare `go_package`. If it contains slashes, everything up to the
rightmost slash is ignored.
## gRPC Support ##
If a proto file specifies RPC services, protoc-gen-go can be instructed to
@ -251,8 +294,6 @@ generated code and declare a new package-level constant whose name incorporates
the latest version number. Removing a compatibility constant is considered a
breaking change and would be subject to the announcement policy stated above.
## Plugins ##
The `protoc-gen-go/generator` package exposes a plugin interface,
which is used by the gRPC code generation. This interface is not
supported and is subject to incompatible changes without notice.

View file

@ -45,6 +45,7 @@ These projects use gogoprotobuf:
- <a href="https://github.com/go-graphite">carbonzipper stack</a>
- <a href="https://sendgrid.com/">sendgrid</a>
- <a href="https://github.com/zero-os/0-stor">zero-os/0-stor</a>
- <a href="https://github.com/spacemeshos/go-spacemesh">go-spacemesh</a>
Please let us know if you are using gogoprotobuf by posting on our <a href="https://groups.google.com/forum/#!topic/gogoprotobuf/Brw76BxmFpQ">GoogleGroup</a>.
@ -53,6 +54,11 @@ Please let us know if you are using gogoprotobuf by posting on our <a href="http
- <a href="http://www.slideshare.net/albertstrasheim/serialization-in-go">Cloudflare - go serialization talk - Albert Strasheim</a>
- <a href="https://youtu.be/4xB46Xl9O9Q?t=557">GopherCon 2014 Writing High Performance Databases in Go by Ben Johnson</a>
- <a href="https://github.com/alecthomas/go_serialization_benchmarks">alecthomas' go serialization benchmarks</a>
- <a href="http://agniva.me/go/2017/11/18/gogoproto.html">Go faster with gogoproto - Agniva De Sarker</a>
- <a href="https://www.youtube.com/watch?v=CY9T020HLP8">Evolution of protobuf (Gource Visualization) - Landon Wilkins</a>
- <a href="https://fosdem.org/2018/schedule/event/gopherjs/">Creating GopherJS Apps with gRPC-Web - Johan Brandhorst</a>
- <a href="https://jbrandhorst.com/post/gogoproto/">So you want to use GoGo Protobuf - Johan Brandhorst</a>
- <a href="https://jbrandhorst.com/post/grpc-errors/">Advanced gRPC Error Usage - Johan Brandhorst</a>
## Getting Started
@ -65,7 +71,8 @@ After that you can choose:
### Installation
To install it, you must first have Go (at least version 1.6.3) installed (see [http://golang.org/doc/install](http://golang.org/doc/install)). Latest patch versions of Go 1.8, 1.9 and 1.10 are continuously tested.
To install it, you must first have Go (at least version 1.6.3 or 1.9 if you are using gRPC) installed (see [http://golang.org/doc/install](http://golang.org/doc/install)).
Latest patch versions of 1.9 and 1.10 are continuously tested.
Next, install the standard protocol buffer implementation from [https://github.com/google/protobuf](https://github.com/google/protobuf).
Most versions from 2.3.1 should not give any problems, but 2.6.1, 3.0.2 and 3.5.1 are continuously tested.
@ -114,7 +121,7 @@ To use proto files from "google/protobuf" you need to add additional args to pro
Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types:. \
myproto.proto
Note that in the protoc command, {binary} does not contain the initial prefix of "protoc-gen".
### Most Speed and most customization
@ -137,3 +144,8 @@ It works the same as golang/protobuf, simply specify the plugin.
Here is an example using gofast:
protoc --gofast_out=plugins=grpc:. my.proto
See [https://github.com/gogo/grpc-example](https://github.com/gogo/grpc-example) for an example of using gRPC with gogoprotobuf and the wider grpc-ecosystem.

View file

@ -29,6 +29,25 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
PROTOBUF_ROOT=$(HOME)/src/protobuf
all:
@echo To run the tests in this directory, acquire the main protobuf
@echo distribution from:
@echo
@echo ' https://github.com/google/protobuf'
@echo
@echo Build the test runner with:
@echo
@echo ' cd conformance && make conformance-test-runner'
@echo
@echo And run the tests in this directory with:
@echo
@echo ' make test PROTOBUF_ROOT=<protobuf distribution>'
test:
./test.sh $(PROTOBUF_ROOT)
regenerate:
protoc-min-version --version="3.0.0" --proto_path=$(GOPATH)/src:$(GOPATH)/src/github.com/gogo/protobuf/protobuf:. --gogo_out=\
Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types,\
@ -37,4 +56,4 @@ regenerate:
Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/field_mask.proto=github.com/gogo/protobuf/types\
:. conformance_proto/conformance.proto
:. ./internal/conformance_proto/conformance.proto

View file

@ -39,7 +39,7 @@ import (
"io"
"os"
pb "github.com/gogo/protobuf/_conformance/conformance_proto"
pb "github.com/gogo/protobuf/conformance/internal/conformance_proto"
"github.com/gogo/protobuf/jsonpb"
"github.com/gogo/protobuf/proto"
)
@ -101,13 +101,6 @@ func handle(req *pb.ConformanceRequest) *pb.ConformanceResponse {
err = proto.Unmarshal(p.ProtobufPayload, &msg)
case *pb.ConformanceRequest_JsonPayload:
err = jsonpb.UnmarshalString(p.JsonPayload, &msg)
if err != nil && err.Error() == "unmarshaling Any not supported yet" {
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_Skipped{
Skipped: err.Error(),
},
}
}
default:
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_RuntimeError{

View file

@ -0,0 +1,4 @@
#!/bin/sh
cd $(dirname $0)
exec go run conformance.go $*

View file

@ -210,11 +210,6 @@ message TestAllTypes {
NestedMessage oneof_nested_message = 112;
string oneof_string = 113;
bytes oneof_bytes = 114;
bool oneof_bool = 115;
uint64 oneof_uint64 = 116;
float oneof_float = 117;
double oneof_double = 118;
NestedEnum oneof_enum = 119;
}
// Well-known types
@ -253,7 +248,6 @@ message TestAllTypes {
repeated google.protobuf.Value repeated_value = 316;
// Test field-name-to-JSON-name convention.
// (protobuf says names can be any valid C/C++ identifier.)
int32 fieldname1 = 401;
int32 field_name2 = 402;
int32 _field_name3 = 403;
@ -266,12 +260,6 @@ message TestAllTypes {
int32 Field_Name10 = 410;
int32 FIELD_NAME11 = 411;
int32 FIELD_name12 = 412;
int32 __field_name13 = 413;
int32 __Field_name14 = 414;
int32 field__name15 = 415;
int32 field__Name16 = 416;
int32 field_name17__ = 417;
int32 Field_name18__ = 418;
}
message ForeignMessage {

26
vendor/github.com/gogo/protobuf/conformance/test.sh generated vendored Executable file
View file

@ -0,0 +1,26 @@
#!/bin/bash
PROTOBUF_ROOT=$1
CONFORMANCE_ROOT=$1/conformance
CONFORMANCE_TEST_RUNNER=$CONFORMANCE_ROOT/conformance-test-runner
cd $(dirname $0)
if [[ $PROTOBUF_ROOT == "" ]]; then
echo "usage: test.sh <protobuf-root>" >/dev/stderr
exit 1
fi
if [[ ! -x $CONFORMANCE_TEST_RUNNER ]]; then
echo "SKIP: conformance test runner not installed" >/dev/stderr
exit 0
fi
a=$CONFORMANCE_ROOT/conformance.proto
b=internal/conformance_proto/conformance.proto
if [[ $(diff $a $b) != "" ]]; then
cp $a $b
echo "WARNING: conformance.proto is out of date" >/dev/stderr
fi
$CONFORMANCE_TEST_RUNNER --failure_list failure_list_go.txt ./conformance.sh

View file

@ -50,9 +50,9 @@ You might also find that basic structs that started their life as part of an API
<tr><td><a href="https://github.com/gogo/protobuf/blob/master/test/types/types.proto">stdduration</a></td><td> Duration Field </td><td> bool </td><td>Changes the Well Known Duration Type to time.Duration</td><td>Duration</td></tr>
</table>
`Warning about nullable: according to the Protocol Buffer specification, you should be able to tell whether a field is set or unset. With the option nullable=false this feature is lost, since your non-nullable fields will always be set.`
`Warning about nullable: according to the Protocol Buffer specification, you should be able to tell whether a field is set or unset. With the option nullable=false this feature is lost, since your non-nullable fields will always be set.`
# Goprotobuf Compatibility
# Goprotobuf Compatibility
Gogoprotobuf is compatible with Goprotobuf, because it is compatible with protocol buffers (see the section on tests below).
@ -70,6 +70,7 @@ The enumprefix, getters and stringer extensions can be used to remove some of th
<tr><td> goproto_extensions_map (beta) </td><td> Message </td><td> bool </td><td> if false, the extensions field is generated as type []byte instead of type map[int32]proto.Extension </td><td> true </td></tr>
<tr><td> goproto_unrecognized (beta) </td><td> Message </td><td> bool </td><td>if false, XXX_unrecognized field is not generated. This is useful to reduce GC pressure at the cost of losing information about unrecognized fields. </td><td> true </td></tr>
<tr><td> goproto_registration (beta) </td><td> File </td><td> bool </td><td>if true, the generated files will register all messages and types against both gogo/protobuf and golang/protobuf. This is necessary when using third-party packages which read registrations from golang/protobuf (such as the grpc-gateway). </td><td> false </td></tr>
<tr><td> message_name </td><td> Message </td><td> bool </td><td>if true, a `XXX_MessageName()` method is generated that returns the message's name. This is useful for grpc-gateway compatibility.</td><td> false </td></tr>
</table>
# Less Typing
@ -117,7 +118,7 @@ Other serialization formats like xml and json typically use reflect to marshal a
<a href="https://groups.google.com/forum/#!topic/gogoprotobuf/xmFnqAS6MIc">Here is a longer explanation of jsontag and moretags</a>
# File Options
# File Options
Each of the boolean message and enum extensions also have a file extension:
@ -148,12 +149,13 @@ Each of the boolean message and enum extensions also have a file extension:
* `benchgen_all`
* `enumdecl_all`
* `typedecl_all`
* `messagename_all`
Each of these are the same as their Message Option counterparts, except they apply to all messages in the file. Their Message option counterparts can also be used to overwrite their effect.
# Tests
* The normal barrage of tests are run with: `make tests`
* The normal barrage of tests are run with: `make tests`
* A few weird tests: `make testall`
* Tests for compatibility with [golang/protobuf](https://github.com/golang/protobuf) are handled by a different project [harmonytests](https://github.com/gogo/harmonytests), since it requires goprotobuf.
* Cross version tests are made with [Travis CI](https://travis-ci.org/gogo/protobuf).

View file

@ -1,20 +1,12 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: gogo.proto
/*
Package gogoproto is a generated protocol buffer package.
It is generated from these files:
gogo.proto
It has these top-level messages:
*/
package gogoproto
package gogoproto // import "github.com/gogo/protobuf/gogoproto"
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import google_protobuf "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
import descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
@ -28,7 +20,7 @@ var _ = math.Inf
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
var E_GoprotoEnumPrefix = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumOptions)(nil),
ExtendedType: (*descriptor.EnumOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 62001,
Name: "gogoproto.goproto_enum_prefix",
@ -37,7 +29,7 @@ var E_GoprotoEnumPrefix = &proto.ExtensionDesc{
}
var E_GoprotoEnumStringer = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumOptions)(nil),
ExtendedType: (*descriptor.EnumOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 62021,
Name: "gogoproto.goproto_enum_stringer",
@ -46,7 +38,7 @@ var E_GoprotoEnumStringer = &proto.ExtensionDesc{
}
var E_EnumStringer = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumOptions)(nil),
ExtendedType: (*descriptor.EnumOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 62022,
Name: "gogoproto.enum_stringer",
@ -55,7 +47,7 @@ var E_EnumStringer = &proto.ExtensionDesc{
}
var E_EnumCustomname = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumOptions)(nil),
ExtendedType: (*descriptor.EnumOptions)(nil),
ExtensionType: (*string)(nil),
Field: 62023,
Name: "gogoproto.enum_customname",
@ -64,7 +56,7 @@ var E_EnumCustomname = &proto.ExtensionDesc{
}
var E_Enumdecl = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumOptions)(nil),
ExtendedType: (*descriptor.EnumOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 62024,
Name: "gogoproto.enumdecl",
@ -73,7 +65,7 @@ var E_Enumdecl = &proto.ExtensionDesc{
}
var E_EnumvalueCustomname = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumValueOptions)(nil),
ExtendedType: (*descriptor.EnumValueOptions)(nil),
ExtensionType: (*string)(nil),
Field: 66001,
Name: "gogoproto.enumvalue_customname",
@ -82,7 +74,7 @@ var E_EnumvalueCustomname = &proto.ExtensionDesc{
}
var E_GoprotoGettersAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63001,
Name: "gogoproto.goproto_getters_all",
@ -91,7 +83,7 @@ var E_GoprotoGettersAll = &proto.ExtensionDesc{
}
var E_GoprotoEnumPrefixAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63002,
Name: "gogoproto.goproto_enum_prefix_all",
@ -100,7 +92,7 @@ var E_GoprotoEnumPrefixAll = &proto.ExtensionDesc{
}
var E_GoprotoStringerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63003,
Name: "gogoproto.goproto_stringer_all",
@ -109,7 +101,7 @@ var E_GoprotoStringerAll = &proto.ExtensionDesc{
}
var E_VerboseEqualAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63004,
Name: "gogoproto.verbose_equal_all",
@ -118,7 +110,7 @@ var E_VerboseEqualAll = &proto.ExtensionDesc{
}
var E_FaceAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63005,
Name: "gogoproto.face_all",
@ -127,7 +119,7 @@ var E_FaceAll = &proto.ExtensionDesc{
}
var E_GostringAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63006,
Name: "gogoproto.gostring_all",
@ -136,7 +128,7 @@ var E_GostringAll = &proto.ExtensionDesc{
}
var E_PopulateAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63007,
Name: "gogoproto.populate_all",
@ -145,7 +137,7 @@ var E_PopulateAll = &proto.ExtensionDesc{
}
var E_StringerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63008,
Name: "gogoproto.stringer_all",
@ -154,7 +146,7 @@ var E_StringerAll = &proto.ExtensionDesc{
}
var E_OnlyoneAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63009,
Name: "gogoproto.onlyone_all",
@ -163,7 +155,7 @@ var E_OnlyoneAll = &proto.ExtensionDesc{
}
var E_EqualAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63013,
Name: "gogoproto.equal_all",
@ -172,7 +164,7 @@ var E_EqualAll = &proto.ExtensionDesc{
}
var E_DescriptionAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63014,
Name: "gogoproto.description_all",
@ -181,7 +173,7 @@ var E_DescriptionAll = &proto.ExtensionDesc{
}
var E_TestgenAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63015,
Name: "gogoproto.testgen_all",
@ -190,7 +182,7 @@ var E_TestgenAll = &proto.ExtensionDesc{
}
var E_BenchgenAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63016,
Name: "gogoproto.benchgen_all",
@ -199,7 +191,7 @@ var E_BenchgenAll = &proto.ExtensionDesc{
}
var E_MarshalerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63017,
Name: "gogoproto.marshaler_all",
@ -208,7 +200,7 @@ var E_MarshalerAll = &proto.ExtensionDesc{
}
var E_UnmarshalerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63018,
Name: "gogoproto.unmarshaler_all",
@ -217,7 +209,7 @@ var E_UnmarshalerAll = &proto.ExtensionDesc{
}
var E_StableMarshalerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63019,
Name: "gogoproto.stable_marshaler_all",
@ -226,7 +218,7 @@ var E_StableMarshalerAll = &proto.ExtensionDesc{
}
var E_SizerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63020,
Name: "gogoproto.sizer_all",
@ -235,7 +227,7 @@ var E_SizerAll = &proto.ExtensionDesc{
}
var E_GoprotoEnumStringerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63021,
Name: "gogoproto.goproto_enum_stringer_all",
@ -244,7 +236,7 @@ var E_GoprotoEnumStringerAll = &proto.ExtensionDesc{
}
var E_EnumStringerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63022,
Name: "gogoproto.enum_stringer_all",
@ -253,7 +245,7 @@ var E_EnumStringerAll = &proto.ExtensionDesc{
}
var E_UnsafeMarshalerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63023,
Name: "gogoproto.unsafe_marshaler_all",
@ -262,7 +254,7 @@ var E_UnsafeMarshalerAll = &proto.ExtensionDesc{
}
var E_UnsafeUnmarshalerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63024,
Name: "gogoproto.unsafe_unmarshaler_all",
@ -271,7 +263,7 @@ var E_UnsafeUnmarshalerAll = &proto.ExtensionDesc{
}
var E_GoprotoExtensionsMapAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63025,
Name: "gogoproto.goproto_extensions_map_all",
@ -280,7 +272,7 @@ var E_GoprotoExtensionsMapAll = &proto.ExtensionDesc{
}
var E_GoprotoUnrecognizedAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63026,
Name: "gogoproto.goproto_unrecognized_all",
@ -289,7 +281,7 @@ var E_GoprotoUnrecognizedAll = &proto.ExtensionDesc{
}
var E_GogoprotoImport = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63027,
Name: "gogoproto.gogoproto_import",
@ -298,7 +290,7 @@ var E_GogoprotoImport = &proto.ExtensionDesc{
}
var E_ProtosizerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63028,
Name: "gogoproto.protosizer_all",
@ -307,7 +299,7 @@ var E_ProtosizerAll = &proto.ExtensionDesc{
}
var E_CompareAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63029,
Name: "gogoproto.compare_all",
@ -316,7 +308,7 @@ var E_CompareAll = &proto.ExtensionDesc{
}
var E_TypedeclAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63030,
Name: "gogoproto.typedecl_all",
@ -325,7 +317,7 @@ var E_TypedeclAll = &proto.ExtensionDesc{
}
var E_EnumdeclAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63031,
Name: "gogoproto.enumdecl_all",
@ -334,7 +326,7 @@ var E_EnumdeclAll = &proto.ExtensionDesc{
}
var E_GoprotoRegistration = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63032,
Name: "gogoproto.goproto_registration",
@ -342,8 +334,17 @@ var E_GoprotoRegistration = &proto.ExtensionDesc{
Filename: "gogo.proto",
}
var E_MessagenameAll = &proto.ExtensionDesc{
ExtendedType: (*descriptor.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63033,
Name: "gogoproto.messagename_all",
Tag: "varint,63033,opt,name=messagename_all,json=messagenameAll",
Filename: "gogo.proto",
}
var E_GoprotoGetters = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64001,
Name: "gogoproto.goproto_getters",
@ -352,7 +353,7 @@ var E_GoprotoGetters = &proto.ExtensionDesc{
}
var E_GoprotoStringer = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64003,
Name: "gogoproto.goproto_stringer",
@ -361,7 +362,7 @@ var E_GoprotoStringer = &proto.ExtensionDesc{
}
var E_VerboseEqual = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64004,
Name: "gogoproto.verbose_equal",
@ -370,7 +371,7 @@ var E_VerboseEqual = &proto.ExtensionDesc{
}
var E_Face = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64005,
Name: "gogoproto.face",
@ -379,7 +380,7 @@ var E_Face = &proto.ExtensionDesc{
}
var E_Gostring = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64006,
Name: "gogoproto.gostring",
@ -388,7 +389,7 @@ var E_Gostring = &proto.ExtensionDesc{
}
var E_Populate = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64007,
Name: "gogoproto.populate",
@ -397,7 +398,7 @@ var E_Populate = &proto.ExtensionDesc{
}
var E_Stringer = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 67008,
Name: "gogoproto.stringer",
@ -406,7 +407,7 @@ var E_Stringer = &proto.ExtensionDesc{
}
var E_Onlyone = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64009,
Name: "gogoproto.onlyone",
@ -415,7 +416,7 @@ var E_Onlyone = &proto.ExtensionDesc{
}
var E_Equal = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64013,
Name: "gogoproto.equal",
@ -424,7 +425,7 @@ var E_Equal = &proto.ExtensionDesc{
}
var E_Description = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64014,
Name: "gogoproto.description",
@ -433,7 +434,7 @@ var E_Description = &proto.ExtensionDesc{
}
var E_Testgen = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64015,
Name: "gogoproto.testgen",
@ -442,7 +443,7 @@ var E_Testgen = &proto.ExtensionDesc{
}
var E_Benchgen = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64016,
Name: "gogoproto.benchgen",
@ -451,7 +452,7 @@ var E_Benchgen = &proto.ExtensionDesc{
}
var E_Marshaler = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64017,
Name: "gogoproto.marshaler",
@ -460,7 +461,7 @@ var E_Marshaler = &proto.ExtensionDesc{
}
var E_Unmarshaler = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64018,
Name: "gogoproto.unmarshaler",
@ -469,7 +470,7 @@ var E_Unmarshaler = &proto.ExtensionDesc{
}
var E_StableMarshaler = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64019,
Name: "gogoproto.stable_marshaler",
@ -478,7 +479,7 @@ var E_StableMarshaler = &proto.ExtensionDesc{
}
var E_Sizer = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64020,
Name: "gogoproto.sizer",
@ -487,7 +488,7 @@ var E_Sizer = &proto.ExtensionDesc{
}
var E_UnsafeMarshaler = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64023,
Name: "gogoproto.unsafe_marshaler",
@ -496,7 +497,7 @@ var E_UnsafeMarshaler = &proto.ExtensionDesc{
}
var E_UnsafeUnmarshaler = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64024,
Name: "gogoproto.unsafe_unmarshaler",
@ -505,7 +506,7 @@ var E_UnsafeUnmarshaler = &proto.ExtensionDesc{
}
var E_GoprotoExtensionsMap = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64025,
Name: "gogoproto.goproto_extensions_map",
@ -514,7 +515,7 @@ var E_GoprotoExtensionsMap = &proto.ExtensionDesc{
}
var E_GoprotoUnrecognized = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64026,
Name: "gogoproto.goproto_unrecognized",
@ -523,7 +524,7 @@ var E_GoprotoUnrecognized = &proto.ExtensionDesc{
}
var E_Protosizer = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64028,
Name: "gogoproto.protosizer",
@ -532,7 +533,7 @@ var E_Protosizer = &proto.ExtensionDesc{
}
var E_Compare = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64029,
Name: "gogoproto.compare",
@ -541,7 +542,7 @@ var E_Compare = &proto.ExtensionDesc{
}
var E_Typedecl = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64030,
Name: "gogoproto.typedecl",
@ -549,8 +550,17 @@ var E_Typedecl = &proto.ExtensionDesc{
Filename: "gogo.proto",
}
var E_Messagename = &proto.ExtensionDesc{
ExtendedType: (*descriptor.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64033,
Name: "gogoproto.messagename",
Tag: "varint,64033,opt,name=messagename",
Filename: "gogo.proto",
}
var E_Nullable = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtendedType: (*descriptor.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 65001,
Name: "gogoproto.nullable",
@ -559,7 +569,7 @@ var E_Nullable = &proto.ExtensionDesc{
}
var E_Embed = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtendedType: (*descriptor.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 65002,
Name: "gogoproto.embed",
@ -568,7 +578,7 @@ var E_Embed = &proto.ExtensionDesc{
}
var E_Customtype = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtendedType: (*descriptor.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65003,
Name: "gogoproto.customtype",
@ -577,7 +587,7 @@ var E_Customtype = &proto.ExtensionDesc{
}
var E_Customname = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtendedType: (*descriptor.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65004,
Name: "gogoproto.customname",
@ -586,7 +596,7 @@ var E_Customname = &proto.ExtensionDesc{
}
var E_Jsontag = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtendedType: (*descriptor.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65005,
Name: "gogoproto.jsontag",
@ -595,7 +605,7 @@ var E_Jsontag = &proto.ExtensionDesc{
}
var E_Moretags = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtendedType: (*descriptor.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65006,
Name: "gogoproto.moretags",
@ -604,7 +614,7 @@ var E_Moretags = &proto.ExtensionDesc{
}
var E_Casttype = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtendedType: (*descriptor.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65007,
Name: "gogoproto.casttype",
@ -613,7 +623,7 @@ var E_Casttype = &proto.ExtensionDesc{
}
var E_Castkey = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtendedType: (*descriptor.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65008,
Name: "gogoproto.castkey",
@ -622,7 +632,7 @@ var E_Castkey = &proto.ExtensionDesc{
}
var E_Castvalue = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtendedType: (*descriptor.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65009,
Name: "gogoproto.castvalue",
@ -631,7 +641,7 @@ var E_Castvalue = &proto.ExtensionDesc{
}
var E_Stdtime = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtendedType: (*descriptor.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 65010,
Name: "gogoproto.stdtime",
@ -640,7 +650,7 @@ var E_Stdtime = &proto.ExtensionDesc{
}
var E_Stdduration = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtendedType: (*descriptor.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 65011,
Name: "gogoproto.stdduration",
@ -684,6 +694,7 @@ func init() {
proto.RegisterExtension(E_TypedeclAll)
proto.RegisterExtension(E_EnumdeclAll)
proto.RegisterExtension(E_GoprotoRegistration)
proto.RegisterExtension(E_MessagenameAll)
proto.RegisterExtension(E_GoprotoGetters)
proto.RegisterExtension(E_GoprotoStringer)
proto.RegisterExtension(E_VerboseEqual)
@ -707,6 +718,7 @@ func init() {
proto.RegisterExtension(E_Protosizer)
proto.RegisterExtension(E_Compare)
proto.RegisterExtension(E_Typedecl)
proto.RegisterExtension(E_Messagename)
proto.RegisterExtension(E_Nullable)
proto.RegisterExtension(E_Embed)
proto.RegisterExtension(E_Customtype)
@ -720,85 +732,86 @@ func init() {
proto.RegisterExtension(E_Stdduration)
}
func init() { proto.RegisterFile("gogo.proto", fileDescriptorGogo) }
func init() { proto.RegisterFile("gogo.proto", fileDescriptor_gogo_68790841c0f79064) }
var fileDescriptorGogo = []byte{
// 1220 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x98, 0x4b, 0x6f, 0x1c, 0x45,
0x10, 0x80, 0x85, 0x48, 0x14, 0x6f, 0xd9, 0x8e, 0xf1, 0xda, 0x98, 0x10, 0x81, 0x08, 0x9c, 0x38,
0xd9, 0xa7, 0x08, 0xa5, 0xad, 0xc8, 0x72, 0x2c, 0xc7, 0x4a, 0x84, 0xc1, 0x98, 0x38, 0xbc, 0x0e,
0xab, 0xd9, 0xdd, 0xf6, 0x78, 0x60, 0x66, 0x7a, 0x98, 0xe9, 0x89, 0xe2, 0xdc, 0x50, 0x78, 0x08,
0x21, 0xde, 0x48, 0x90, 0x90, 0x04, 0x38, 0xf0, 0x7e, 0x86, 0xf7, 0x91, 0x0b, 0x8f, 0x2b, 0xff,
0x81, 0x0b, 0x60, 0xde, 0xbe, 0xf9, 0x82, 0x6a, 0xb6, 0x6a, 0xb6, 0x67, 0xbd, 0x52, 0xf7, 0xde,
0xc6, 0xeb, 0xfe, 0xbe, 0xad, 0xa9, 0x9a, 0xae, 0xea, 0x59, 0x00, 0x5f, 0xf9, 0x6a, 0x3a, 0x49,
0x95, 0x56, 0xf5, 0x1a, 0x5e, 0x17, 0x97, 0x07, 0x0f, 0xf9, 0x4a, 0xf9, 0xa1, 0x9c, 0x29, 0xfe,
0x6a, 0xe6, 0xeb, 0x33, 0x6d, 0x99, 0xb5, 0xd2, 0x20, 0xd1, 0x2a, 0xed, 0x2c, 0x16, 0x77, 0xc1,
0x04, 0x2d, 0x6e, 0xc8, 0x38, 0x8f, 0x1a, 0x49, 0x2a, 0xd7, 0x83, 0xb3, 0xf5, 0x9b, 0xa6, 0x3b,
0xe4, 0x34, 0x93, 0xd3, 0x8b, 0x71, 0x1e, 0xdd, 0x9d, 0xe8, 0x40, 0xc5, 0xd9, 0x81, 0xab, 0xbf,
0x5c, 0x7b, 0xe8, 0x9a, 0xdb, 0x87, 0x56, 0xc7, 0x09, 0xc5, 0xff, 0xad, 0x14, 0xa0, 0x58, 0x85,
0xeb, 0x2b, 0xbe, 0x4c, 0xa7, 0x41, 0xec, 0xcb, 0xd4, 0x62, 0xfc, 0x9e, 0x8c, 0x13, 0x86, 0xf1,
0x5e, 0x42, 0xc5, 0x02, 0x8c, 0x0e, 0xe2, 0xfa, 0x81, 0x5c, 0x23, 0xd2, 0x94, 0x2c, 0xc1, 0x58,
0x21, 0x69, 0xe5, 0x99, 0x56, 0x51, 0xec, 0x45, 0xd2, 0xa2, 0xf9, 0xb1, 0xd0, 0xd4, 0x56, 0xf7,
0x23, 0xb6, 0x50, 0x52, 0x42, 0xc0, 0x10, 0x7e, 0xd2, 0x96, 0xad, 0xd0, 0x62, 0xf8, 0x89, 0x02,
0x29, 0xd7, 0x8b, 0xd3, 0x30, 0x89, 0xd7, 0x67, 0xbc, 0x30, 0x97, 0x66, 0x24, 0xb7, 0xf6, 0xf5,
0x9c, 0xc6, 0x65, 0x2c, 0xfb, 0xf9, 0xfc, 0x9e, 0x22, 0x9c, 0x89, 0x52, 0x60, 0xc4, 0x64, 0x54,
0xd1, 0x97, 0x5a, 0xcb, 0x34, 0x6b, 0x78, 0x61, 0xbf, 0xf0, 0x8e, 0x07, 0x61, 0x69, 0xbc, 0xb0,
0x55, 0xad, 0xe2, 0x52, 0x87, 0x9c, 0x0f, 0x43, 0xb1, 0x06, 0x37, 0xf4, 0x79, 0x2a, 0x1c, 0x9c,
0x17, 0xc9, 0x39, 0xb9, 0xeb, 0xc9, 0x40, 0xed, 0x0a, 0xf0, 0xe7, 0x65, 0x2d, 0x1d, 0x9c, 0xaf,
0x93, 0xb3, 0x4e, 0x2c, 0x97, 0x14, 0x8d, 0x27, 0x61, 0xfc, 0x8c, 0x4c, 0x9b, 0x2a, 0x93, 0x0d,
0xf9, 0x68, 0xee, 0x85, 0x0e, 0xba, 0x4b, 0xa4, 0x1b, 0x23, 0x70, 0x11, 0x39, 0x74, 0x1d, 0x81,
0xa1, 0x75, 0xaf, 0x25, 0x1d, 0x14, 0x97, 0x49, 0xb1, 0x0f, 0xd7, 0x23, 0x3a, 0x0f, 0x23, 0xbe,
0xea, 0xdc, 0x92, 0x03, 0x7e, 0x85, 0xf0, 0x61, 0x66, 0x48, 0x91, 0xa8, 0x24, 0x0f, 0x3d, 0xed,
0x12, 0xc1, 0x1b, 0xac, 0x60, 0x86, 0x14, 0x03, 0xa4, 0xf5, 0x4d, 0x56, 0x64, 0x46, 0x3e, 0xe7,
0x60, 0x58, 0xc5, 0xe1, 0xa6, 0x8a, 0x5d, 0x82, 0x78, 0x8b, 0x0c, 0x40, 0x08, 0x0a, 0x66, 0xa1,
0xe6, 0x5a, 0x88, 0xb7, 0xb7, 0x78, 0x7b, 0x70, 0x05, 0x96, 0x60, 0x8c, 0x1b, 0x54, 0xa0, 0x62,
0x07, 0xc5, 0x3b, 0xa4, 0xd8, 0x6f, 0x60, 0x74, 0x1b, 0x5a, 0x66, 0xda, 0x97, 0x2e, 0x92, 0x77,
0xf9, 0x36, 0x08, 0xa1, 0x54, 0x36, 0x65, 0xdc, 0xda, 0x70, 0x33, 0xbc, 0xc7, 0xa9, 0x64, 0x06,
0x15, 0x0b, 0x30, 0x1a, 0x79, 0x69, 0xb6, 0xe1, 0x85, 0x4e, 0xe5, 0x78, 0x9f, 0x1c, 0x23, 0x25,
0x44, 0x19, 0xc9, 0xe3, 0x41, 0x34, 0x1f, 0x70, 0x46, 0x0c, 0x8c, 0xb6, 0x5e, 0xa6, 0xbd, 0x66,
0x28, 0x1b, 0x83, 0xd8, 0x3e, 0xe4, 0xad, 0xd7, 0x61, 0x97, 0x4d, 0xe3, 0x2c, 0xd4, 0xb2, 0xe0,
0x9c, 0x93, 0xe6, 0x23, 0xae, 0x74, 0x01, 0x20, 0xfc, 0x00, 0xdc, 0xd8, 0x77, 0x4c, 0x38, 0xc8,
0x3e, 0x26, 0xd9, 0x54, 0x9f, 0x51, 0x41, 0x2d, 0x61, 0x50, 0xe5, 0x27, 0xdc, 0x12, 0x64, 0x8f,
0x6b, 0x05, 0x26, 0xf3, 0x38, 0xf3, 0xd6, 0x07, 0xcb, 0xda, 0xa7, 0x9c, 0xb5, 0x0e, 0x5b, 0xc9,
0xda, 0x29, 0x98, 0x22, 0xe3, 0x60, 0x75, 0xfd, 0x8c, 0x1b, 0x6b, 0x87, 0x5e, 0xab, 0x56, 0xf7,
0x21, 0x38, 0x58, 0xa6, 0xf3, 0xac, 0x96, 0x71, 0x86, 0x4c, 0x23, 0xf2, 0x12, 0x07, 0xf3, 0x55,
0x32, 0x73, 0xc7, 0x5f, 0x2c, 0x05, 0xcb, 0x5e, 0x82, 0xf2, 0xfb, 0xe1, 0x00, 0xcb, 0xf3, 0x38,
0x95, 0x2d, 0xe5, 0xc7, 0xc1, 0x39, 0xd9, 0x76, 0x50, 0x7f, 0xde, 0x53, 0xaa, 0x35, 0x03, 0x47,
0xf3, 0x09, 0xb8, 0xae, 0x3c, 0xab, 0x34, 0x82, 0x28, 0x51, 0xa9, 0xb6, 0x18, 0xbf, 0xe0, 0x4a,
0x95, 0xdc, 0x89, 0x02, 0x13, 0x8b, 0xb0, 0xbf, 0xf8, 0xd3, 0xf5, 0x91, 0xfc, 0x92, 0x44, 0xa3,
0x5d, 0x8a, 0x1a, 0x47, 0x4b, 0x45, 0x89, 0x97, 0xba, 0xf4, 0xbf, 0xaf, 0xb8, 0x71, 0x10, 0x42,
0x8d, 0x43, 0x6f, 0x26, 0x12, 0xa7, 0xbd, 0x83, 0xe1, 0x6b, 0x6e, 0x1c, 0xcc, 0x90, 0x82, 0x0f,
0x0c, 0x0e, 0x8a, 0x6f, 0x58, 0xc1, 0x0c, 0x2a, 0xee, 0xe9, 0x0e, 0xda, 0x54, 0xfa, 0x41, 0xa6,
0x53, 0x0f, 0x57, 0x5b, 0x54, 0xdf, 0x6e, 0x55, 0x0f, 0x61, 0xab, 0x06, 0x2a, 0x4e, 0xc2, 0x58,
0xcf, 0x11, 0xa3, 0x7e, 0xcb, 0x2e, 0xdb, 0xb2, 0xcc, 0x32, 0xcf, 0x2f, 0x85, 0x8f, 0x6d, 0x53,
0x33, 0xaa, 0x9e, 0x30, 0xc4, 0x9d, 0x58, 0xf7, 0xea, 0x39, 0xc0, 0x2e, 0x3b, 0xbf, 0x5d, 0x96,
0xbe, 0x72, 0x0c, 0x10, 0xc7, 0x61, 0xb4, 0x72, 0x06, 0xb0, 0xab, 0x1e, 0x27, 0xd5, 0x88, 0x79,
0x04, 0x10, 0x87, 0x61, 0x0f, 0xce, 0x73, 0x3b, 0xfe, 0x04, 0xe1, 0xc5, 0x72, 0x71, 0x14, 0x86,
0x78, 0x8e, 0xdb, 0xd1, 0x27, 0x09, 0x2d, 0x11, 0xc4, 0x79, 0x86, 0xdb, 0xf1, 0xa7, 0x18, 0x67,
0x04, 0x71, 0xf7, 0x14, 0x7e, 0xf7, 0xcc, 0x1e, 0xea, 0xc3, 0x9c, 0xbb, 0x59, 0xd8, 0x47, 0xc3,
0xdb, 0x4e, 0x3f, 0x4d, 0x5f, 0xce, 0x84, 0xb8, 0x03, 0xf6, 0x3a, 0x26, 0xfc, 0x59, 0x42, 0x3b,
0xeb, 0xc5, 0x02, 0x0c, 0x1b, 0x03, 0xdb, 0x8e, 0x3f, 0x47, 0xb8, 0x49, 0x61, 0xe8, 0x34, 0xb0,
0xed, 0x82, 0xe7, 0x39, 0x74, 0x22, 0x30, 0x6d, 0x3c, 0xab, 0xed, 0xf4, 0x0b, 0x9c, 0x75, 0x46,
0xc4, 0x1c, 0xd4, 0xca, 0xfe, 0x6b, 0xe7, 0x5f, 0x24, 0xbe, 0xcb, 0x60, 0x06, 0x8c, 0xfe, 0x6f,
0x57, 0xbc, 0xc4, 0x19, 0x30, 0x28, 0xdc, 0x46, 0xbd, 0x33, 0xdd, 0x6e, 0x7a, 0x99, 0xb7, 0x51,
0xcf, 0x48, 0xc7, 0x6a, 0x16, 0x6d, 0xd0, 0xae, 0x78, 0x85, 0xab, 0x59, 0xac, 0xc7, 0x30, 0x7a,
0x87, 0xa4, 0xdd, 0xf1, 0x2a, 0x87, 0xd1, 0x33, 0x23, 0xc5, 0x0a, 0xd4, 0x77, 0x0f, 0x48, 0xbb,
0xef, 0x35, 0xf2, 0x8d, 0xef, 0x9a, 0x8f, 0xe2, 0x3e, 0x98, 0xea, 0x3f, 0x1c, 0xed, 0xd6, 0x0b,
0xdb, 0x3d, 0xaf, 0x33, 0xe6, 0x6c, 0x14, 0xa7, 0xba, 0x5d, 0xd6, 0x1c, 0x8c, 0x76, 0xed, 0xc5,
0xed, 0x6a, 0xa3, 0x35, 0xe7, 0xa2, 0x98, 0x07, 0xe8, 0xce, 0x24, 0xbb, 0xeb, 0x12, 0xb9, 0x0c,
0x08, 0xb7, 0x06, 0x8d, 0x24, 0x3b, 0x7f, 0x99, 0xb7, 0x06, 0x11, 0xb8, 0x35, 0x78, 0x1a, 0xd9,
0xe9, 0x2b, 0xbc, 0x35, 0x18, 0x11, 0xb3, 0x30, 0x14, 0xe7, 0x61, 0x88, 0xcf, 0x56, 0xfd, 0xe6,
0x3e, 0xe3, 0x46, 0x86, 0x6d, 0x86, 0x7f, 0xdd, 0x21, 0x98, 0x01, 0x71, 0x18, 0xf6, 0xca, 0xa8,
0x29, 0xdb, 0x36, 0xf2, 0xb7, 0x1d, 0xee, 0x27, 0xb8, 0x5a, 0xcc, 0x01, 0x74, 0x5e, 0xa6, 0x31,
0x0a, 0x1b, 0xfb, 0xfb, 0x4e, 0xe7, 0xbd, 0xde, 0x40, 0xba, 0x82, 0xe2, 0x6d, 0xdc, 0x22, 0xd8,
0xaa, 0x0a, 0x8a, 0x17, 0xf0, 0x23, 0xb0, 0xef, 0xe1, 0x4c, 0xc5, 0xda, 0xf3, 0x6d, 0xf4, 0x1f,
0x44, 0xf3, 0x7a, 0x4c, 0x58, 0xa4, 0x52, 0xa9, 0x3d, 0x3f, 0xb3, 0xb1, 0x7f, 0x12, 0x5b, 0x02,
0x08, 0xb7, 0xbc, 0x4c, 0xbb, 0xdc, 0xf7, 0x5f, 0x0c, 0x33, 0x80, 0x41, 0xe3, 0xf5, 0x23, 0x72,
0xd3, 0xc6, 0xfe, 0xcd, 0x41, 0xd3, 0x7a, 0x71, 0x14, 0x6a, 0x78, 0x59, 0xfc, 0x0e, 0x61, 0x83,
0xff, 0x21, 0xb8, 0x4b, 0xe0, 0x37, 0x67, 0xba, 0xad, 0x03, 0x7b, 0xb2, 0xff, 0xa5, 0x4a, 0xf3,
0x7a, 0x31, 0x0f, 0xc3, 0x99, 0x6e, 0xb7, 0x73, 0x3a, 0xd1, 0x58, 0xf0, 0xff, 0x76, 0xca, 0x97,
0xdc, 0x92, 0x39, 0xb6, 0x08, 0x13, 0x2d, 0x15, 0xf5, 0x82, 0xc7, 0x60, 0x49, 0x2d, 0xa9, 0x95,
0x62, 0x17, 0x3d, 0x78, 0x9b, 0x1f, 0xe8, 0x8d, 0xbc, 0x39, 0xdd, 0x52, 0xd1, 0x0c, 0x1e, 0x35,
0xbb, 0xbf, 0xa0, 0x95, 0x07, 0xcf, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xed, 0x5f, 0x6c, 0x20,
0x74, 0x13, 0x00, 0x00,
var fileDescriptor_gogo_68790841c0f79064 = []byte{
// 1246 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x98, 0x49, 0x6f, 0x1c, 0x45,
0x14, 0x80, 0x85, 0x70, 0x64, 0xcf, 0xf3, 0x86, 0xc7, 0xc6, 0x84, 0x08, 0x44, 0xe0, 0xc4, 0xc9,
0x3e, 0x45, 0x28, 0x65, 0x45, 0x96, 0x63, 0x39, 0x56, 0x10, 0x06, 0x63, 0xe2, 0xb0, 0x1d, 0x46,
0x3d, 0x33, 0xe5, 0x76, 0x43, 0x77, 0xd7, 0xd0, 0x5d, 0x1d, 0xc5, 0xb9, 0xa1, 0xb0, 0x08, 0x21,
0x76, 0x24, 0x48, 0x48, 0x02, 0x39, 0xb0, 0xaf, 0x61, 0xe7, 0xc6, 0x85, 0xe5, 0xca, 0x7f, 0xe0,
0x02, 0x98, 0xdd, 0x37, 0x5f, 0xa2, 0xd7, 0xfd, 0x5e, 0x4f, 0xcd, 0x78, 0xa4, 0xaa, 0xb9, 0xb5,
0xed, 0xfa, 0x3e, 0x57, 0xbf, 0x57, 0xf5, 0xde, 0x9b, 0x01, 0xf0, 0x95, 0xaf, 0x66, 0x5a, 0x89,
0xd2, 0xaa, 0x5a, 0xc1, 0xe7, 0xfc, 0xf1, 0xc0, 0x41, 0x5f, 0x29, 0x3f, 0x94, 0xb3, 0xf9, 0x4f,
0xf5, 0x6c, 0x63, 0xb6, 0x29, 0xd3, 0x46, 0x12, 0xb4, 0xb4, 0x4a, 0x8a, 0xc5, 0xe2, 0x6e, 0x98,
0xa4, 0xc5, 0x35, 0x19, 0x67, 0x51, 0xad, 0x95, 0xc8, 0x8d, 0xe0, 0x74, 0xf5, 0xa6, 0x99, 0x82,
0x9c, 0x61, 0x72, 0x66, 0x29, 0xce, 0xa2, 0x7b, 0x5a, 0x3a, 0x50, 0x71, 0xba, 0xff, 0xca, 0xaf,
0xd7, 0x1e, 0xbc, 0xe6, 0xf6, 0xa1, 0xb5, 0x09, 0x42, 0xf1, 0x6f, 0xab, 0x39, 0x28, 0xd6, 0xe0,
0xfa, 0x0e, 0x5f, 0xaa, 0x93, 0x20, 0xf6, 0x65, 0x62, 0x31, 0xfe, 0x40, 0xc6, 0x49, 0xc3, 0x78,
0x1f, 0xa1, 0x62, 0x11, 0x46, 0xfb, 0x71, 0xfd, 0x48, 0xae, 0x11, 0x69, 0x4a, 0x96, 0x61, 0x3c,
0x97, 0x34, 0xb2, 0x54, 0xab, 0x28, 0xf6, 0x22, 0x69, 0xd1, 0xfc, 0x94, 0x6b, 0x2a, 0x6b, 0x63,
0x88, 0x2d, 0x96, 0x94, 0x10, 0x30, 0x84, 0xbf, 0x69, 0xca, 0x46, 0x68, 0x31, 0xfc, 0x4c, 0x1b,
0x29, 0xd7, 0x8b, 0x93, 0x30, 0x85, 0xcf, 0xa7, 0xbc, 0x30, 0x93, 0xe6, 0x4e, 0x6e, 0xed, 0xe9,
0x39, 0x89, 0xcb, 0x58, 0xf6, 0xcb, 0xd9, 0x81, 0x7c, 0x3b, 0x93, 0xa5, 0xc0, 0xd8, 0x93, 0x91,
0x45, 0x5f, 0x6a, 0x2d, 0x93, 0xb4, 0xe6, 0x85, 0xbd, 0xb6, 0x77, 0x2c, 0x08, 0x4b, 0xe3, 0xb9,
0xed, 0xce, 0x2c, 0x2e, 0x17, 0xe4, 0x42, 0x18, 0x8a, 0x75, 0xb8, 0xa1, 0xc7, 0xa9, 0x70, 0x70,
0x9e, 0x27, 0xe7, 0xd4, 0x9e, 0x93, 0x81, 0xda, 0x55, 0xe0, 0xdf, 0x97, 0xb9, 0x74, 0x70, 0xbe,
0x41, 0xce, 0x2a, 0xb1, 0x9c, 0x52, 0x34, 0xde, 0x09, 0x13, 0xa7, 0x64, 0x52, 0x57, 0xa9, 0xac,
0xc9, 0xc7, 0x32, 0x2f, 0x74, 0xd0, 0x5d, 0x20, 0xdd, 0x38, 0x81, 0x4b, 0xc8, 0xa1, 0xeb, 0x30,
0x0c, 0x6d, 0x78, 0x0d, 0xe9, 0xa0, 0xb8, 0x48, 0x8a, 0x41, 0x5c, 0x8f, 0xe8, 0x02, 0x8c, 0xf8,
0xaa, 0x78, 0x25, 0x07, 0xfc, 0x12, 0xe1, 0xc3, 0xcc, 0x90, 0xa2, 0xa5, 0x5a, 0x59, 0xe8, 0x69,
0x97, 0x1d, 0xbc, 0xc9, 0x0a, 0x66, 0x48, 0xd1, 0x47, 0x58, 0xdf, 0x62, 0x45, 0x6a, 0xc4, 0x73,
0x1e, 0x86, 0x55, 0x1c, 0x6e, 0xa9, 0xd8, 0x65, 0x13, 0x97, 0xc9, 0x00, 0x84, 0xa0, 0x60, 0x0e,
0x2a, 0xae, 0x89, 0x78, 0x7b, 0x9b, 0xaf, 0x07, 0x67, 0x60, 0x19, 0xc6, 0xb9, 0x40, 0x05, 0x2a,
0x76, 0x50, 0xbc, 0x43, 0x8a, 0x31, 0x03, 0xa3, 0xd7, 0xd0, 0x32, 0xd5, 0xbe, 0x74, 0x91, 0xbc,
0xcb, 0xaf, 0x41, 0x08, 0x85, 0xb2, 0x2e, 0xe3, 0xc6, 0xa6, 0x9b, 0xe1, 0x3d, 0x0e, 0x25, 0x33,
0xa8, 0x58, 0x84, 0xd1, 0xc8, 0x4b, 0xd2, 0x4d, 0x2f, 0x74, 0x4a, 0xc7, 0xfb, 0xe4, 0x18, 0x29,
0x21, 0x8a, 0x48, 0x16, 0xf7, 0xa3, 0xf9, 0x80, 0x23, 0x62, 0x60, 0x74, 0xf5, 0x52, 0xed, 0xd5,
0x43, 0x59, 0xeb, 0xc7, 0xf6, 0x21, 0x5f, 0xbd, 0x82, 0x5d, 0x31, 0x8d, 0x73, 0x50, 0x49, 0x83,
0x33, 0x4e, 0x9a, 0x8f, 0x38, 0xd3, 0x39, 0x80, 0xf0, 0x83, 0x70, 0x63, 0xcf, 0x36, 0xe1, 0x20,
0xfb, 0x98, 0x64, 0xd3, 0x3d, 0x5a, 0x05, 0x95, 0x84, 0x7e, 0x95, 0x9f, 0x70, 0x49, 0x90, 0x5d,
0xae, 0x55, 0x98, 0xca, 0xe2, 0xd4, 0xdb, 0xe8, 0x2f, 0x6a, 0x9f, 0x72, 0xd4, 0x0a, 0xb6, 0x23,
0x6a, 0x27, 0x60, 0x9a, 0x8c, 0xfd, 0xe5, 0xf5, 0x33, 0x2e, 0xac, 0x05, 0xbd, 0xde, 0x99, 0xdd,
0x87, 0xe1, 0x40, 0x19, 0xce, 0xd3, 0x5a, 0xc6, 0x29, 0x32, 0xb5, 0xc8, 0x6b, 0x39, 0x98, 0xaf,
0x90, 0x99, 0x2b, 0xfe, 0x52, 0x29, 0x58, 0xf1, 0x5a, 0x28, 0x7f, 0x00, 0xf6, 0xb3, 0x3c, 0x8b,
0x13, 0xd9, 0x50, 0x7e, 0x1c, 0x9c, 0x91, 0x4d, 0x07, 0xf5, 0xe7, 0x5d, 0xa9, 0x5a, 0x37, 0x70,
0x34, 0x1f, 0x87, 0xeb, 0xca, 0x59, 0xa5, 0x16, 0x44, 0x2d, 0x95, 0x68, 0x8b, 0xf1, 0x0b, 0xce,
0x54, 0xc9, 0x1d, 0xcf, 0x31, 0xb1, 0x04, 0x63, 0xf9, 0x8f, 0xae, 0x47, 0xf2, 0x4b, 0x12, 0x8d,
0xb6, 0x29, 0x2a, 0x1c, 0x0d, 0x15, 0xb5, 0xbc, 0xc4, 0xa5, 0xfe, 0x7d, 0xc5, 0x85, 0x83, 0x10,
0x2a, 0x1c, 0x7a, 0xab, 0x25, 0xb1, 0xdb, 0x3b, 0x18, 0xbe, 0xe6, 0xc2, 0xc1, 0x0c, 0x29, 0x78,
0x60, 0x70, 0x50, 0x7c, 0xc3, 0x0a, 0x66, 0x50, 0x71, 0x6f, 0xbb, 0xd1, 0x26, 0xd2, 0x0f, 0x52,
0x9d, 0x78, 0xb8, 0xda, 0xa2, 0xfa, 0x76, 0xbb, 0x73, 0x08, 0x5b, 0x33, 0x50, 0xac, 0x44, 0x91,
0x4c, 0x53, 0xcf, 0x97, 0x38, 0x71, 0x38, 0x6c, 0xec, 0x3b, 0xae, 0x44, 0x06, 0x56, 0xdc, 0xcf,
0xf1, 0xae, 0x59, 0xa5, 0x7a, 0xcb, 0x1e, 0xd1, 0x4a, 0xc1, 0xb0, 0xeb, 0xf1, 0x1d, 0x72, 0x75,
0x8e, 0x2a, 0xe2, 0x2e, 0x3c, 0x40, 0x9d, 0x03, 0x85, 0x5d, 0x76, 0x76, 0xa7, 0x3c, 0x43, 0x1d,
0xf3, 0x84, 0x38, 0x06, 0xa3, 0x1d, 0xc3, 0x84, 0x5d, 0xf5, 0x04, 0xa9, 0x46, 0xcc, 0x59, 0x42,
0x1c, 0x82, 0x01, 0x1c, 0x0c, 0xec, 0xf8, 0x93, 0x84, 0xe7, 0xcb, 0xc5, 0x11, 0x18, 0xe2, 0x81,
0xc0, 0x8e, 0x3e, 0x45, 0x68, 0x89, 0x20, 0xce, 0xc3, 0x80, 0x1d, 0x7f, 0x9a, 0x71, 0x46, 0x10,
0x77, 0x0f, 0xe1, 0xf7, 0xcf, 0x0e, 0x50, 0x41, 0xe7, 0xd8, 0xcd, 0xc1, 0x20, 0x4d, 0x01, 0x76,
0xfa, 0x19, 0xfa, 0xe7, 0x4c, 0x88, 0x3b, 0x60, 0x9f, 0x63, 0xc0, 0x9f, 0x23, 0xb4, 0x58, 0x2f,
0x16, 0x61, 0xd8, 0xe8, 0xfc, 0x76, 0xfc, 0x79, 0xc2, 0x4d, 0x0a, 0xb7, 0x4e, 0x9d, 0xdf, 0x2e,
0x78, 0x81, 0xb7, 0x4e, 0x04, 0x86, 0x8d, 0x9b, 0xbe, 0x9d, 0x7e, 0x91, 0xa3, 0xce, 0x88, 0x98,
0x87, 0x4a, 0x59, 0xc8, 0xed, 0xfc, 0x4b, 0xc4, 0xb7, 0x19, 0x8c, 0x80, 0xd1, 0x48, 0xec, 0x8a,
0x97, 0x39, 0x02, 0x06, 0x85, 0xd7, 0xa8, 0x7b, 0x38, 0xb0, 0x9b, 0x5e, 0xe1, 0x6b, 0xd4, 0x35,
0x1b, 0x60, 0x36, 0xf3, 0x7a, 0x6a, 0x57, 0xbc, 0xca, 0xd9, 0xcc, 0xd7, 0xe3, 0x36, 0xba, 0xbb,
0xad, 0xdd, 0xf1, 0x1a, 0x6f, 0xa3, 0xab, 0xd9, 0x8a, 0x55, 0xa8, 0xee, 0xed, 0xb4, 0x76, 0xdf,
0xeb, 0xe4, 0x9b, 0xd8, 0xd3, 0x68, 0xc5, 0xfd, 0x30, 0xdd, 0xbb, 0xcb, 0xda, 0xad, 0xe7, 0x76,
0xba, 0x3e, 0x17, 0x99, 0x4d, 0x56, 0x9c, 0x68, 0x97, 0x6b, 0xb3, 0xc3, 0xda, 0xb5, 0xe7, 0x77,
0x3a, 0x2b, 0xb6, 0xd9, 0x60, 0xc5, 0x02, 0x40, 0xbb, 0xb9, 0xd9, 0x5d, 0x17, 0xc8, 0x65, 0x40,
0x78, 0x35, 0xa8, 0xb7, 0xd9, 0xf9, 0x8b, 0x7c, 0x35, 0x88, 0xc0, 0xab, 0xc1, 0x6d, 0xcd, 0x4e,
0x5f, 0xe2, 0xab, 0xc1, 0x08, 0x9e, 0x6c, 0xa3, 0x73, 0xd8, 0x0d, 0x97, 0xf9, 0x64, 0x1b, 0x94,
0x98, 0x83, 0xa1, 0x38, 0x0b, 0x43, 0x3c, 0xa0, 0xd5, 0x9b, 0x7b, 0xb4, 0x2b, 0x19, 0x36, 0x99,
0xff, 0x6d, 0x97, 0x76, 0xc0, 0x80, 0x38, 0x04, 0xfb, 0x64, 0x54, 0x97, 0x4d, 0x1b, 0xf9, 0xfb,
0x2e, 0x17, 0x25, 0x5c, 0x2d, 0xe6, 0x01, 0x8a, 0x8f, 0xf6, 0xf8, 0x2a, 0x36, 0xf6, 0x8f, 0xdd,
0xe2, 0x5b, 0x06, 0x03, 0x69, 0x0b, 0xf2, 0x17, 0xb7, 0x08, 0xb6, 0x3b, 0x05, 0xf9, 0x5b, 0x1f,
0x86, 0xc1, 0x47, 0x52, 0x15, 0x6b, 0xcf, 0xb7, 0xd1, 0x7f, 0x12, 0xcd, 0xeb, 0x31, 0x60, 0x91,
0x4a, 0xa4, 0xf6, 0xfc, 0xd4, 0xc6, 0xfe, 0x45, 0x6c, 0x09, 0x20, 0xdc, 0xf0, 0x52, 0xed, 0xf2,
0xde, 0x7f, 0x33, 0xcc, 0x00, 0x6e, 0x1a, 0x9f, 0x1f, 0x95, 0x5b, 0x36, 0xf6, 0x1f, 0xde, 0x34,
0xad, 0x17, 0x47, 0xa0, 0x82, 0x8f, 0xf9, 0xb7, 0x22, 0x36, 0xf8, 0x5f, 0x82, 0xdb, 0x04, 0xfe,
0xe7, 0x54, 0x37, 0x75, 0x60, 0x0f, 0xf6, 0x7f, 0x94, 0x69, 0x5e, 0x2f, 0x16, 0x60, 0x38, 0xd5,
0xcd, 0x66, 0x46, 0xf3, 0x95, 0x05, 0xff, 0x7f, 0xb7, 0xfc, 0xc8, 0x5d, 0x32, 0x47, 0x97, 0x60,
0xb2, 0xa1, 0xa2, 0x6e, 0xf0, 0x28, 0x2c, 0xab, 0x65, 0xb5, 0x9a, 0x5f, 0xc5, 0x87, 0x6e, 0xf3,
0x03, 0xbd, 0x99, 0xd5, 0x67, 0x1a, 0x2a, 0x9a, 0xc5, 0xc1, 0xb7, 0xfd, 0x7d, 0x5e, 0x39, 0x06,
0x5f, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x51, 0xf0, 0xa5, 0x95, 0x02, 0x14, 0x00, 0x00,
}

View file

@ -83,6 +83,7 @@ extend google.protobuf.FileOptions {
optional bool enumdecl_all = 63031;
optional bool goproto_registration = 63032;
optional bool messagename_all = 63033;
}
extend google.protobuf.MessageOptions {
@ -115,6 +116,8 @@ extend google.protobuf.MessageOptions {
optional bool compare = 64029;
optional bool typedecl = 64030;
optional bool messagename = 64033;
}
extend google.protobuf.FieldOptions {

View file

@ -334,9 +334,6 @@ func HasExtensionsMap(file *google_protobuf.FileDescriptorProto, message *google
}
func HasUnrecognized(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
if IsProto3(file) {
return false
}
return proto.GetBoolExtension(message.Options, E_GoprotoUnrecognized, proto.GetBoolExtension(file.Options, E_GoprotoUnrecognizedAll, true))
}
@ -355,3 +352,7 @@ func HasCompare(file *google_protobuf.FileDescriptorProto, message *google_proto
func RegistersGolangProto(file *google_protobuf.FileDescriptorProto) bool {
return proto.GetBoolExtension(file.Options, E_GoprotoRegistration, false)
}
func HasMessageName(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Messagename, proto.GetBoolExtension(file.Options, E_MessagenameAll, false))
}

View file

@ -55,6 +55,8 @@ import (
"github.com/gogo/protobuf/types"
)
const secondInNanos = int64(time.Second / time.Nanosecond)
// Marshaler is a configurable object for converting between
// protocol buffer objects and a JSON representation for them.
type Marshaler struct {
@ -117,6 +119,14 @@ type JSONPBUnmarshaler interface {
// Marshal marshals a protocol buffer into JSON.
func (m *Marshaler) Marshal(out io.Writer, pb proto.Message) error {
v := reflect.ValueOf(pb)
if pb == nil || (v.Kind() == reflect.Ptr && v.IsNil()) {
return errors.New("Marshal called with nil")
}
// Check for unset required fields first.
if err := checkRequiredFields(pb); err != nil {
return err
}
writer := &errWriter{writer: out}
return m.marshalObject(writer, pb, "", "")
}
@ -189,13 +199,22 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU
// Any is a bit more involved.
return m.marshalAny(out, v, indent)
case "Duration":
// "Generated output always contains 3, 6, or 9 fractional digits,
// "Generated output always contains 0, 3, 6, or 9 fractional digits,
// depending on required precision."
s, ns := s.Field(0).Int(), s.Field(1).Int()
d := time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond
x := fmt.Sprintf("%.9f", d.Seconds())
if ns <= -secondInNanos || ns >= secondInNanos {
return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos)
}
if (s > 0 && ns < 0) || (s < 0 && ns > 0) {
return errors.New("signs of seconds and nanos do not match")
}
if s < 0 {
ns = -ns
}
x := fmt.Sprintf("%d.%09d", s, ns)
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, ".000")
out.write(`"`)
out.write(x)
out.write(`s"`)
@ -206,13 +225,17 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU
return m.marshalValue(out, &proto.Properties{}, s.Field(0), indent)
case "Timestamp":
// "RFC 3339, where generated output will always be Z-normalized
// and uses 3, 6 or 9 fractional digits."
// and uses 0, 3, 6 or 9 fractional digits."
s, ns := s.Field(0).Int(), s.Field(1).Int()
if ns < 0 || ns >= secondInNanos {
return fmt.Errorf("ns out of range [0, %v)", secondInNanos)
}
t := time.Unix(s, ns).UTC()
// time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits).
x := t.Format("2006-01-02T15:04:05.000000000")
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, ".000")
out.write(`"`)
out.write(x)
out.write(`Z"`)
@ -716,7 +739,10 @@ func (u *Unmarshaler) UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
if err := dec.Decode(&inputValue); err != nil {
return err
}
return u.unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil)
if err := u.unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil); err != nil {
return err
}
return checkRequiredFields(pb)
}
// Unmarshal unmarshals a JSON object stream into a protocol
@ -886,7 +912,7 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
return fmt.Errorf("bad ListValue: %v", err)
}
target.Field(0).Set(reflect.ValueOf(make([]*types.Value, len(s), len(s))))
target.Field(0).Set(reflect.ValueOf(make([]*types.Value, len(s))))
for i, sv := range s {
if err := u.unmarshalValue(target.Field(0).Index(i), sv, prop); err != nil {
return err
@ -1114,13 +1140,6 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
}
if mp != nil {
target.Set(reflect.MakeMap(targetType))
var keyprop, valprop *proto.Properties
if prop != nil {
// These could still be nil if the protobuf metadata is broken somehow.
// TODO: This won't work because the fields are unexported.
// We should probably just reparse them.
//keyprop, valprop = prop.mkeyprop, prop.mvalprop
}
for ks, raw := range mp {
// Unmarshal map key. The core json library already decoded the key into a
// string, so we handle that specially. Other types were quoted post-serialization.
@ -1129,7 +1148,8 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
k = reflect.ValueOf(ks)
} else {
k = reflect.New(targetType.Key()).Elem()
if err := u.unmarshalValue(k, json.RawMessage(ks), keyprop); err != nil {
// TODO: pass the correct Properties if needed.
if err := u.unmarshalValue(k, json.RawMessage(ks), nil); err != nil {
return err
}
}
@ -1140,7 +1160,8 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
// Unmarshal map value.
v := reflect.New(targetType.Elem()).Elem()
if err := u.unmarshalValue(v, raw, valprop); err != nil {
// TODO: pass the correct Properties if needed.
if err := u.unmarshalValue(v, raw, nil); err != nil {
return err
}
target.SetMapIndex(k, v)
@ -1226,3 +1247,140 @@ func (s mapKeys) Less(i, j int) bool {
}
return fmt.Sprint(s[i].Interface()) < fmt.Sprint(s[j].Interface())
}
// checkRequiredFields returns an error if any required field in the given proto message is not set.
// This function is used by both Marshal and Unmarshal. While required fields only exist in a
// proto2 message, a proto3 message can contain proto2 message(s).
func checkRequiredFields(pb proto.Message) error {
// Most well-known type messages do not contain required fields. The "Any" type may contain
// a message that has required fields.
//
// When an Any message is being marshaled, the code will invoked proto.Unmarshal on Any.Value
// field in order to transform that into JSON, and that should have returned an error if a
// required field is not set in the embedded message.
//
// When an Any message is being unmarshaled, the code will have invoked proto.Marshal on the
// embedded message to store the serialized message in Any.Value field, and that should have
// returned an error if a required field is not set.
if _, ok := pb.(isWkt); ok {
return nil
}
v := reflect.ValueOf(pb)
// Skip message if it is not a struct pointer.
if v.Kind() != reflect.Ptr {
return nil
}
v = v.Elem()
if v.Kind() != reflect.Struct {
return nil
}
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
sfield := v.Type().Field(i)
if sfield.PkgPath != "" {
// blank PkgPath means the field is exported; skip if not exported
continue
}
if strings.HasPrefix(sfield.Name, "XXX_") {
continue
}
// Oneof field is an interface implemented by wrapper structs containing the actual oneof
// field, i.e. an interface containing &T{real_value}.
if sfield.Tag.Get("protobuf_oneof") != "" {
if field.Kind() != reflect.Interface {
continue
}
v := field.Elem()
if v.Kind() != reflect.Ptr || v.IsNil() {
continue
}
v = v.Elem()
if v.Kind() != reflect.Struct || v.NumField() < 1 {
continue
}
field = v.Field(0)
sfield = v.Type().Field(0)
}
protoTag := sfield.Tag.Get("protobuf")
if protoTag == "" {
continue
}
var prop proto.Properties
prop.Init(sfield.Type, sfield.Name, protoTag, &sfield)
switch field.Kind() {
case reflect.Map:
if field.IsNil() {
continue
}
// Check each map value.
keys := field.MapKeys()
for _, k := range keys {
v := field.MapIndex(k)
if err := checkRequiredFieldsInValue(v); err != nil {
return err
}
}
case reflect.Slice:
// Handle non-repeated type, e.g. bytes.
if !prop.Repeated {
if prop.Required && field.IsNil() {
return fmt.Errorf("required field %q is not set", prop.Name)
}
continue
}
// Handle repeated type.
if field.IsNil() {
continue
}
// Check each slice item.
for i := 0; i < field.Len(); i++ {
v := field.Index(i)
if err := checkRequiredFieldsInValue(v); err != nil {
return err
}
}
case reflect.Ptr:
if field.IsNil() {
if prop.Required {
return fmt.Errorf("required field %q is not set", prop.Name)
}
continue
}
if err := checkRequiredFieldsInValue(field); err != nil {
return err
}
}
}
// Handle proto2 extensions.
for _, ext := range proto.RegisteredExtensions(pb) {
if !proto.HasExtension(pb, ext) {
continue
}
ep, err := proto.GetExtension(pb, ext)
if err != nil {
return err
}
err = checkRequiredFieldsInValue(reflect.ValueOf(ep))
if err != nil {
return err
}
}
return nil
}
func checkRequiredFieldsInValue(v reflect.Value) error {
if pm, ok := v.Interface().(proto.Message); ok {
return checkRequiredFields(pm)
}
return nil
}

View file

@ -403,7 +403,10 @@ var marshalingTests = []struct {
{"Any with message and indent", marshalerAllOptions, anySimple, anySimplePrettyJSON},
{"Any with WKT", marshaler, anyWellKnown, anyWellKnownJSON},
{"Any with WKT and indent", marshalerAllOptions, anyWellKnown, anyWellKnownPrettyJSON},
{"Duration", marshaler, &pb.KnownTypes{Dur: &types.Duration{Seconds: 3}}, `{"dur":"3.000s"}`},
{"Duration", marshaler, &pb.KnownTypes{Dur: &types.Duration{Seconds: 3}}, `{"dur":"3s"}`},
{"Duration", marshaler, &pb.KnownTypes{Dur: &types.Duration{Seconds: 3, Nanos: 1e6}}, `{"dur":"3.001s"}`},
{"Duration beyond float64 precision", marshaler, &pb.KnownTypes{Dur: &types.Duration{Seconds: 100000000, Nanos: 1}}, `{"dur":"100000000.000000001s"}`},
{"negative Duration", marshaler, &pb.KnownTypes{Dur: &types.Duration{Seconds: -123, Nanos: -456}}, `{"dur":"-123.000000456s"}`},
{"Struct", marshaler, &pb.KnownTypes{St: &types.Struct{
Fields: map[string]*types.Value{
"one": {Kind: &types.Value_StringValue{StringValue: "loneliest number"}},
@ -418,6 +421,7 @@ var marshalingTests = []struct {
{Kind: &types.Value_BoolValue{BoolValue: true}},
}}}, `{"lv":["x",null,3,true]}`},
{"Timestamp", marshaler, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: 14e8, Nanos: 21e6}}, `{"ts":"2014-05-13T16:53:20.021Z"}`},
{"Timestamp", marshaler, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: 14e8, Nanos: 0}}, `{"ts":"2014-05-13T16:53:20Z"}`},
{"number Value", marshaler, &pb.KnownTypes{Val: &types.Value{Kind: &types.Value_NumberValue{NumberValue: 1}}}, `{"val":1}`},
{"null Value", marshaler, &pb.KnownTypes{Val: &types.Value{Kind: &types.Value_NullValue{NullValue: types.NULL_VALUE}}}, `{"val":null}`},
{"string number value", marshaler, &pb.KnownTypes{Val: &types.Value{Kind: &types.Value_StringValue{StringValue: "9223372036854775807"}}}, `{"val":"9223372036854775807"}`},
@ -445,6 +449,8 @@ var marshalingTests = []struct {
{"BoolValue", marshaler, &pb.KnownTypes{Bool: &types.BoolValue{Value: true}}, `{"bool":true}`},
{"StringValue", marshaler, &pb.KnownTypes{Str: &types.StringValue{Value: "plush"}}, `{"str":"plush"}`},
{"BytesValue", marshaler, &pb.KnownTypes{Bytes: &types.BytesValue{Value: []byte("wow")}}, `{"bytes":"d293"}`},
{"required", marshaler, &pb.MsgWithRequired{Str: proto.String("hello")}, `{"str":"hello"}`},
{"required bytes", marshaler, &pb.MsgWithRequiredBytes{Byts: []byte{}}, `{"byts":""}`},
}
func TestMarshaling(t *testing.T) {
@ -458,6 +464,40 @@ func TestMarshaling(t *testing.T) {
}
}
func TestMarshalingNil(t *testing.T) {
var msg *pb.Simple
m := &Marshaler{}
if _, err := m.MarshalToString(msg); err == nil {
t.Errorf("mashaling nil returned no error")
}
}
func TestMarshalIllegalTime(t *testing.T) {
tests := []struct {
pb proto.Message
fail bool
}{
{&pb.KnownTypes{Dur: &types.Duration{Seconds: 1, Nanos: 0}}, false},
{&pb.KnownTypes{Dur: &types.Duration{Seconds: -1, Nanos: 0}}, false},
{&pb.KnownTypes{Dur: &types.Duration{Seconds: 1, Nanos: -1}}, true},
{&pb.KnownTypes{Dur: &types.Duration{Seconds: -1, Nanos: 1}}, true},
{&pb.KnownTypes{Dur: &types.Duration{Seconds: 1, Nanos: 1000000000}}, true},
{&pb.KnownTypes{Dur: &types.Duration{Seconds: -1, Nanos: -1000000000}}, true},
{&pb.KnownTypes{Ts: &types.Timestamp{Seconds: 1, Nanos: 1}}, false},
{&pb.KnownTypes{Ts: &types.Timestamp{Seconds: 1, Nanos: -1}}, true},
{&pb.KnownTypes{Ts: &types.Timestamp{Seconds: 1, Nanos: 1000000000}}, true},
}
for _, tt := range tests {
_, err := marshaler.MarshalToString(tt.pb)
if err == nil && tt.fail {
t.Errorf("marshaler.MarshalToString(%v) = _, <nil>; want _, <non-nil>", tt.pb)
}
if err != nil && !tt.fail {
t.Errorf("marshaler.MarshalToString(%v) = _, %v; want _, <nil>", tt.pb, err)
}
}
}
func TestMarshalJSONPBMarshaler(t *testing.T) {
rawJson := `{ "foo": "bar", "baz": [0, 1, 2, 3] }`
msg := dynamicMessage{rawJson: rawJson}
@ -488,6 +528,104 @@ func TestMarshalAnyJSONPBMarshaler(t *testing.T) {
}
}
func TestMarshalWithCustomValidation(t *testing.T) {
msg := dynamicMessage{rawJson: `{ "foo": "bar", "baz": [0, 1, 2, 3] }`, dummy: &dynamicMessage{}}
js, err := new(Marshaler).MarshalToString(&msg)
if err != nil {
t.Errorf("an unexpected error occurred when marshalling to json: %v", err)
}
err = Unmarshal(strings.NewReader(js), &msg)
if err != nil {
t.Errorf("an unexpected error occurred when unmarshalling from json: %v", err)
}
}
// Test marshaling message containing unset required fields should produce error.
func TestMarshalUnsetRequiredFields(t *testing.T) {
msgExt := &pb.Real{}
proto.SetExtension(msgExt, pb.E_Extm, &pb.MsgWithRequired{})
tests := []struct {
desc string
marshaler *Marshaler
pb proto.Message
}{
{
desc: "direct required field",
marshaler: &Marshaler{},
pb: &pb.MsgWithRequired{},
},
{
desc: "direct required field + emit defaults",
marshaler: &Marshaler{EmitDefaults: true},
pb: &pb.MsgWithRequired{},
},
{
desc: "indirect required field",
marshaler: &Marshaler{},
pb: &pb.MsgWithIndirectRequired{Subm: &pb.MsgWithRequired{}},
},
{
desc: "indirect required field + emit defaults",
marshaler: &Marshaler{EmitDefaults: true},
pb: &pb.MsgWithIndirectRequired{Subm: &pb.MsgWithRequired{}},
},
{
desc: "direct required wkt field",
marshaler: &Marshaler{},
pb: &pb.MsgWithRequiredWKT{},
},
{
desc: "direct required wkt field + emit defaults",
marshaler: &Marshaler{EmitDefaults: true},
pb: &pb.MsgWithRequiredWKT{},
},
{
desc: "direct required bytes field",
marshaler: &Marshaler{},
pb: &pb.MsgWithRequiredBytes{},
},
{
desc: "required in map value",
marshaler: &Marshaler{},
pb: &pb.MsgWithIndirectRequired{
MapField: map[string]*pb.MsgWithRequired{
"key": {},
},
},
},
{
desc: "required in repeated item",
marshaler: &Marshaler{},
pb: &pb.MsgWithIndirectRequired{
SliceField: []*pb.MsgWithRequired{
{Str: proto.String("hello")},
{},
},
},
},
{
desc: "required inside oneof",
marshaler: &Marshaler{},
pb: &pb.MsgWithOneof{
Union: &pb.MsgWithOneof_MsgWithRequired{MsgWithRequired: &pb.MsgWithRequired{}},
},
},
{
desc: "required inside extension",
marshaler: &Marshaler{},
pb: msgExt,
},
}
for _, tc := range tests {
if _, err := tc.marshaler.MarshalToString(tc.pb); err == nil {
t.Errorf("%s: expecting error in marshaling with unset required fields %+v", tc.desc, tc.pb)
}
}
}
var unmarshalingTests = []struct {
desc string
unmarshaler Unmarshaler
@ -548,8 +686,10 @@ var unmarshalingTests = []struct {
{"orig_name input", Unmarshaler{}, `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
{"camelName input", Unmarshaler{}, `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
{"Duration", Unmarshaler{}, `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &types.Duration{Seconds: 3}}},
{"Duration", Unmarshaler{}, `{"dur":"4s"}`, &pb.KnownTypes{Dur: &types.Duration{Seconds: 4}}},
{"null Duration", Unmarshaler{}, `{"dur":null}`, &pb.KnownTypes{Dur: nil}},
{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: 14e8, Nanos: 21e6}}},
{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20Z"}`, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: 14e8, Nanos: 0}}},
{"PreEpochTimestamp", Unmarshaler{}, `{"ts":"1969-12-31T23:59:58.999999995Z"}`, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: -2, Nanos: 999999995}}},
{"ZeroTimeTimestamp", Unmarshaler{}, `{"ts":"0001-01-01T00:00:00Z"}`, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: -62135596800, Nanos: 0}}},
{"null Timestamp", Unmarshaler{}, `{"ts":null}`, &pb.KnownTypes{Ts: nil}},
@ -617,6 +757,8 @@ var unmarshalingTests = []struct {
{"null BoolValue", Unmarshaler{}, `{"bool":null}`, &pb.KnownTypes{Bool: nil}},
{"null StringValue", Unmarshaler{}, `{"str":null}`, &pb.KnownTypes{Str: nil}},
{"null BytesValue", Unmarshaler{}, `{"bytes":null}`, &pb.KnownTypes{Bytes: nil}},
{"required", Unmarshaler{}, `{"str":"hello"}`, &pb.MsgWithRequired{Str: proto.String("hello")}},
{"required bytes", Unmarshaler{}, `{"byts": []}`, &pb.MsgWithRequiredBytes{Byts: []byte{}}},
}
func TestUnmarshaling(t *testing.T) {
@ -815,7 +957,7 @@ func TestUnmarshalAnyJSONPBUnmarshaler(t *testing.T) {
}
if !proto.Equal(&got, &want) {
t.Errorf("message contents not set correctly after unmarshalling JSON: got %s, wanted %s", got, want)
t.Errorf("message contents not set correctly after unmarshalling JSON: got %v, wanted %v", got, want)
}
}
@ -867,6 +1009,10 @@ func (s *stringField) UnmarshalJSONPB(jum *Unmarshaler, js []byte) error {
// It provides implementations of JSONPBMarshaler and JSONPBUnmarshaler for JSON support.
type dynamicMessage struct {
rawJson string `protobuf:"bytes,1,opt,name=rawJson"`
// an unexported nested message is present just to ensure that it
// won't result in a panic (see issue #509)
dummy *dynamicMessage `protobuf:"bytes,2,opt,name=dummy"`
}
func (m *dynamicMessage) Reset() {
@ -888,3 +1034,109 @@ func (m *dynamicMessage) UnmarshalJSONPB(jum *Unmarshaler, js []byte) error {
m.rawJson = string(js)
return nil
}
// Test unmarshaling message containing unset required fields should produce error.
func TestUnmarshalUnsetRequiredFields(t *testing.T) {
tests := []struct {
desc string
pb proto.Message
json string
}{
{
desc: "direct required field missing",
pb: &pb.MsgWithRequired{},
json: `{}`,
},
{
desc: "direct required field set to null",
pb: &pb.MsgWithRequired{},
json: `{"str": null}`,
},
{
desc: "indirect required field missing",
pb: &pb.MsgWithIndirectRequired{},
json: `{"subm": {}}`,
},
{
desc: "indirect required field set to null",
pb: &pb.MsgWithIndirectRequired{},
json: `{"subm": {"str": null}}`,
},
{
desc: "direct required bytes field missing",
pb: &pb.MsgWithRequiredBytes{},
json: `{}`,
},
{
desc: "direct required bytes field set to null",
pb: &pb.MsgWithRequiredBytes{},
json: `{"byts": null}`,
},
{
desc: "direct required wkt field missing",
pb: &pb.MsgWithRequiredWKT{},
json: `{}`,
},
{
desc: "direct required wkt field set to null",
pb: &pb.MsgWithRequiredWKT{},
json: `{"str": null}`,
},
{
desc: "any containing message with required field set to null",
pb: &pb.KnownTypes{},
json: `{"an": {"@type": "example.com/jsonpb.MsgWithRequired", "str": null}}`,
},
{
desc: "any containing message with missing required field",
pb: &pb.KnownTypes{},
json: `{"an": {"@type": "example.com/jsonpb.MsgWithRequired"}}`,
},
{
desc: "missing required in map value",
pb: &pb.MsgWithIndirectRequired{},
json: `{"map_field": {"a": {}, "b": {"str": "hi"}}}`,
},
{
desc: "required in map value set to null",
pb: &pb.MsgWithIndirectRequired{},
json: `{"map_field": {"a": {"str": "hello"}, "b": {"str": null}}}`,
},
{
desc: "missing required in slice item",
pb: &pb.MsgWithIndirectRequired{},
json: `{"slice_field": [{}, {"str": "hi"}]}`,
},
{
desc: "required in slice item set to null",
pb: &pb.MsgWithIndirectRequired{},
json: `{"slice_field": [{"str": "hello"}, {"str": null}]}`,
},
{
desc: "required inside oneof missing",
pb: &pb.MsgWithOneof{},
json: `{"msgWithRequired": {}}`,
},
{
desc: "required inside oneof set to null",
pb: &pb.MsgWithOneof{},
json: `{"msgWithRequired": {"str": null}}`,
},
{
desc: "required field in extension missing",
pb: &pb.Real{},
json: `{"[jsonpb.extm]":{}}`,
},
{
desc: "required field in extension set to null",
pb: &pb.Real{},
json: `{"[jsonpb.extm]":{"str": null}}`,
},
}
for _, tc := range tests {
if err := UnmarshalString(tc.json, tc.pb); err == nil {
t.Errorf("%s: expecting error in unmarshaling with unset required fields %s", tc.desc, tc.json)
}
}
}

View file

@ -1,29 +1,6 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: more_test_objects.proto
/*
Package jsonpb is a generated protocol buffer package.
It is generated from these files:
more_test_objects.proto
test_objects.proto
It has these top-level messages:
Simple3
SimpleSlice3
SimpleMap3
SimpleNull3
Mappy
Simple
NonFinites
Repeats
Widget
Maps
MsgWithOneof
Real
Complex
KnownTypes
*/
package jsonpb
import proto "github.com/gogo/protobuf/proto"
@ -63,16 +40,40 @@ var Numeral_value = map[string]int32{
func (x Numeral) String() string {
return proto.EnumName(Numeral_name, int32(x))
}
func (Numeral) EnumDescriptor() ([]byte, []int) { return fileDescriptorMoreTestObjects, []int{0} }
type Simple3 struct {
Dub float64 `protobuf:"fixed64,1,opt,name=dub,proto3" json:"dub,omitempty"`
func (Numeral) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_more_test_objects_bef0d79b901f4c4a, []int{0}
}
func (m *Simple3) Reset() { *m = Simple3{} }
func (m *Simple3) String() string { return proto.CompactTextString(m) }
func (*Simple3) ProtoMessage() {}
func (*Simple3) Descriptor() ([]byte, []int) { return fileDescriptorMoreTestObjects, []int{0} }
type Simple3 struct {
Dub float64 `protobuf:"fixed64,1,opt,name=dub,proto3" json:"dub,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Simple3) Reset() { *m = Simple3{} }
func (m *Simple3) String() string { return proto.CompactTextString(m) }
func (*Simple3) ProtoMessage() {}
func (*Simple3) Descriptor() ([]byte, []int) {
return fileDescriptor_more_test_objects_bef0d79b901f4c4a, []int{0}
}
func (m *Simple3) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Simple3.Unmarshal(m, b)
}
func (m *Simple3) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Simple3.Marshal(b, m, deterministic)
}
func (dst *Simple3) XXX_Merge(src proto.Message) {
xxx_messageInfo_Simple3.Merge(dst, src)
}
func (m *Simple3) XXX_Size() int {
return xxx_messageInfo_Simple3.Size(m)
}
func (m *Simple3) XXX_DiscardUnknown() {
xxx_messageInfo_Simple3.DiscardUnknown(m)
}
var xxx_messageInfo_Simple3 proto.InternalMessageInfo
func (m *Simple3) GetDub() float64 {
if m != nil {
@ -82,13 +83,35 @@ func (m *Simple3) GetDub() float64 {
}
type SimpleSlice3 struct {
Slices []string `protobuf:"bytes,1,rep,name=slices" json:"slices,omitempty"`
Slices []string `protobuf:"bytes,1,rep,name=slices" json:"slices,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SimpleSlice3) Reset() { *m = SimpleSlice3{} }
func (m *SimpleSlice3) String() string { return proto.CompactTextString(m) }
func (*SimpleSlice3) ProtoMessage() {}
func (*SimpleSlice3) Descriptor() ([]byte, []int) { return fileDescriptorMoreTestObjects, []int{1} }
func (m *SimpleSlice3) Reset() { *m = SimpleSlice3{} }
func (m *SimpleSlice3) String() string { return proto.CompactTextString(m) }
func (*SimpleSlice3) ProtoMessage() {}
func (*SimpleSlice3) Descriptor() ([]byte, []int) {
return fileDescriptor_more_test_objects_bef0d79b901f4c4a, []int{1}
}
func (m *SimpleSlice3) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SimpleSlice3.Unmarshal(m, b)
}
func (m *SimpleSlice3) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SimpleSlice3.Marshal(b, m, deterministic)
}
func (dst *SimpleSlice3) XXX_Merge(src proto.Message) {
xxx_messageInfo_SimpleSlice3.Merge(dst, src)
}
func (m *SimpleSlice3) XXX_Size() int {
return xxx_messageInfo_SimpleSlice3.Size(m)
}
func (m *SimpleSlice3) XXX_DiscardUnknown() {
xxx_messageInfo_SimpleSlice3.DiscardUnknown(m)
}
var xxx_messageInfo_SimpleSlice3 proto.InternalMessageInfo
func (m *SimpleSlice3) GetSlices() []string {
if m != nil {
@ -98,13 +121,35 @@ func (m *SimpleSlice3) GetSlices() []string {
}
type SimpleMap3 struct {
Stringy map[string]string `protobuf:"bytes,1,rep,name=stringy" json:"stringy,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Stringy map[string]string `protobuf:"bytes,1,rep,name=stringy" json:"stringy,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SimpleMap3) Reset() { *m = SimpleMap3{} }
func (m *SimpleMap3) String() string { return proto.CompactTextString(m) }
func (*SimpleMap3) ProtoMessage() {}
func (*SimpleMap3) Descriptor() ([]byte, []int) { return fileDescriptorMoreTestObjects, []int{2} }
func (m *SimpleMap3) Reset() { *m = SimpleMap3{} }
func (m *SimpleMap3) String() string { return proto.CompactTextString(m) }
func (*SimpleMap3) ProtoMessage() {}
func (*SimpleMap3) Descriptor() ([]byte, []int) {
return fileDescriptor_more_test_objects_bef0d79b901f4c4a, []int{2}
}
func (m *SimpleMap3) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SimpleMap3.Unmarshal(m, b)
}
func (m *SimpleMap3) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SimpleMap3.Marshal(b, m, deterministic)
}
func (dst *SimpleMap3) XXX_Merge(src proto.Message) {
xxx_messageInfo_SimpleMap3.Merge(dst, src)
}
func (m *SimpleMap3) XXX_Size() int {
return xxx_messageInfo_SimpleMap3.Size(m)
}
func (m *SimpleMap3) XXX_DiscardUnknown() {
xxx_messageInfo_SimpleMap3.DiscardUnknown(m)
}
var xxx_messageInfo_SimpleMap3 proto.InternalMessageInfo
func (m *SimpleMap3) GetStringy() map[string]string {
if m != nil {
@ -114,13 +159,35 @@ func (m *SimpleMap3) GetStringy() map[string]string {
}
type SimpleNull3 struct {
Simple *Simple3 `protobuf:"bytes,1,opt,name=simple" json:"simple,omitempty"`
Simple *Simple3 `protobuf:"bytes,1,opt,name=simple" json:"simple,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SimpleNull3) Reset() { *m = SimpleNull3{} }
func (m *SimpleNull3) String() string { return proto.CompactTextString(m) }
func (*SimpleNull3) ProtoMessage() {}
func (*SimpleNull3) Descriptor() ([]byte, []int) { return fileDescriptorMoreTestObjects, []int{3} }
func (m *SimpleNull3) Reset() { *m = SimpleNull3{} }
func (m *SimpleNull3) String() string { return proto.CompactTextString(m) }
func (*SimpleNull3) ProtoMessage() {}
func (*SimpleNull3) Descriptor() ([]byte, []int) {
return fileDescriptor_more_test_objects_bef0d79b901f4c4a, []int{3}
}
func (m *SimpleNull3) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SimpleNull3.Unmarshal(m, b)
}
func (m *SimpleNull3) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SimpleNull3.Marshal(b, m, deterministic)
}
func (dst *SimpleNull3) XXX_Merge(src proto.Message) {
xxx_messageInfo_SimpleNull3.Merge(dst, src)
}
func (m *SimpleNull3) XXX_Size() int {
return xxx_messageInfo_SimpleNull3.Size(m)
}
func (m *SimpleNull3) XXX_DiscardUnknown() {
xxx_messageInfo_SimpleNull3.DiscardUnknown(m)
}
var xxx_messageInfo_SimpleNull3 proto.InternalMessageInfo
func (m *SimpleNull3) GetSimple() *Simple3 {
if m != nil {
@ -130,22 +197,44 @@ func (m *SimpleNull3) GetSimple() *Simple3 {
}
type Mappy struct {
Nummy map[int64]int32 `protobuf:"bytes,1,rep,name=nummy" json:"nummy,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
Strry map[string]string `protobuf:"bytes,2,rep,name=strry" json:"strry,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Objjy map[int32]*Simple3 `protobuf:"bytes,3,rep,name=objjy" json:"objjy,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
Buggy map[int64]string `protobuf:"bytes,4,rep,name=buggy" json:"buggy,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Booly map[bool]bool `protobuf:"bytes,5,rep,name=booly" json:"booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
Enumy map[string]Numeral `protobuf:"bytes,6,rep,name=enumy" json:"enumy,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3,enum=jsonpb.Numeral"`
S32Booly map[int32]bool `protobuf:"bytes,7,rep,name=s32booly" json:"s32booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
S64Booly map[int64]bool `protobuf:"bytes,8,rep,name=s64booly" json:"s64booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
U32Booly map[uint32]bool `protobuf:"bytes,9,rep,name=u32booly" json:"u32booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
U64Booly map[uint64]bool `protobuf:"bytes,10,rep,name=u64booly" json:"u64booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
Nummy map[int64]int32 `protobuf:"bytes,1,rep,name=nummy" json:"nummy,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
Strry map[string]string `protobuf:"bytes,2,rep,name=strry" json:"strry,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Objjy map[int32]*Simple3 `protobuf:"bytes,3,rep,name=objjy" json:"objjy,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
Buggy map[int64]string `protobuf:"bytes,4,rep,name=buggy" json:"buggy,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Booly map[bool]bool `protobuf:"bytes,5,rep,name=booly" json:"booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
Enumy map[string]Numeral `protobuf:"bytes,6,rep,name=enumy" json:"enumy,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3,enum=jsonpb.Numeral"`
S32Booly map[int32]bool `protobuf:"bytes,7,rep,name=s32booly" json:"s32booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
S64Booly map[int64]bool `protobuf:"bytes,8,rep,name=s64booly" json:"s64booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
U32Booly map[uint32]bool `protobuf:"bytes,9,rep,name=u32booly" json:"u32booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
U64Booly map[uint64]bool `protobuf:"bytes,10,rep,name=u64booly" json:"u64booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Mappy) Reset() { *m = Mappy{} }
func (m *Mappy) String() string { return proto.CompactTextString(m) }
func (*Mappy) ProtoMessage() {}
func (*Mappy) Descriptor() ([]byte, []int) { return fileDescriptorMoreTestObjects, []int{4} }
func (m *Mappy) Reset() { *m = Mappy{} }
func (m *Mappy) String() string { return proto.CompactTextString(m) }
func (*Mappy) ProtoMessage() {}
func (*Mappy) Descriptor() ([]byte, []int) {
return fileDescriptor_more_test_objects_bef0d79b901f4c4a, []int{4}
}
func (m *Mappy) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Mappy.Unmarshal(m, b)
}
func (m *Mappy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Mappy.Marshal(b, m, deterministic)
}
func (dst *Mappy) XXX_Merge(src proto.Message) {
xxx_messageInfo_Mappy.Merge(dst, src)
}
func (m *Mappy) XXX_Size() int {
return xxx_messageInfo_Mappy.Size(m)
}
func (m *Mappy) XXX_DiscardUnknown() {
xxx_messageInfo_Mappy.DiscardUnknown(m)
}
var xxx_messageInfo_Mappy proto.InternalMessageInfo
func (m *Mappy) GetNummy() map[int64]int32 {
if m != nil {
@ -221,14 +310,27 @@ func init() {
proto.RegisterType((*Simple3)(nil), "jsonpb.Simple3")
proto.RegisterType((*SimpleSlice3)(nil), "jsonpb.SimpleSlice3")
proto.RegisterType((*SimpleMap3)(nil), "jsonpb.SimpleMap3")
proto.RegisterMapType((map[string]string)(nil), "jsonpb.SimpleMap3.StringyEntry")
proto.RegisterType((*SimpleNull3)(nil), "jsonpb.SimpleNull3")
proto.RegisterType((*Mappy)(nil), "jsonpb.Mappy")
proto.RegisterMapType((map[bool]bool)(nil), "jsonpb.Mappy.BoolyEntry")
proto.RegisterMapType((map[int64]string)(nil), "jsonpb.Mappy.BuggyEntry")
proto.RegisterMapType((map[string]Numeral)(nil), "jsonpb.Mappy.EnumyEntry")
proto.RegisterMapType((map[int64]int32)(nil), "jsonpb.Mappy.NummyEntry")
proto.RegisterMapType((map[int32]*Simple3)(nil), "jsonpb.Mappy.ObjjyEntry")
proto.RegisterMapType((map[int32]bool)(nil), "jsonpb.Mappy.S32boolyEntry")
proto.RegisterMapType((map[int64]bool)(nil), "jsonpb.Mappy.S64boolyEntry")
proto.RegisterMapType((map[string]string)(nil), "jsonpb.Mappy.StrryEntry")
proto.RegisterMapType((map[uint32]bool)(nil), "jsonpb.Mappy.U32boolyEntry")
proto.RegisterMapType((map[uint64]bool)(nil), "jsonpb.Mappy.U64boolyEntry")
proto.RegisterEnum("jsonpb.Numeral", Numeral_name, Numeral_value)
}
func init() { proto.RegisterFile("more_test_objects.proto", fileDescriptorMoreTestObjects) }
func init() {
proto.RegisterFile("more_test_objects.proto", fileDescriptor_more_test_objects_bef0d79b901f4c4a)
}
var fileDescriptorMoreTestObjects = []byte{
var fileDescriptor_more_test_objects_bef0d79b901f4c4a = []byte{
// 526 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0xdd, 0x6b, 0xdb, 0x3c,
0x14, 0x87, 0x5f, 0x27, 0xf5, 0xd7, 0x49, 0xfb, 0x2e, 0x88, 0xb1, 0x99, 0xf4, 0x62, 0xc5, 0xb0,

File diff suppressed because it is too large Load diff

View file

@ -111,6 +111,7 @@ message MsgWithOneof {
int64 salary = 2;
string Country = 3;
string home_address = 4;
MsgWithRequired msg_with_required = 5;
}
}
@ -149,3 +150,26 @@ message KnownTypes {
optional google.protobuf.StringValue str = 10;
optional google.protobuf.BytesValue bytes = 11;
}
// Test messages for marshaling/unmarshaling required fields.
message MsgWithRequired {
required string str = 1;
}
message MsgWithIndirectRequired {
optional MsgWithRequired subm = 1;
map<string, MsgWithRequired> map_field = 2;
repeated MsgWithRequired slice_field = 3;
}
message MsgWithRequiredBytes {
required bytes byts = 1;
}
message MsgWithRequiredWKT {
required google.protobuf.StringValue str = 1;
}
extend Real {
optional MsgWithRequired extm = 125;
}

View file

@ -47,9 +47,10 @@ package embedcheck
import (
"fmt"
"os"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"os"
)
type plugin struct {
@ -163,7 +164,7 @@ func (p *plugin) checkOverwrite(message *generator.Descriptor, enablers map[stri
desc := p.ObjectNamed(field.GetTypeName())
msg := desc.(*generator.Descriptor)
for errStr, enabled := range enablers {
if enabled(msg.File(), msg.DescriptorProto) {
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)
}
}

View file

@ -157,7 +157,7 @@ func (p *gostring) Generate(file *generator.FileDescriptor) {
continue
}
p.atleastOne = true
packageName := file.PackageName()
packageName := file.GoPackageName()
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (this *`, ccTypeName, `) GoString() string {`)

View file

@ -534,7 +534,7 @@ func (p *plugin) Generate(file *generator.FileDescriptor) {
p.P(`func NewPopulated`, ccTypeName, `(r randy`, p.localName, `, easy bool) *`, ccTypeName, ` {`)
p.In()
p.P(`this := &`, ccTypeName, `{}`)
if gogoproto.IsUnion(message.File(), message.DescriptorProto) && len(message.Field) > 0 {
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

View file

@ -184,7 +184,7 @@ func (p *union) Generate(file *generator.FileDescriptor) {
goTyp, _ := p.GoType(message, field)
obj := p.ObjectNamed(field.GetTypeName()).(*generator.Descriptor)
if gogoproto.IsUnion(obj.File(), obj.DescriptorProto) {
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()

View file

@ -38,6 +38,6 @@ test: install generate-test-pbs
generate-test-pbs:
make install
make -C testdata
protoc-min-version --version="3.0.0" --proto_path=.:../../../../:../protobuf --gogo_out=Mtestdata/test.proto=github.com/gogo/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types:. proto3_proto/proto3.proto
make -C test_proto
make -C proto3_proto
make

View file

@ -41,11 +41,12 @@ import (
"reflect"
"runtime/debug"
"strings"
"sync"
"testing"
"time"
. "github.com/gogo/protobuf/proto"
. "github.com/gogo/protobuf/proto/testdata"
. "github.com/gogo/protobuf/proto/test_proto"
)
var globalO *Buffer
@ -114,6 +115,8 @@ func initGoTest(setdefaults bool) *GoTest {
pb.F_BytesDefaulted = Default_GoTest_F_BytesDefaulted
pb.F_Sint32Defaulted = Int32(Default_GoTest_F_Sint32Defaulted)
pb.F_Sint64Defaulted = Int64(Default_GoTest_F_Sint64Defaulted)
pb.F_Sfixed32Defaulted = Int32(Default_GoTest_F_Sfixed32Defaulted)
pb.F_Sfixed64Defaulted = Int64(Default_GoTest_F_Sfixed64Defaulted)
}
pb.Kind = GoTest_TIME.Enum()
@ -131,135 +134,13 @@ func initGoTest(setdefaults bool) *GoTest {
pb.F_BytesRequired = []byte("bytes")
pb.F_Sint32Required = Int32(-32)
pb.F_Sint64Required = Int64(-64)
pb.F_Sfixed32Required = Int32(-32)
pb.F_Sfixed64Required = Int64(-64)
pb.Requiredgroup = initGoTest_RequiredGroup()
return pb
}
func fail(msg string, b *bytes.Buffer, s string, t *testing.T) {
data := b.Bytes()
ld := len(data)
ls := len(s) / 2
fmt.Printf("fail %s ld=%d ls=%d\n", msg, ld, ls)
// find the interesting spot - n
n := ls
if ld < ls {
n = ld
}
j := 0
for i := 0; i < n; i++ {
bs := hex(s[j])*16 + hex(s[j+1])
j += 2
if data[i] == bs {
continue
}
n = i
break
}
l := n - 10
if l < 0 {
l = 0
}
h := n + 10
// find the interesting spot - n
fmt.Printf("is[%d]:", l)
for i := l; i < h; i++ {
if i >= ld {
fmt.Printf(" --")
continue
}
fmt.Printf(" %.2x", data[i])
}
fmt.Printf("\n")
fmt.Printf("sb[%d]:", l)
for i := l; i < h; i++ {
if i >= ls {
fmt.Printf(" --")
continue
}
bs := hex(s[j])*16 + hex(s[j+1])
j += 2
fmt.Printf(" %.2x", bs)
}
fmt.Printf("\n")
t.Fail()
// t.Errorf("%s: \ngood: %s\nbad: %x", msg, s, b.Bytes())
// Print the output in a partially-decoded format; can
// be helpful when updating the test. It produces the output
// that is pasted, with minor edits, into the argument to verify().
// data := b.Bytes()
// nesting := 0
// for b.Len() > 0 {
// start := len(data) - b.Len()
// var u uint64
// u, err := DecodeVarint(b)
// if err != nil {
// fmt.Printf("decode error on varint:", err)
// return
// }
// wire := u & 0x7
// tag := u >> 3
// switch wire {
// case WireVarint:
// v, err := DecodeVarint(b)
// if err != nil {
// fmt.Printf("decode error on varint:", err)
// return
// }
// fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n",
// data[start:len(data)-b.Len()], tag, wire, v)
// case WireFixed32:
// v, err := DecodeFixed32(b)
// if err != nil {
// fmt.Printf("decode error on fixed32:", err)
// return
// }
// fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n",
// data[start:len(data)-b.Len()], tag, wire, v)
// case WireFixed64:
// v, err := DecodeFixed64(b)
// if err != nil {
// fmt.Printf("decode error on fixed64:", err)
// return
// }
// fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n",
// data[start:len(data)-b.Len()], tag, wire, v)
// case WireBytes:
// nb, err := DecodeVarint(b)
// if err != nil {
// fmt.Printf("decode error on bytes:", err)
// return
// }
// after_tag := len(data) - b.Len()
// str := make([]byte, nb)
// _, err = b.Read(str)
// if err != nil {
// fmt.Printf("decode error on bytes:", err)
// return
// }
// fmt.Printf("\t\t\"%x\" \"%x\" // field %d, encoding %d (FIELD)\n",
// data[start:after_tag], str, tag, wire)
// case WireStartGroup:
// nesting++
// fmt.Printf("\t\t\"%x\"\t\t// start group field %d level %d\n",
// data[start:len(data)-b.Len()], tag, nesting)
// case WireEndGroup:
// fmt.Printf("\t\t\"%x\"\t\t// end group field %d level %d\n",
// data[start:len(data)-b.Len()], tag, nesting)
// nesting--
// default:
// fmt.Printf("unrecognized wire type %d\n", wire)
// return
// }
// }
}
func hex(c uint8) uint8 {
if '0' <= c && c <= '9' {
return c - '0'
@ -482,6 +363,48 @@ func TestMarshalerEncoding(t *testing.T) {
}
}
// Ensure that Buffer.Marshal uses O(N) memory for N messages
func TestBufferMarshalAllocs(t *testing.T) {
value := &OtherMessage{Key: Int64(1)}
msg := &MyMessage{Count: Int32(1), Others: []*OtherMessage{value}}
reallocSize := func(t *testing.T, items int, prealloc int) (int64, int64) {
var b Buffer
b.SetBuf(make([]byte, 0, prealloc))
var allocSpace int64
prevCap := cap(b.Bytes())
for i := 0; i < items; i++ {
err := b.Marshal(msg)
if err != nil {
t.Errorf("Marshal err = %q", err)
break
}
if c := cap(b.Bytes()); prevCap != c {
allocSpace += int64(c)
prevCap = c
}
}
needSpace := int64(len(b.Bytes()))
return allocSpace, needSpace
}
for _, prealloc := range []int{0, 100, 10000} {
for _, items := range []int{1, 2, 5, 10, 20, 50, 100, 200, 500, 1000} {
runtimeSpace, need := reallocSize(t, items, prealloc)
totalSpace := int64(prealloc) + runtimeSpace
runtimeRatio := float64(runtimeSpace) / float64(need)
totalRatio := float64(totalSpace) / float64(need)
if totalRatio < 1 || runtimeRatio > 4 {
t.Errorf("needed %dB, allocated %dB total (ratio %.1f), allocated %dB at runtime (ratio %.1f)",
need, totalSpace, totalRatio, runtimeSpace, runtimeRatio)
}
}
}
}
// Simple tests for bytes
func TestBytesPrimitives(t *testing.T) {
o := old()
@ -519,7 +442,7 @@ func TestRequiredBit(t *testing.T) {
err := o.Marshal(pb)
if err == nil {
t.Error("did not catch missing required fields")
} else if strings.Index(err.Error(), "Kind") < 0 {
} else if !strings.Contains(err.Error(), "Kind") {
t.Error("wrong error type:", err)
}
}
@ -612,7 +535,9 @@ func TestEncodeDecode1(t *testing.T) {
"b404"+ // field 70, encoding 4, end group
"aa0605"+"6279746573"+ // field 101, encoding 2, string "bytes"
"b0063f"+ // field 102, encoding 0, 0x3f zigzag32
"b8067f") // field 103, encoding 0, 0x7f zigzag64
"b8067f"+ // field 103, encoding 0, 0x7f zigzag64
"c506e0ffffff"+ // field 104, encoding 5, -32 fixed32
"c906c0ffffffffffffff") // field 105, encoding 1, -64 fixed64
}
// All required fields set, defaults provided.
@ -647,9 +572,13 @@ func TestEncodeDecode2(t *testing.T) {
"aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes"
"b0063f"+ // field 102, encoding 0, 0x3f zigzag32
"b8067f"+ // field 103, encoding 0, 0x7f zigzag64
"c506e0ffffff"+ // field 104, encoding 5, -32 fixed32
"c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64
"8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose"
"90193f"+ // field 402, encoding 0, value 63
"98197f") // field 403, encoding 0, value 127
"98197f"+ // field 403, encoding 0, value 127
"a519e0ffffff"+ // field 404, encoding 5, -32 fixed32
"a919c0ffffffffffffff") // field 405, encoding 1, -64 fixed64
}
@ -669,6 +598,8 @@ func TestEncodeDecode3(t *testing.T) {
pb.F_BytesDefaulted = []byte("Bignose")
pb.F_Sint32Defaulted = Int32(-32)
pb.F_Sint64Defaulted = Int64(-64)
pb.F_Sfixed32Defaulted = Int32(-32)
pb.F_Sfixed64Defaulted = Int64(-64)
overify(t, pb,
"0807"+ // field 1, encoding 0, value 7
@ -699,9 +630,13 @@ func TestEncodeDecode3(t *testing.T) {
"aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes"
"b0063f"+ // field 102, encoding 0, 0x3f zigzag32
"b8067f"+ // field 103, encoding 0, 0x7f zigzag64
"c506e0ffffff"+ // field 104, encoding 5, -32 fixed32
"c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64
"8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose"
"90193f"+ // field 402, encoding 0, value 63
"98197f") // field 403, encoding 0, value 127
"98197f"+ // field 403, encoding 0, value 127
"a519e0ffffff"+ // field 404, encoding 5, -32 fixed32
"a919c0ffffffffffffff") // field 405, encoding 1, -64 fixed64
}
@ -724,6 +659,8 @@ func TestEncodeDecode4(t *testing.T) {
pb.F_BytesOptional = []byte("Bignose")
pb.F_Sint32Optional = Int32(-32)
pb.F_Sint64Optional = Int64(-64)
pb.F_Sfixed32Optional = Int32(-32)
pb.F_Sfixed64Optional = Int64(-64)
pb.Optionalgroup = initGoTest_OptionalGroup()
overify(t, pb,
@ -771,12 +708,18 @@ func TestEncodeDecode4(t *testing.T) {
"aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes"
"b0063f"+ // field 102, encoding 0, 0x3f zigzag32
"b8067f"+ // field 103, encoding 0, 0x7f zigzag64
"c506e0ffffff"+ // field 104, encoding 5, -32 fixed32
"c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64
"ea1207"+"4269676e6f7365"+ // field 301, encoding 2, string "Bignose"
"f0123f"+ // field 302, encoding 0, value 63
"f8127f"+ // field 303, encoding 0, value 127
"8513e0ffffff"+ // field 304, encoding 5, -32 fixed32
"8913c0ffffffffffffff"+ // field 305, encoding 1, -64 fixed64
"8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose"
"90193f"+ // field 402, encoding 0, value 63
"98197f") // field 403, encoding 0, value 127
"98197f"+ // field 403, encoding 0, value 127
"a519e0ffffff"+ // field 404, encoding 5, -32 fixed32
"a919c0ffffffffffffff") // field 405, encoding 1, -64 fixed64
}
@ -797,6 +740,8 @@ func TestEncodeDecode5(t *testing.T) {
pb.F_BytesRepeated = [][]byte{[]byte("big"), []byte("nose")}
pb.F_Sint32Repeated = []int32{32, -32}
pb.F_Sint64Repeated = []int64{64, -64}
pb.F_Sfixed32Repeated = []int32{32, -32}
pb.F_Sfixed64Repeated = []int64{64, -64}
pb.Repeatedgroup = []*GoTest_RepeatedGroup{initGoTest_RepeatedGroup(), initGoTest_RepeatedGroup()}
overify(t, pb,
@ -856,15 +801,23 @@ func TestEncodeDecode5(t *testing.T) {
"aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes"
"b0063f"+ // field 102, encoding 0, 0x3f zigzag32
"b8067f"+ // field 103, encoding 0, 0x7f zigzag64
"c506e0ffffff"+ // field 104, encoding 5, -32 fixed32
"c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64
"ca0c03"+"626967"+ // field 201, encoding 2, string "big"
"ca0c04"+"6e6f7365"+ // field 201, encoding 2, string "nose"
"d00c40"+ // field 202, encoding 0, value 32
"d00c3f"+ // field 202, encoding 0, value -32
"d80c8001"+ // field 203, encoding 0, value 64
"d80c7f"+ // field 203, encoding 0, value -64
"e50c20000000"+ // field 204, encoding 5, 32 fixed32
"e50ce0ffffff"+ // field 204, encoding 5, -32 fixed32
"e90c4000000000000000"+ // field 205, encoding 1, 64 fixed64
"e90cc0ffffffffffffff"+ // field 205, encoding 1, -64 fixed64
"8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose"
"90193f"+ // field 402, encoding 0, value 63
"98197f") // field 403, encoding 0, value 127
"98197f"+ // field 403, encoding 0, value 127
"a519e0ffffff"+ // field 404, encoding 5, -32 fixed32
"a919c0ffffffffffffff") // field 405, encoding 1, -64 fixed64
}
@ -882,6 +835,8 @@ func TestEncodeDecode6(t *testing.T) {
pb.F_DoubleRepeatedPacked = []float64{64., 65.}
pb.F_Sint32RepeatedPacked = []int32{32, -32}
pb.F_Sint64RepeatedPacked = []int64{64, -64}
pb.F_Sfixed32RepeatedPacked = []int32{32, -32}
pb.F_Sfixed64RepeatedPacked = []int64{64, -64}
overify(t, pb,
"0807"+ // field 1, encoding 0, value 7
@ -917,10 +872,17 @@ func TestEncodeDecode6(t *testing.T) {
"aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes"
"b0063f"+ // field 102, encoding 0, 0x3f zigzag32
"b8067f"+ // field 103, encoding 0, 0x7f zigzag64
"c506e0ffffff"+ // field 104, encoding 5, -32 fixed32
"c906c0ffffffffffffff"+ // field 105, encoding 1, -64 fixed64
"b21f02"+ // field 502, encoding 2, 2 bytes
"403f"+ // value 32, value -32
"ba1f03"+ // field 503, encoding 2, 3 bytes
"80017f") // value 64, value -64
"80017f"+ // value 64, value -64
"c21f08"+ // field 504, encoding 2, 8 bytes
"20000000e0ffffff"+ // value 32, value -32
"ca1f10"+ // field 505, encoding 2, 16 bytes
"4000000000000000c0ffffffffffffff") // value 64, value -64
}
// Test that we can encode empty bytes fields.
@ -1167,13 +1129,10 @@ func TestBigRepeated(t *testing.T) {
if pbd.Repeatedgroup[i] == nil { // TODO: more checking?
t.Error("pbd.Repeatedgroup bad")
}
var x uint64
x = uint64(pbd.F_Sint64Repeated[i])
if x != i {
if x := uint64(pbd.F_Sint64Repeated[i]); x != i {
t.Error("pbd.F_Sint64Repeated bad", x, i)
}
x = uint64(pbd.F_Sint32Repeated[i])
if x != i {
if x := uint64(pbd.F_Sint32Repeated[i]); x != i {
t.Error("pbd.F_Sint32Repeated bad", x, i)
}
s := fmt.Sprint(i)
@ -1181,39 +1140,31 @@ func TestBigRepeated(t *testing.T) {
if pbd.F_StringRepeated[i] != s {
t.Error("pbd.F_Sint32Repeated bad", pbd.F_StringRepeated[i], i)
}
x = uint64(pbd.F_DoubleRepeated[i])
if x != i {
if x := uint64(pbd.F_DoubleRepeated[i]); x != i {
t.Error("pbd.F_DoubleRepeated bad", x, i)
}
x = uint64(pbd.F_FloatRepeated[i])
if x != i {
if x := uint64(pbd.F_FloatRepeated[i]); x != i {
t.Error("pbd.F_FloatRepeated bad", x, i)
}
x = pbd.F_Uint64Repeated[i]
if x != i {
if x := pbd.F_Uint64Repeated[i]; x != i {
t.Error("pbd.F_Uint64Repeated bad", x, i)
}
x = uint64(pbd.F_Uint32Repeated[i])
if x != i {
if x := uint64(pbd.F_Uint32Repeated[i]); x != i {
t.Error("pbd.F_Uint32Repeated bad", x, i)
}
x = pbd.F_Fixed64Repeated[i]
if x != i {
if x := pbd.F_Fixed64Repeated[i]; x != i {
t.Error("pbd.F_Fixed64Repeated bad", x, i)
}
x = uint64(pbd.F_Fixed32Repeated[i])
if x != i {
if x := uint64(pbd.F_Fixed32Repeated[i]); x != i {
t.Error("pbd.F_Fixed32Repeated bad", x, i)
}
x = uint64(pbd.F_Int64Repeated[i])
if x != i {
if x := uint64(pbd.F_Int64Repeated[i]); x != i {
t.Error("pbd.F_Int64Repeated bad", x, i)
}
x = uint64(pbd.F_Int32Repeated[i])
if x != i {
if x := uint64(pbd.F_Int32Repeated[i]); x != i {
t.Error("pbd.F_Int32Repeated bad", x, i)
}
if pbd.F_BoolRepeated[i] != (i%2 == 0) {
if x := pbd.F_BoolRepeated[i]; x != (i%2 == 0) {
t.Error("pbd.F_BoolRepeated bad", x, i)
}
if pbd.RepeatedField[i] == nil { // TODO: more checking?
@ -1222,21 +1173,25 @@ func TestBigRepeated(t *testing.T) {
}
}
// Verify we give a useful message when decoding to the wrong structure type.
func TestTypeMismatch(t *testing.T) {
pb1 := initGoTest(true)
func TestBadWireTypeUnknown(t *testing.T) {
var b []byte
fmt.Sscanf("0a01780d00000000080b101612036161611521000000202c220362626225370000002203636363214200000000000000584d5a036464645900000000000056405d63000000", "%x", &b)
// Marshal
o := old()
o.Marshal(pb1)
m := new(MyMessage)
if err := Unmarshal(b, m); err != nil {
t.Errorf("unexpected Unmarshal error: %v", err)
}
// Now Unmarshal it to the wrong type.
pb2 := initGoTestField()
err := o.Unmarshal(pb2)
if err == nil {
t.Error("expected error, got no error")
} else if !strings.Contains(err.Error(), "bad wiretype") {
t.Error("expected bad wiretype error, got", err)
var unknown []byte
fmt.Sscanf("0a01780d0000000010161521000000202c2537000000214200000000000000584d5a036464645d63000000", "%x", &unknown)
if !bytes.Equal(m.XXX_unrecognized, unknown) {
t.Errorf("unknown bytes mismatch:\ngot %x\nwant %x", m.XXX_unrecognized, unknown)
}
DiscardUnknown(m)
want := &MyMessage{Count: Int32(11), Name: String("aaa"), Pet: []string{"bbb", "ccc"}, Bigfloat: Float64(88)}
if !Equal(m, want) {
t.Errorf("message mismatch:\ngot %v\nwant %v", m, want)
}
}
@ -1331,7 +1286,8 @@ func TestRequiredFieldEnforcement(t *testing.T) {
err = Unmarshal(buf, pb)
if err == nil {
t.Error("unmarshal: expected error, got nil")
} else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "{Unknown}") {
} else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Type") && !strings.Contains(err.Error(), "{Unknown}") {
// TODO: remove unknown cases once we commit to the new unmarshaler.
t.Errorf("unmarshal: bad error type: %v", err)
}
}
@ -1348,7 +1304,7 @@ func TestRequiredFieldEnforcementGroups(t *testing.T) {
buf := []byte{11, 12}
if err := Unmarshal(buf, pb); err == nil {
t.Error("unmarshal: expected error, got nil")
} else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Group.{Unknown}") {
} else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Group.Field") && !strings.Contains(err.Error(), "Group.{Unknown}") {
t.Errorf("unmarshal: bad error type: %v", err)
}
}
@ -1385,18 +1341,7 @@ func (*NNIMessage) Reset() {}
func (*NNIMessage) String() string { return "" }
func (*NNIMessage) ProtoMessage() {}
// A type that implements the Marshaler interface and is nillable.
type nillableMessage struct {
x uint64
}
func (nm *nillableMessage) Marshal() ([]byte, error) {
return EncodeVarint(nm.x), nil
}
type NMMessage struct {
nm *nillableMessage
}
type NMMessage struct{}
func (*NMMessage) Reset() {}
func (*NMMessage) String() string { return "" }
@ -1595,6 +1540,14 @@ func TestVarintOverflow(t *testing.T) {
}
}
func TestBytesWithInvalidLengthInGroup(t *testing.T) {
// Overflowing a 64-bit length should not be allowed.
b := []byte{0xbb, 0x30, 0xb2, 0x30, 0xb0, 0xb2, 0x83, 0xf1, 0xb0, 0xb2, 0xef, 0xbf, 0xbd, 0x01}
if err := Unmarshal(b, new(MyMessage)); err == nil {
t.Fatalf("Overflowed uint64 length without error")
}
}
func TestUnmarshalFuzz(t *testing.T) {
const N = 1000
seed := time.Now().UnixNano()
@ -1668,6 +1621,28 @@ func TestExtensionMarshalOrder(t *testing.T) {
}
}
func TestExtensionMapFieldMarshalDeterministic(t *testing.T) {
m := &MyMessage{Count: Int(123)}
if err := SetExtension(m, E_Ext_More, &Ext{MapField: map[int32]int32{1: 1, 2: 2, 3: 3, 4: 4}}); err != nil {
t.Fatalf("SetExtension: %v", err)
}
marshal := func(m Message) []byte {
var b Buffer
b.SetDeterministic(true)
if err := b.Marshal(m); err != nil {
t.Fatalf("Marshal failed: %v", err)
}
return b.Bytes()
}
want := marshal(m)
for i := 0; i < 100; i++ {
if got := marshal(m); !bytes.Equal(got, want) {
t.Errorf("Marshal produced inconsistent output with determinism enabled (pass %d).\n got %v\nwant %v", i, got, want)
}
}
}
// Many extensions, because small maps might not iterate differently on each iteration.
var exts = []*ExtensionDesc{
E_X201,
@ -1802,6 +1777,43 @@ func TestUnmarshalMergesMessages(t *testing.T) {
}
}
func TestUnmarshalMergesGroups(t *testing.T) {
// If a nested group occurs twice in the input,
// the fields should be merged when decoding.
a := &GroupNew{
G: &GroupNew_G{
X: Int32(7),
Y: Int32(8),
},
}
aData, err := Marshal(a)
if err != nil {
t.Fatalf("Marshal(a): %v", err)
}
b := &GroupNew{
G: &GroupNew_G{
X: Int32(9),
},
}
bData, err := Marshal(b)
if err != nil {
t.Fatalf("Marshal(b): %v", err)
}
want := &GroupNew{
G: &GroupNew_G{
X: Int32(9),
Y: Int32(8),
},
}
got := new(GroupNew)
if err := Unmarshal(append(aData, bData...), got); err != nil {
t.Fatalf("Unmarshal: %v", err)
}
if !Equal(got, want) {
t.Errorf("\n got %v\nwant %v", got, want)
}
}
func TestEncodingSizes(t *testing.T) {
tests := []struct {
m Message
@ -1845,7 +1857,9 @@ func TestRequiredNotSetError(t *testing.T) {
"b404" + // field 70, encoding 4, end group
"aa0605" + "6279746573" + // field 101, encoding 2, string "bytes"
"b0063f" + // field 102, encoding 0, 0x3f zigzag32
"b8067f" // field 103, encoding 0, 0x7f zigzag64
"b8067f" + // field 103, encoding 0, 0x7f zigzag64
"c506e0ffffff" + // field 104, encoding 5, -32 fixed32
"c906c0ffffffffffffff" // field 105, encoding 1, -64 fixed64
o := old()
mbytes, err := Marshal(pb)
@ -1854,7 +1868,7 @@ func TestRequiredNotSetError(t *testing.T) {
o.DebugPrint("", mbytes)
t.Fatalf("expected = %s", expected)
}
if strings.Index(err.Error(), "RequiredField.Label") < 0 {
if !strings.Contains(err.Error(), "RequiredField.Label") {
t.Errorf("marshal-1 wrong err msg: %v", err)
}
if !equal(mbytes, expected, t) {
@ -1870,7 +1884,7 @@ func TestRequiredNotSetError(t *testing.T) {
o.DebugPrint("", mbytes)
t.Fatalf("string = %s", expected)
}
if strings.Index(err.Error(), "RequiredField.{Unknown}") < 0 {
if !strings.Contains(err.Error(), "RequiredField.Label") && !strings.Contains(err.Error(), "RequiredField.{Unknown}") {
t.Errorf("unmarshal wrong err msg: %v", err)
}
mbytes, err = Marshal(pbd)
@ -1879,7 +1893,7 @@ func TestRequiredNotSetError(t *testing.T) {
o.DebugPrint("", mbytes)
t.Fatalf("string = %s", expected)
}
if strings.Index(err.Error(), "RequiredField.Label") < 0 {
if !strings.Contains(err.Error(), "RequiredField.Label") {
t.Errorf("marshal-2 wrong err msg: %v", err)
}
if !equal(mbytes, expected, t) {
@ -1888,6 +1902,25 @@ func TestRequiredNotSetError(t *testing.T) {
}
}
func TestRequiredNotSetErrorWithBadWireTypes(t *testing.T) {
// Required field expects a varint, and properly found a varint.
if err := Unmarshal([]byte{0x08, 0x00}, new(GoEnum)); err != nil {
t.Errorf("Unmarshal = %v, want nil", err)
}
// Required field expects a varint, but found a fixed32 instead.
if err := Unmarshal([]byte{0x0d, 0x00, 0x00, 0x00, 0x00}, new(GoEnum)); err == nil {
t.Errorf("Unmarshal = nil, want RequiredNotSetError")
}
// Required field expects a varint, and found both a varint and fixed32 (ignored).
m := new(GoEnum)
if err := Unmarshal([]byte{0x08, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00}, m); err != nil {
t.Errorf("Unmarshal = %v, want nil", err)
}
if !bytes.Equal(m.XXX_unrecognized, []byte{0x0d, 0x00, 0x00, 0x00, 0x00}) {
t.Errorf("expected fixed32 to appear as unknown bytes: %x", m.XXX_unrecognized)
}
}
func fuzzUnmarshal(t *testing.T, data []byte) {
defer func() {
if e := recover(); e != nil {
@ -1946,6 +1979,32 @@ func TestMapFieldMarshal(t *testing.T) {
(new(Buffer)).DebugPrint("Dump of b", b)
}
func TestMapFieldDeterministicMarshal(t *testing.T) {
m := &MessageWithMap{
NameMapping: map[int32]string{
1: "Rob",
4: "Ian",
8: "Dave",
},
}
marshal := func(m Message) []byte {
var b Buffer
b.SetDeterministic(true)
if err := b.Marshal(m); err != nil {
t.Fatalf("Marshal failed: %v", err)
}
return b.Bytes()
}
want := marshal(m)
for i := 0; i < 10; i++ {
if got := marshal(m); !bytes.Equal(got, want) {
t.Errorf("Marshal produced inconsistent output with determinism enabled (pass %d).\n got %v\nwant %v", i, got, want)
}
}
}
func TestMapFieldRoundTrips(t *testing.T) {
m := &MessageWithMap{
NameMapping: map[int32]string{
@ -1970,14 +2029,8 @@ func TestMapFieldRoundTrips(t *testing.T) {
if err := Unmarshal(b, m2); err != nil {
t.Fatalf("Unmarshal: %v", err)
}
for _, pair := range [][2]interface{}{
{m.NameMapping, m2.NameMapping},
{m.MsgMapping, m2.MsgMapping},
{m.ByteMapping, m2.ByteMapping},
} {
if !reflect.DeepEqual(pair[0], pair[1]) {
t.Errorf("Map did not survive a round trip.\ninitial: %v\n final: %v", pair[0], pair[1])
}
if !Equal(m, m2) {
t.Errorf("Map did not survive a round trip.\ninitial: %v\n final: %v", m, m2)
}
}
@ -2119,6 +2172,22 @@ func TestOneof(t *testing.T) {
}
}
func TestOneofNilBytes(t *testing.T) {
// A oneof with nil byte slice should marshal to tag + 0 (size), with no error.
m := &Communique{Union: &Communique_Data{Data: nil}}
b, err := Marshal(m)
if err != nil {
t.Fatalf("Marshal failed: %v", err)
}
want := []byte{
7<<3 | 2, // tag 7, wire type 2
0, // size
}
if !bytes.Equal(b, want) {
t.Errorf("Wrong result of Marshal: got %x, want %x", b, want)
}
}
func TestInefficientPackedBool(t *testing.T) {
// https://github.com/golang/protobuf/issues/76
inp := []byte{
@ -2132,6 +2201,80 @@ func TestInefficientPackedBool(t *testing.T) {
}
}
// Make sure pure-reflect-based implementation handles
// []int32-[]enum conversion correctly.
func TestRepeatedEnum2(t *testing.T) {
pb := &RepeatedEnum{
Color: []RepeatedEnum_Color{RepeatedEnum_RED},
}
b, err := Marshal(pb)
if err != nil {
t.Fatalf("Marshal failed: %v", err)
}
x := new(RepeatedEnum)
err = Unmarshal(b, x)
if err != nil {
t.Fatalf("Unmarshal failed: %v", err)
}
if !Equal(pb, x) {
t.Errorf("Incorrect result: want: %v got: %v", pb, x)
}
}
// TestConcurrentMarshal makes sure that it is safe to marshal
// same message in multiple goroutines concurrently.
func TestConcurrentMarshal(t *testing.T) {
pb := initGoTest(true)
const N = 100
b := make([][]byte, N)
var wg sync.WaitGroup
for i := 0; i < N; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
var err error
b[i], err = Marshal(pb)
if err != nil {
t.Errorf("marshal error: %v", err)
}
}(i)
}
wg.Wait()
for i := 1; i < N; i++ {
if !bytes.Equal(b[0], b[i]) {
t.Errorf("concurrent marshal result not same: b[0] = %v, b[%d] = %v", b[0], i, b[i])
}
}
}
func TestInvalidUTF8(t *testing.T) {
const wire = "\x12\x04\xde\xea\xca\xfe"
var m GoTest
if err := Unmarshal([]byte(wire), &m); err == nil {
t.Errorf("Unmarshal error: got nil, want non-nil")
}
m.Reset()
m.Table = String(wire[2:])
if _, err := Marshal(&m); err == nil {
t.Errorf("Marshal error: got nil, want non-nil")
}
}
func TestDeterministicErrorOnCustomMarshaler(t *testing.T) {
u := uint64(0)
in := &CustomDeterministicMarshaler{Field1: &u}
var b1 Buffer
b1.SetDeterministic(true)
err := b1.Marshal(in)
if !strings.Contains(err.Error(), "deterministic") {
t.Fatalf("Expected: %s but got %s", "proto: deterministic not supported by the Marshal method of test_proto.CustomDeterministicMarshaler", err.Error())
}
}
// Benchmarks
func testMsg() *GoTest {

View file

@ -38,7 +38,7 @@ import (
"github.com/gogo/protobuf/proto"
pb "github.com/gogo/protobuf/proto/proto3_proto"
testpb "github.com/gogo/protobuf/proto/testdata"
testpb "github.com/gogo/protobuf/proto/test_proto"
"github.com/gogo/protobuf/types"
)
@ -166,33 +166,33 @@ anything: <
name: "David"
result_count: 47
anything: <
[type.googleapis.com/testdata.MyMessage]: <
[type.googleapis.com/test_proto.MyMessage]: <
count: 47
name: "David"
[testdata.Ext.more]: <
[test_proto.Ext.more]: <
data: "foo"
>
[testdata.Ext.text]: "bar"
[test_proto.Ext.text]: "bar"
>
>
many_things: <
[type.googleapis.com/testdata.MyMessage]: <
[type.googleapis.com/test_proto.MyMessage]: <
count: 42
bikeshed: GREEN
rep_bytes: "roboto"
[testdata.Ext.more]: <
[test_proto.Ext.more]: <
data: "baz"
>
>
>
many_things: <
[type.googleapis.com/testdata.MyMessage]: <
[type.googleapis.com/test_proto.MyMessage]: <
count: 47
name: "David"
[testdata.Ext.more]: <
[test_proto.Ext.more]: <
data: "foo"
>
[testdata.Ext.text]: "bar"
[test_proto.Ext.text]: "bar"
>
>
`

View file

@ -35,22 +35,39 @@
package proto
import (
"fmt"
"log"
"reflect"
"strings"
)
// Clone returns a deep copy of a protocol buffer.
func Clone(pb Message) Message {
in := reflect.ValueOf(pb)
func Clone(src Message) Message {
in := reflect.ValueOf(src)
if in.IsNil() {
return pb
return src
}
out := reflect.New(in.Type().Elem())
// out is empty so a merge is a deep copy.
mergeStruct(out.Elem(), in.Elem())
return out.Interface().(Message)
dst := out.Interface().(Message)
Merge(dst, src)
return dst
}
// Merger is the interface representing objects that can merge messages of the same type.
type Merger interface {
// Merge merges src into this message.
// Required and optional fields that are set in src will be set to that value in dst.
// Elements of repeated fields will be appended.
//
// Merge may panic if called with a different argument type than the receiver.
Merge(src Message)
}
// generatedMerger is the custom merge method that generated protos will have.
// We must add this method since a generate Merge method will conflict with
// many existing protos that have a Merge data field already defined.
type generatedMerger interface {
XXX_Merge(src Message)
}
// Merge merges src into dst.
@ -58,17 +75,24 @@ func Clone(pb Message) Message {
// Elements of repeated fields will be appended.
// Merge panics if src and dst are not the same type, or if dst is nil.
func Merge(dst, src Message) {
if m, ok := dst.(Merger); ok {
m.Merge(src)
return
}
in := reflect.ValueOf(src)
out := reflect.ValueOf(dst)
if out.IsNil() {
panic("proto: nil destination")
}
if in.Type() != out.Type() {
// Explicit test prior to mergeStruct so that mistyped nils will fail
panic("proto: type mismatch")
panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src))
}
if in.IsNil() {
// Merging nil into non-nil is a quiet no-op
return // Merge from nil src is a noop
}
if m, ok := dst.(generatedMerger); ok {
m.XXX_Merge(src)
return
}
mergeStruct(out.Elem(), in.Elem())
@ -89,7 +113,7 @@ func mergeStruct(out, in reflect.Value) {
bIn := emIn.GetExtensions()
bOut := emOut.GetExtensions()
*bOut = append(*bOut, *bIn...)
} else if emIn, ok := extendable(in.Addr().Interface()); ok {
} else if emIn, err := extendable(in.Addr().Interface()); err == nil {
emOut, _ := extendable(out.Addr().Interface())
mIn, muIn := emIn.extensionsRead()
if mIn != nil {

View file

@ -37,7 +37,7 @@ import (
"github.com/gogo/protobuf/proto"
proto3pb "github.com/gogo/protobuf/proto/proto3_proto"
pb "github.com/gogo/protobuf/proto/testdata"
pb "github.com/gogo/protobuf/proto/test_proto"
)
var cloneTestMessage = &pb.MyMessage{
@ -72,7 +72,7 @@ func init() {
func TestClone(t *testing.T) {
m := proto.Clone(cloneTestMessage).(*pb.MyMessage)
if !proto.Equal(m, cloneTestMessage) {
t.Errorf("Clone(%v) = %v", cloneTestMessage, m)
t.Fatalf("Clone(%v) = %v", cloneTestMessage, m)
}
// Verify it was a deep copy.
@ -256,15 +256,40 @@ var mergeTests = []struct {
Union: &pb.Communique_Number{Number: 41},
},
},
// Oneof nil is the same as not set.
{ // Oneof nil is the same as not set.
src: &pb.Communique{},
dst: &pb.Communique{Union: &pb.Communique_Name{Name: "Bobby Tables"}},
want: &pb.Communique{Union: &pb.Communique_Name{Name: "Bobby Tables"}},
},
{
src: &pb.Communique{},
dst: &pb.Communique{
Union: &pb.Communique_Name{Name: "Bobby Tables"},
},
want: &pb.Communique{
Union: &pb.Communique_Name{Name: "Bobby Tables"},
},
src: &pb.Communique{Union: &pb.Communique_Number{Number: 1337}},
dst: &pb.Communique{},
want: &pb.Communique{Union: &pb.Communique_Number{Number: 1337}},
},
{
src: &pb.Communique{Union: &pb.Communique_Col{Col: pb.MyMessage_RED}},
dst: &pb.Communique{},
want: &pb.Communique{Union: &pb.Communique_Col{Col: pb.MyMessage_RED}},
},
{
src: &pb.Communique{Union: &pb.Communique_Data{Data: []byte("hello")}},
dst: &pb.Communique{},
want: &pb.Communique{Union: &pb.Communique_Data{Data: []byte("hello")}},
},
{
src: &pb.Communique{Union: &pb.Communique_Msg{Msg: &pb.Strings{BytesField: []byte{1, 2, 3}}}},
dst: &pb.Communique{},
want: &pb.Communique{Union: &pb.Communique_Msg{Msg: &pb.Strings{BytesField: []byte{1, 2, 3}}}},
},
{
src: &pb.Communique{Union: &pb.Communique_Msg{}},
dst: &pb.Communique{},
want: &pb.Communique{Union: &pb.Communique_Msg{}},
},
{
src: &pb.Communique{Union: &pb.Communique_Msg{Msg: &pb.Strings{StringField: proto.String("123")}}},
dst: &pb.Communique{Union: &pb.Communique_Msg{Msg: &pb.Strings{BytesField: []byte{1, 2, 3}}}},
want: &pb.Communique{Union: &pb.Communique_Msg{Msg: &pb.Strings{StringField: proto.String("123"), BytesField: []byte{1, 2, 3}}}},
},
{
src: &proto3pb.Message{
@ -287,14 +312,86 @@ var mergeTests = []struct {
},
},
},
{
src: &pb.GoTest{
F_BoolRepeated: []bool{},
F_Int32Repeated: []int32{},
F_Int64Repeated: []int64{},
F_Uint32Repeated: []uint32{},
F_Uint64Repeated: []uint64{},
F_FloatRepeated: []float32{},
F_DoubleRepeated: []float64{},
F_StringRepeated: []string{},
F_BytesRepeated: [][]byte{},
},
dst: &pb.GoTest{},
want: &pb.GoTest{
F_BoolRepeated: []bool{},
F_Int32Repeated: []int32{},
F_Int64Repeated: []int64{},
F_Uint32Repeated: []uint32{},
F_Uint64Repeated: []uint64{},
F_FloatRepeated: []float32{},
F_DoubleRepeated: []float64{},
F_StringRepeated: []string{},
F_BytesRepeated: [][]byte{},
},
},
{
src: &pb.GoTest{},
dst: &pb.GoTest{
F_BoolRepeated: []bool{},
F_Int32Repeated: []int32{},
F_Int64Repeated: []int64{},
F_Uint32Repeated: []uint32{},
F_Uint64Repeated: []uint64{},
F_FloatRepeated: []float32{},
F_DoubleRepeated: []float64{},
F_StringRepeated: []string{},
F_BytesRepeated: [][]byte{},
},
want: &pb.GoTest{
F_BoolRepeated: []bool{},
F_Int32Repeated: []int32{},
F_Int64Repeated: []int64{},
F_Uint32Repeated: []uint32{},
F_Uint64Repeated: []uint64{},
F_FloatRepeated: []float32{},
F_DoubleRepeated: []float64{},
F_StringRepeated: []string{},
F_BytesRepeated: [][]byte{},
},
},
{
src: &pb.GoTest{
F_BytesRepeated: [][]byte{nil, {}, {0}},
},
dst: &pb.GoTest{},
want: &pb.GoTest{
F_BytesRepeated: [][]byte{nil, {}, {0}},
},
},
{
src: &pb.MyMessage{
Others: []*pb.OtherMessage{},
},
dst: &pb.MyMessage{},
want: &pb.MyMessage{
Others: []*pb.OtherMessage{},
},
},
}
func TestMerge(t *testing.T) {
for _, m := range mergeTests {
got := proto.Clone(m.dst)
if !proto.Equal(got, m.dst) {
t.Errorf("Clone()\ngot %v\nwant %v", got, m.dst)
continue
}
proto.Merge(got, m.src)
if !proto.Equal(got, m.want) {
t.Errorf("Merge(%v, %v)\n got %v\nwant %v\n", m.dst, m.src, got, m.want)
t.Errorf("Merge(%v, %v)\ngot %v\nwant %v", m.dst, m.src, got, m.want)
}
}
}

39
vendor/github.com/gogo/protobuf/proto/custom_gogo.go generated vendored Normal file
View file

@ -0,0 +1,39 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2018, 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 proto
import "reflect"
type custom interface {
Marshal() ([]byte, error)
Unmarshal(data []byte) error
Size() int
}
var customType = reflect.TypeOf((*custom)(nil)).Elem()

View file

@ -39,8 +39,6 @@ import (
"errors"
"fmt"
"io"
"os"
"reflect"
)
// errOverflow is returned when an integer is too large to be represented.
@ -50,10 +48,6 @@ var errOverflow = errors.New("proto: integer overflow")
// wire type is encountered. It does not get returned to user code.
var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
// The fundamental decoders that interpret bytes on the wire.
// Those that take integer types all return uint64 and are
// therefore of type valueDecoder.
// DecodeVarint reads a varint-encoded integer from the slice.
// It returns the integer and the number of bytes consumed, or
// zero if there is not enough.
@ -267,9 +261,6 @@ func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
return
}
// These are not ValueDecoders: they produce an array of bytes or a string.
// bytes, embedded messages
// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
// This is the format used for the bytes protocol buffer
// type and for embedded messages.
@ -311,81 +302,29 @@ func (p *Buffer) DecodeStringBytes() (s string, err error) {
return string(buf), nil
}
// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
// If the protocol buffer has extensions, and the field matches, add it as an extension.
// Otherwise, if the XXX_unrecognized field exists, append the skipped data there.
func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error {
oi := o.index
err := o.skip(t, tag, wire)
if err != nil {
return err
}
if !unrecField.IsValid() {
return nil
}
ptr := structPointer_Bytes(base, unrecField)
// Add the skipped field to struct field
obuf := o.buf
o.buf = *ptr
o.EncodeVarint(uint64(tag<<3 | wire))
*ptr = append(o.buf, obuf[oi:o.index]...)
o.buf = obuf
return nil
}
// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
func (o *Buffer) skip(t reflect.Type, tag, wire int) error {
var u uint64
var err error
switch wire {
case WireVarint:
_, err = o.DecodeVarint()
case WireFixed64:
_, err = o.DecodeFixed64()
case WireBytes:
_, err = o.DecodeRawBytes(false)
case WireFixed32:
_, err = o.DecodeFixed32()
case WireStartGroup:
for {
u, err = o.DecodeVarint()
if err != nil {
break
}
fwire := int(u & 0x7)
if fwire == WireEndGroup {
break
}
ftag := int(u >> 3)
err = o.skip(t, ftag, fwire)
if err != nil {
break
}
}
default:
err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t)
}
return err
}
// Unmarshaler is the interface representing objects that can
// unmarshal themselves. The method should reset the receiver before
// decoding starts. The argument points to data that may be
// unmarshal themselves. The argument points to data that may be
// overwritten, so implementations should not keep references to the
// buffer.
// Unmarshal implementations should not clear the receiver.
// Any unmarshaled data should be merged into the receiver.
// Callers of Unmarshal that do not want to retain existing data
// should Reset the receiver before calling Unmarshal.
type Unmarshaler interface {
Unmarshal([]byte) error
}
// newUnmarshaler is the interface representing objects that can
// unmarshal themselves. The semantics are identical to Unmarshaler.
//
// This exists to support protoc-gen-go generated messages.
// The proto package will stop type-asserting to this interface in the future.
//
// DO NOT DEPEND ON THIS.
type newUnmarshaler interface {
XXX_Unmarshal([]byte) error
}
// Unmarshal parses the protocol buffer representation in buf and places the
// decoded result in pb. If the struct underlying pb does not match
// the data in buf, the results can be unpredictable.
@ -395,7 +334,13 @@ type Unmarshaler interface {
// to preserve and append to existing data.
func Unmarshal(buf []byte, pb Message) error {
pb.Reset()
return UnmarshalMerge(buf, pb)
if u, ok := pb.(newUnmarshaler); ok {
return u.XXX_Unmarshal(buf)
}
if u, ok := pb.(Unmarshaler); ok {
return u.Unmarshal(buf)
}
return NewBuffer(buf).Unmarshal(pb)
}
// UnmarshalMerge parses the protocol buffer representation in buf and
@ -405,8 +350,16 @@ func Unmarshal(buf []byte, pb Message) error {
// UnmarshalMerge merges into existing data in pb.
// Most code should use Unmarshal instead.
func UnmarshalMerge(buf []byte, pb Message) error {
// If the object can unmarshal itself, let it.
if u, ok := pb.(newUnmarshaler); ok {
return u.XXX_Unmarshal(buf)
}
if u, ok := pb.(Unmarshaler); ok {
// NOTE: The history of proto have unfortunately been inconsistent
// whether Unmarshaler should or should not implicitly clear itself.
// Some implementations do, most do not.
// Thus, calling this here may or may not do what people want.
//
// See https://github.com/golang/protobuf/issues/424
return u.Unmarshal(buf)
}
return NewBuffer(buf).Unmarshal(pb)
@ -422,12 +375,17 @@ func (p *Buffer) DecodeMessage(pb Message) error {
}
// DecodeGroup reads a tag-delimited group from the Buffer.
// StartGroup tag is already consumed. This function consumes
// EndGroup tag.
func (p *Buffer) DecodeGroup(pb Message) error {
typ, base, err := getbase(pb)
if err != nil {
return err
b := p.buf[p.index:]
x, y := findEndGroup(b)
if x < 0 {
return io.ErrUnexpectedEOF
}
return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base)
err := Unmarshal(b[:x], pb)
p.index += y
return err
}
// Unmarshal parses the protocol buffer representation in the
@ -438,541 +396,33 @@ func (p *Buffer) DecodeGroup(pb Message) error {
// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
func (p *Buffer) Unmarshal(pb Message) error {
// If the object can unmarshal itself, let it.
if u, ok := pb.(newUnmarshaler); ok {
err := u.XXX_Unmarshal(p.buf[p.index:])
p.index = len(p.buf)
return err
}
if u, ok := pb.(Unmarshaler); ok {
// NOTE: The history of proto have unfortunately been inconsistent
// whether Unmarshaler should or should not implicitly clear itself.
// Some implementations do, most do not.
// Thus, calling this here may or may not do what people want.
//
// See https://github.com/golang/protobuf/issues/424
err := u.Unmarshal(p.buf[p.index:])
p.index = len(p.buf)
return err
}
typ, base, err := getbase(pb)
if err != nil {
return err
}
err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base)
if collectStats {
stats.Decode++
}
return err
}
// unmarshalType does the work of unmarshaling a structure.
func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error {
var state errorState
required, reqFields := prop.reqCount, uint64(0)
var err error
for err == nil && o.index < len(o.buf) {
oi := o.index
var u uint64
u, err = o.DecodeVarint()
if err != nil {
break
}
wire := int(u & 0x7)
if wire == WireEndGroup {
if is_group {
if required > 0 {
// Not enough information to determine the exact field.
// (See below.)
return &RequiredNotSetError{"{Unknown}"}
}
return nil // input is satisfied
}
return fmt.Errorf("proto: %s: wiretype end group for non-group", st)
}
tag := int(u >> 3)
if tag <= 0 {
return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire)
}
fieldnum, ok := prop.decoderTags.get(tag)
if !ok {
// Maybe it's an extension?
if prop.extendable {
if e, eok := structPointer_Interface(base, st).(extensionsBytes); eok {
if isExtensionField(e, int32(tag)) {
if err = o.skip(st, tag, wire); err == nil {
ext := e.GetExtensions()
*ext = append(*ext, o.buf[oi:o.index]...)
}
continue
}
} else if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) {
if err = o.skip(st, tag, wire); err == nil {
extmap := e.extensionsWrite()
ext := extmap[int32(tag)] // may be missing
ext.enc = append(ext.enc, o.buf[oi:o.index]...)
extmap[int32(tag)] = ext
}
continue
}
}
// Maybe it's a oneof?
if prop.oneofUnmarshaler != nil {
m := structPointer_Interface(base, st).(Message)
// First return value indicates whether tag is a oneof field.
ok, err = prop.oneofUnmarshaler(m, tag, wire, o)
if err == ErrInternalBadWireType {
// Map the error to something more descriptive.
// Do the formatting here to save generated code space.
err = fmt.Errorf("bad wiretype for oneof field in %T", m)
}
if ok {
continue
}
}
err = o.skipAndSave(st, tag, wire, base, prop.unrecField)
continue
}
p := prop.Prop[fieldnum]
if p.dec == nil {
fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name)
continue
}
dec := p.dec
if wire != WireStartGroup && wire != p.WireType {
if wire == WireBytes && p.packedDec != nil {
// a packable field
dec = p.packedDec
} else {
err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType)
continue
}
}
decErr := dec(o, p, base)
if decErr != nil && !state.shouldContinue(decErr, p) {
err = decErr
}
if err == nil && p.Required {
// Successfully decoded a required field.
if tag <= 64 {
// use bitmap for fields 1-64 to catch field reuse.
var mask uint64 = 1 << uint64(tag-1)
if reqFields&mask == 0 {
// new required field
reqFields |= mask
required--
}
} else {
// This is imprecise. It can be fooled by a required field
// with a tag > 64 that is encoded twice; that's very rare.
// A fully correct implementation would require allocating
// a data structure, which we would like to avoid.
required--
}
}
}
if err == nil {
if is_group {
return io.ErrUnexpectedEOF
}
if state.err != nil {
return state.err
}
if required > 0 {
// Not enough information to determine the exact field. If we use extra
// CPU, we could determine the field only if the missing required field
// has a tag <= 64 and we check reqFields.
return &RequiredNotSetError{"{Unknown}"}
}
}
return err
}
// Individual type decoders
// For each,
// u is the decoded value,
// v is a pointer to the field (pointer) in the struct
// Sizes of the pools to allocate inside the Buffer.
// The goal is modest amortization and allocation
// on at least 16-byte boundaries.
const (
boolPoolSize = 16
uint32PoolSize = 8
uint64PoolSize = 4
)
// Decode a bool.
func (o *Buffer) dec_bool(p *Properties, base structPointer) error {
u, err := p.valDec(o)
if err != nil {
return err
}
if len(o.bools) == 0 {
o.bools = make([]bool, boolPoolSize)
}
o.bools[0] = u != 0
*structPointer_Bool(base, p.field) = &o.bools[0]
o.bools = o.bools[1:]
return nil
}
func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error {
u, err := p.valDec(o)
if err != nil {
return err
}
*structPointer_BoolVal(base, p.field) = u != 0
return nil
}
// Decode an int32.
func (o *Buffer) dec_int32(p *Properties, base structPointer) error {
u, err := p.valDec(o)
if err != nil {
return err
}
word32_Set(structPointer_Word32(base, p.field), o, uint32(u))
return nil
}
func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error {
u, err := p.valDec(o)
if err != nil {
return err
}
word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u))
return nil
}
// Decode an int64.
func (o *Buffer) dec_int64(p *Properties, base structPointer) error {
u, err := p.valDec(o)
if err != nil {
return err
}
word64_Set(structPointer_Word64(base, p.field), o, u)
return nil
}
func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error {
u, err := p.valDec(o)
if err != nil {
return err
}
word64Val_Set(structPointer_Word64Val(base, p.field), o, u)
return nil
}
// Decode a string.
func (o *Buffer) dec_string(p *Properties, base structPointer) error {
s, err := o.DecodeStringBytes()
if err != nil {
return err
}
*structPointer_String(base, p.field) = &s
return nil
}
func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error {
s, err := o.DecodeStringBytes()
if err != nil {
return err
}
*structPointer_StringVal(base, p.field) = s
return nil
}
// Decode a slice of bytes ([]byte).
func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error {
b, err := o.DecodeRawBytes(true)
if err != nil {
return err
}
*structPointer_Bytes(base, p.field) = b
return nil
}
// Decode a slice of bools ([]bool).
func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error {
u, err := p.valDec(o)
if err != nil {
return err
}
v := structPointer_BoolSlice(base, p.field)
*v = append(*v, u != 0)
return nil
}
// Decode a slice of bools ([]bool) in packed format.
func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error {
v := structPointer_BoolSlice(base, p.field)
nn, err := o.DecodeVarint()
if err != nil {
return err
}
nb := int(nn) // number of bytes of encoded bools
fin := o.index + nb
if fin < o.index {
return errOverflow
}
y := *v
for o.index < fin {
u, err := p.valDec(o)
if err != nil {
return err
}
y = append(y, u != 0)
}
*v = y
return nil
}
// Decode a slice of int32s ([]int32).
func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error {
u, err := p.valDec(o)
if err != nil {
return err
}
structPointer_Word32Slice(base, p.field).Append(uint32(u))
return nil
}
// Decode a slice of int32s ([]int32) in packed format.
func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error {
v := structPointer_Word32Slice(base, p.field)
nn, err := o.DecodeVarint()
if err != nil {
return err
}
nb := int(nn) // number of bytes of encoded int32s
fin := o.index + nb
if fin < o.index {
return errOverflow
}
for o.index < fin {
u, err := p.valDec(o)
if err != nil {
return err
}
v.Append(uint32(u))
}
return nil
}
// Decode a slice of int64s ([]int64).
func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error {
u, err := p.valDec(o)
if err != nil {
return err
}
structPointer_Word64Slice(base, p.field).Append(u)
return nil
}
// Decode a slice of int64s ([]int64) in packed format.
func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error {
v := structPointer_Word64Slice(base, p.field)
nn, err := o.DecodeVarint()
if err != nil {
return err
}
nb := int(nn) // number of bytes of encoded int64s
fin := o.index + nb
if fin < o.index {
return errOverflow
}
for o.index < fin {
u, err := p.valDec(o)
if err != nil {
return err
}
v.Append(u)
}
return nil
}
// Decode a slice of strings ([]string).
func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error {
s, err := o.DecodeStringBytes()
if err != nil {
return err
}
v := structPointer_StringSlice(base, p.field)
*v = append(*v, s)
return nil
}
// Decode a slice of slice of bytes ([][]byte).
func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error {
b, err := o.DecodeRawBytes(true)
if err != nil {
return err
}
v := structPointer_BytesSlice(base, p.field)
*v = append(*v, b)
return nil
}
// Decode a map field.
func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
raw, err := o.DecodeRawBytes(false)
if err != nil {
return err
}
oi := o.index // index at the end of this map entry
o.index -= len(raw) // move buffer back to start of map entry
mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V
if mptr.Elem().IsNil() {
mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem()))
}
v := mptr.Elem() // map[K]V
// Prepare addressable doubly-indirect placeholders for the key and value types.
// See enc_new_map for why.
keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K
keybase := toStructPointer(keyptr.Addr()) // **K
var valbase structPointer
var valptr reflect.Value
switch p.mtype.Elem().Kind() {
case reflect.Slice:
// []byte
var dummy []byte
valptr = reflect.ValueOf(&dummy) // *[]byte
valbase = toStructPointer(valptr) // *[]byte
case reflect.Ptr:
// message; valptr is **Msg; need to allocate the intermediate pointer
valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
valptr.Set(reflect.New(valptr.Type().Elem()))
valbase = toStructPointer(valptr)
default:
// everything else
valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
valbase = toStructPointer(valptr.Addr()) // **V
}
// Decode.
// This parses a restricted wire format, namely the encoding of a message
// with two fields. See enc_new_map for the format.
for o.index < oi {
// tagcode for key and value properties are always a single byte
// because they have tags 1 and 2.
tagcode := o.buf[o.index]
o.index++
switch tagcode {
case p.mkeyprop.tagcode[0]:
if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil {
return err
}
case p.mvalprop.tagcode[0]:
if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil {
return err
}
default:
// TODO: Should we silently skip this instead?
return fmt.Errorf("proto: bad map data tag %d", raw[0])
}
}
keyelem, valelem := keyptr.Elem(), valptr.Elem()
if !keyelem.IsValid() {
keyelem = reflect.Zero(p.mtype.Key())
}
if !valelem.IsValid() {
valelem = reflect.Zero(p.mtype.Elem())
}
v.SetMapIndex(keyelem, valelem)
return nil
}
// Decode a group.
func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error {
bas := structPointer_GetStructPointer(base, p.field)
if structPointer_IsNil(bas) {
// allocate new nested message
bas = toStructPointer(reflect.New(p.stype))
structPointer_SetStructPointer(base, p.field, bas)
}
return o.unmarshalType(p.stype, p.sprop, true, bas)
}
// Decode an embedded message.
func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) {
raw, e := o.DecodeRawBytes(false)
if e != nil {
return e
}
bas := structPointer_GetStructPointer(base, p.field)
if structPointer_IsNil(bas) {
// allocate new nested message
bas = toStructPointer(reflect.New(p.stype))
structPointer_SetStructPointer(base, p.field, bas)
}
// If the object can unmarshal itself, let it.
if p.isUnmarshaler {
iv := structPointer_Interface(bas, p.stype)
return iv.(Unmarshaler).Unmarshal(raw)
}
obuf := o.buf
oi := o.index
o.buf = raw
o.index = 0
err = o.unmarshalType(p.stype, p.sprop, false, bas)
o.buf = obuf
o.index = oi
return err
}
// Decode a slice of embedded messages.
func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error {
return o.dec_slice_struct(p, false, base)
}
// Decode a slice of embedded groups.
func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error {
return o.dec_slice_struct(p, true, base)
}
// Decode a slice of structs ([]*struct).
func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error {
v := reflect.New(p.stype)
bas := toStructPointer(v)
structPointer_StructPointerSlice(base, p.field).Append(bas)
if is_group {
err := o.unmarshalType(p.stype, p.sprop, is_group, bas)
return err
}
raw, err := o.DecodeRawBytes(false)
if err != nil {
return err
}
// If the object can unmarshal itself, let it.
if p.isUnmarshaler {
iv := v.Interface()
return iv.(Unmarshaler).Unmarshal(raw)
}
obuf := o.buf
oi := o.index
o.buf = raw
o.index = 0
err = o.unmarshalType(p.stype, p.sprop, is_group, bas)
o.buf = obuf
o.index = oi
// Slow workaround for messages that aren't Unmarshalers.
// This includes some hand-coded .pb.go files and
// bootstrap protos.
// TODO: fix all of those and then add Unmarshal to
// the Message interface. Then:
// The cast above and code below can be deleted.
// The old unmarshaler can be deleted.
// Clients can call Unmarshal directly (can already do that, actually).
var info InternalMessageInfo
err := info.Unmarshal(pb, p.buf[p.index:])
p.index = len(p.buf)
return err
}

View file

@ -1,172 +0,0 @@
// 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 proto
import (
"reflect"
)
// Decode a reference to a struct pointer.
func (o *Buffer) dec_ref_struct_message(p *Properties, base structPointer) (err error) {
raw, e := o.DecodeRawBytes(false)
if e != nil {
return e
}
// If the object can unmarshal itself, let it.
if p.isUnmarshaler {
panic("not supported, since this is a pointer receiver")
}
obuf := o.buf
oi := o.index
o.buf = raw
o.index = 0
bas := structPointer_FieldPointer(base, p.field)
err = o.unmarshalType(p.stype, p.sprop, false, bas)
o.buf = obuf
o.index = oi
return err
}
// Decode a slice of references to struct pointers ([]struct).
func (o *Buffer) dec_slice_ref_struct(p *Properties, is_group bool, base structPointer) error {
newBas := appendStructPointer(base, p.field, p.sstype)
if is_group {
panic("not supported, maybe in future, if requested.")
}
raw, err := o.DecodeRawBytes(false)
if err != nil {
return err
}
// If the object can unmarshal itself, let it.
if p.isUnmarshaler {
panic("not supported, since this is not a pointer receiver.")
}
obuf := o.buf
oi := o.index
o.buf = raw
o.index = 0
err = o.unmarshalType(p.stype, p.sprop, is_group, newBas)
o.buf = obuf
o.index = oi
return err
}
// Decode a slice of references to struct pointers.
func (o *Buffer) dec_slice_ref_struct_message(p *Properties, base structPointer) error {
return o.dec_slice_ref_struct(p, false, base)
}
func setPtrCustomType(base structPointer, f field, v interface{}) {
if v == nil {
return
}
structPointer_SetStructPointer(base, f, toStructPointer(reflect.ValueOf(v)))
}
func setCustomType(base structPointer, f field, value interface{}) {
if value == nil {
return
}
v := reflect.ValueOf(value).Elem()
t := reflect.TypeOf(value).Elem()
kind := t.Kind()
switch kind {
case reflect.Slice:
slice := reflect.MakeSlice(t, v.Len(), v.Cap())
reflect.Copy(slice, v)
oldHeader := structPointer_GetSliceHeader(base, f)
oldHeader.Data = slice.Pointer()
oldHeader.Len = v.Len()
oldHeader.Cap = v.Cap()
default:
size := reflect.TypeOf(value).Elem().Size()
structPointer_Copy(toStructPointer(reflect.ValueOf(value)), structPointer_Add(base, f), int(size))
}
}
func (o *Buffer) dec_custom_bytes(p *Properties, base structPointer) error {
b, err := o.DecodeRawBytes(true)
if err != nil {
return err
}
i := reflect.New(p.ctype.Elem()).Interface()
custom := (i).(Unmarshaler)
if err := custom.Unmarshal(b); err != nil {
return err
}
setPtrCustomType(base, p.field, custom)
return nil
}
func (o *Buffer) dec_custom_ref_bytes(p *Properties, base structPointer) error {
b, err := o.DecodeRawBytes(true)
if err != nil {
return err
}
i := reflect.New(p.ctype).Interface()
custom := (i).(Unmarshaler)
if err := custom.Unmarshal(b); err != nil {
return err
}
if custom != nil {
setCustomType(base, p.field, custom)
}
return nil
}
// Decode a slice of bytes ([]byte) into a slice of custom types.
func (o *Buffer) dec_custom_slice_bytes(p *Properties, base structPointer) error {
b, err := o.DecodeRawBytes(true)
if err != nil {
return err
}
i := reflect.New(p.ctype.Elem()).Interface()
custom := (i).(Unmarshaler)
if err := custom.Unmarshal(b); err != nil {
return err
}
newBas := appendStructPointer(base, p.field, p.ctype)
var zero field
setCustomType(newBas, zero, custom)
return nil
}

View file

@ -40,10 +40,7 @@ import (
tpb "github.com/gogo/protobuf/proto/proto3_proto"
)
var (
bytesBlackhole []byte
msgBlackhole = new(tpb.Message)
)
var msgBlackhole = new(tpb.Message)
// Disabled this Benchmark because it is using features (b.Run) from go1.7 and gogoprotobuf still have compatibility with go1.5
// BenchmarkVarint32ArraySmall shows the performance on an array of small int32 fields (1 and

View file

@ -35,8 +35,14 @@ import (
"fmt"
"reflect"
"strings"
"sync"
"sync/atomic"
)
type generatedDiscarder interface {
XXX_DiscardUnknown()
}
// DiscardUnknown recursively discards all unknown fields from this message
// and all embedded messages.
//
@ -49,9 +55,202 @@ import (
// For proto2 messages, the unknown fields of message extensions are only
// discarded from messages that have been accessed via GetExtension.
func DiscardUnknown(m Message) {
if m, ok := m.(generatedDiscarder); ok {
m.XXX_DiscardUnknown()
return
}
// TODO: Dynamically populate a InternalMessageInfo for legacy messages,
// but the master branch has no implementation for InternalMessageInfo,
// so it would be more work to replicate that approach.
discardLegacy(m)
}
// DiscardUnknown recursively discards all unknown fields.
func (a *InternalMessageInfo) DiscardUnknown(m Message) {
di := atomicLoadDiscardInfo(&a.discard)
if di == nil {
di = getDiscardInfo(reflect.TypeOf(m).Elem())
atomicStoreDiscardInfo(&a.discard, di)
}
di.discard(toPointer(&m))
}
type discardInfo struct {
typ reflect.Type
initialized int32 // 0: only typ is valid, 1: everything is valid
lock sync.Mutex
fields []discardFieldInfo
unrecognized field
}
type discardFieldInfo struct {
field field // Offset of field, guaranteed to be valid
discard func(src pointer)
}
var (
discardInfoMap = map[reflect.Type]*discardInfo{}
discardInfoLock sync.Mutex
)
func getDiscardInfo(t reflect.Type) *discardInfo {
discardInfoLock.Lock()
defer discardInfoLock.Unlock()
di := discardInfoMap[t]
if di == nil {
di = &discardInfo{typ: t}
discardInfoMap[t] = di
}
return di
}
func (di *discardInfo) discard(src pointer) {
if src.isNil() {
return // Nothing to do.
}
if atomic.LoadInt32(&di.initialized) == 0 {
di.computeDiscardInfo()
}
for _, fi := range di.fields {
sfp := src.offset(fi.field)
fi.discard(sfp)
}
// For proto2 messages, only discard unknown fields in message extensions
// that have been accessed via GetExtension.
if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil {
// Ignore lock since DiscardUnknown is not concurrency safe.
emm, _ := em.extensionsRead()
for _, mx := range emm {
if m, ok := mx.value.(Message); ok {
DiscardUnknown(m)
}
}
}
if di.unrecognized.IsValid() {
*src.offset(di.unrecognized).toBytes() = nil
}
}
func (di *discardInfo) computeDiscardInfo() {
di.lock.Lock()
defer di.lock.Unlock()
if di.initialized != 0 {
return
}
t := di.typ
n := t.NumField()
for i := 0; i < n; i++ {
f := t.Field(i)
if strings.HasPrefix(f.Name, "XXX_") {
continue
}
dfi := discardFieldInfo{field: toField(&f)}
tf := f.Type
// Unwrap tf to get its most basic type.
var isPointer, isSlice bool
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
isSlice = true
tf = tf.Elem()
}
if tf.Kind() == reflect.Ptr {
isPointer = true
tf = tf.Elem()
}
if isPointer && isSlice && tf.Kind() != reflect.Struct {
panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name))
}
switch tf.Kind() {
case reflect.Struct:
switch {
case !isPointer:
panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name))
case isSlice: // E.g., []*pb.T
discardInfo := getDiscardInfo(tf)
dfi.discard = func(src pointer) {
sps := src.getPointerSlice()
for _, sp := range sps {
if !sp.isNil() {
discardInfo.discard(sp)
}
}
}
default: // E.g., *pb.T
discardInfo := getDiscardInfo(tf)
dfi.discard = func(src pointer) {
sp := src.getPointer()
if !sp.isNil() {
discardInfo.discard(sp)
}
}
}
case reflect.Map:
switch {
case isPointer || isSlice:
panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name))
default: // E.g., map[K]V
if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T)
dfi.discard = func(src pointer) {
sm := src.asPointerTo(tf).Elem()
if sm.Len() == 0 {
return
}
for _, key := range sm.MapKeys() {
val := sm.MapIndex(key)
DiscardUnknown(val.Interface().(Message))
}
}
} else {
dfi.discard = func(pointer) {} // Noop
}
}
case reflect.Interface:
// Must be oneof field.
switch {
case isPointer || isSlice:
panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name))
default: // E.g., interface{}
// TODO: Make this faster?
dfi.discard = func(src pointer) {
su := src.asPointerTo(tf).Elem()
if !su.IsNil() {
sv := su.Elem().Elem().Field(0)
if sv.Kind() == reflect.Ptr && sv.IsNil() {
return
}
switch sv.Type().Kind() {
case reflect.Ptr: // Proto struct (e.g., *T)
DiscardUnknown(sv.Interface().(Message))
}
}
}
}
default:
continue
}
di.fields = append(di.fields, dfi)
}
di.unrecognized = invalidField
if f, ok := t.FieldByName("XXX_unrecognized"); ok {
if f.Type != reflect.TypeOf([]byte{}) {
panic("expected XXX_unrecognized to be of type []byte")
}
di.unrecognized = toField(&f)
}
atomic.StoreInt32(&di.initialized, 1)
}
func discardLegacy(m Message) {
v := reflect.ValueOf(m)
if v.Kind() != reflect.Ptr || v.IsNil() {
@ -139,7 +338,7 @@ func discardLegacy(m Message) {
// For proto2 messages, only discard unknown fields in message extensions
// that have been accessed via GetExtension.
if em, ok := extendable(m); ok {
if em, err := extendable(m); err == nil {
// Ignore lock since discardLegacy is not concurrency safe.
emm, _ := em.extensionsRead()
for _, mx := range emm {

169
vendor/github.com/gogo/protobuf/proto/discard_test.go generated vendored Normal file
View file

@ -0,0 +1,169 @@
// 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 proto_test
import (
"testing"
"github.com/gogo/protobuf/proto"
proto3pb "github.com/gogo/protobuf/proto/proto3_proto"
pb "github.com/gogo/protobuf/proto/test_proto"
)
func TestDiscardUnknown(t *testing.T) {
tests := []struct {
desc string
in, want proto.Message
}{{
desc: "Nil",
in: nil, want: nil, // Should not panic
}, {
desc: "NilPtr",
in: (*proto3pb.Message)(nil), want: (*proto3pb.Message)(nil), // Should not panic
}, {
desc: "Nested",
in: &proto3pb.Message{
Name: "Aaron",
Nested: &proto3pb.Nested{Cute: true, XXX_unrecognized: []byte("blah")},
XXX_unrecognized: []byte("blah"),
},
want: &proto3pb.Message{
Name: "Aaron",
Nested: &proto3pb.Nested{Cute: true},
},
}, {
desc: "Slice",
in: &proto3pb.Message{
Name: "Aaron",
Children: []*proto3pb.Message{
{Name: "Sarah", XXX_unrecognized: []byte("blah")},
{Name: "Abraham", XXX_unrecognized: []byte("blah")},
},
XXX_unrecognized: []byte("blah"),
},
want: &proto3pb.Message{
Name: "Aaron",
Children: []*proto3pb.Message{
{Name: "Sarah"},
{Name: "Abraham"},
},
},
}, {
desc: "OneOf",
in: &pb.Communique{
Union: &pb.Communique_Msg{Msg: &pb.Strings{
StringField: proto.String("123"),
XXX_unrecognized: []byte("blah"),
}},
XXX_unrecognized: []byte("blah"),
},
want: &pb.Communique{
Union: &pb.Communique_Msg{Msg: &pb.Strings{StringField: proto.String("123")}},
},
}, {
desc: "Map",
in: &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{
0x4002: {
Exact: proto.Bool(true),
XXX_unrecognized: []byte("blah"),
},
}},
want: &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{
0x4002: {Exact: proto.Bool(true)},
}},
}, {
desc: "Extension",
in: func() proto.Message {
m := &pb.MyMessage{
Count: proto.Int32(42),
Somegroup: &pb.MyMessage_SomeGroup{
GroupField: proto.Int32(6),
XXX_unrecognized: []byte("blah"),
},
XXX_unrecognized: []byte("blah"),
}
proto.SetExtension(m, pb.E_Ext_More, &pb.Ext{
Data: proto.String("extension"),
XXX_unrecognized: []byte("blah"),
})
return m
}(),
want: func() proto.Message {
m := &pb.MyMessage{
Count: proto.Int32(42),
Somegroup: &pb.MyMessage_SomeGroup{GroupField: proto.Int32(6)},
}
proto.SetExtension(m, pb.E_Ext_More, &pb.Ext{Data: proto.String("extension")})
return m
}(),
}}
// Test the legacy code path.
for _, tt := range tests {
// Clone the input so that we don't alter the original.
in := tt.in
if in != nil {
in = proto.Clone(tt.in)
}
var m LegacyMessage
m.Message, _ = in.(*proto3pb.Message)
m.Communique, _ = in.(*pb.Communique)
m.MessageWithMap, _ = in.(*pb.MessageWithMap)
m.MyMessage, _ = in.(*pb.MyMessage)
proto.DiscardUnknown(&m)
if !proto.Equal(in, tt.want) {
t.Errorf("test %s/Legacy, expected unknown fields to be discarded\ngot %v\nwant %v", tt.desc, in, tt.want)
}
}
for _, tt := range tests {
proto.DiscardUnknown(tt.in)
if !proto.Equal(tt.in, tt.want) {
t.Errorf("test %s, expected unknown fields to be discarded\ngot %v\nwant %v", tt.desc, tt.in, tt.want)
}
}
}
// LegacyMessage is a proto.Message that has several nested messages.
// This does not have the XXX_DiscardUnknown method and so forces DiscardUnknown
// to use the legacy fallback logic.
type LegacyMessage struct {
Message *proto3pb.Message
Communique *pb.Communique
MessageWithMap *pb.MessageWithMap
MyMessage *pb.MyMessage
}
func (m *LegacyMessage) Reset() { *m = LegacyMessage{} }
func (m *LegacyMessage) String() string { return proto.CompactTextString(m) }
func (*LegacyMessage) ProtoMessage() {}

View file

@ -47,157 +47,3 @@ func (*duration) String() string { return "duration<string>" }
func init() {
RegisterType((*duration)(nil), "gogo.protobuf.proto.duration")
}
func (o *Buffer) decDuration() (time.Duration, error) {
b, err := o.DecodeRawBytes(true)
if err != nil {
return 0, err
}
dproto := &duration{}
if err := Unmarshal(b, dproto); err != nil {
return 0, err
}
return durationFromProto(dproto)
}
func (o *Buffer) dec_duration(p *Properties, base structPointer) error {
d, err := o.decDuration()
if err != nil {
return err
}
word64_Set(structPointer_Word64(base, p.field), o, uint64(d))
return nil
}
func (o *Buffer) dec_ref_duration(p *Properties, base structPointer) error {
d, err := o.decDuration()
if err != nil {
return err
}
word64Val_Set(structPointer_Word64Val(base, p.field), o, uint64(d))
return nil
}
func (o *Buffer) dec_slice_duration(p *Properties, base structPointer) error {
d, err := o.decDuration()
if err != nil {
return err
}
newBas := appendStructPointer(base, p.field, reflect.SliceOf(reflect.PtrTo(durationType)))
var zero field
setPtrCustomType(newBas, zero, &d)
return nil
}
func (o *Buffer) dec_slice_ref_duration(p *Properties, base structPointer) error {
d, err := o.decDuration()
if err != nil {
return err
}
structPointer_Word64Slice(base, p.field).Append(uint64(d))
return nil
}
func size_duration(p *Properties, base structPointer) (n int) {
structp := structPointer_GetStructPointer(base, p.field)
if structPointer_IsNil(structp) {
return 0
}
dur := structPointer_Interface(structp, durationType).(*time.Duration)
d := durationProto(*dur)
size := Size(d)
return size + sizeVarint(uint64(size)) + len(p.tagcode)
}
func (o *Buffer) enc_duration(p *Properties, base structPointer) error {
structp := structPointer_GetStructPointer(base, p.field)
if structPointer_IsNil(structp) {
return ErrNil
}
dur := structPointer_Interface(structp, durationType).(*time.Duration)
d := durationProto(*dur)
data, err := Marshal(d)
if err != nil {
return err
}
o.buf = append(o.buf, p.tagcode...)
o.EncodeRawBytes(data)
return nil
}
func size_ref_duration(p *Properties, base structPointer) (n int) {
dur := structPointer_InterfaceAt(base, p.field, durationType).(*time.Duration)
d := durationProto(*dur)
size := Size(d)
return size + sizeVarint(uint64(size)) + len(p.tagcode)
}
func (o *Buffer) enc_ref_duration(p *Properties, base structPointer) error {
dur := structPointer_InterfaceAt(base, p.field, durationType).(*time.Duration)
d := durationProto(*dur)
data, err := Marshal(d)
if err != nil {
return err
}
o.buf = append(o.buf, p.tagcode...)
o.EncodeRawBytes(data)
return nil
}
func size_slice_duration(p *Properties, base structPointer) (n int) {
pdurs := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(reflect.PtrTo(durationType))).(*[]*time.Duration)
durs := *pdurs
for i := 0; i < len(durs); i++ {
if durs[i] == nil {
return 0
}
dproto := durationProto(*durs[i])
size := Size(dproto)
n += len(p.tagcode) + size + sizeVarint(uint64(size))
}
return n
}
func (o *Buffer) enc_slice_duration(p *Properties, base structPointer) error {
pdurs := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(reflect.PtrTo(durationType))).(*[]*time.Duration)
durs := *pdurs
for i := 0; i < len(durs); i++ {
if durs[i] == nil {
return errRepeatedHasNil
}
dproto := durationProto(*durs[i])
data, err := Marshal(dproto)
if err != nil {
return err
}
o.buf = append(o.buf, p.tagcode...)
o.EncodeRawBytes(data)
}
return nil
}
func size_slice_ref_duration(p *Properties, base structPointer) (n int) {
pdurs := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(durationType)).(*[]time.Duration)
durs := *pdurs
for i := 0; i < len(durs); i++ {
dproto := durationProto(durs[i])
size := Size(dproto)
n += len(p.tagcode) + size + sizeVarint(uint64(size))
}
return n
}
func (o *Buffer) enc_slice_ref_duration(p *Properties, base structPointer) error {
pdurs := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(durationType)).(*[]time.Duration)
durs := *pdurs
for i := 0; i < len(durs); i++ {
dproto := durationProto(durs[i])
data, err := Marshal(dproto)
if err != nil {
return err
}
o.buf = append(o.buf, p.tagcode...)
o.EncodeRawBytes(data)
}
return nil
}

File diff suppressed because it is too large Load diff

View file

@ -3,11 +3,6 @@
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors. All rights reserved.
// http://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:
@ -18,9 +13,6 @@
// 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
@ -36,315 +28,6 @@
package proto
import (
"reflect"
)
func NewRequiredNotSetError(field string) *RequiredNotSetError {
return &RequiredNotSetError{field}
}
type Sizer interface {
Size() int
}
func (o *Buffer) enc_ext_slice_byte(p *Properties, base structPointer) error {
s := *structPointer_Bytes(base, p.field)
if s == nil {
return ErrNil
}
o.buf = append(o.buf, s...)
return nil
}
func size_ext_slice_byte(p *Properties, base structPointer) (n int) {
s := *structPointer_Bytes(base, p.field)
if s == nil {
return 0
}
n += len(s)
return
}
// Encode a reference to bool pointer.
func (o *Buffer) enc_ref_bool(p *Properties, base structPointer) error {
v := *structPointer_BoolVal(base, p.field)
x := 0
if v {
x = 1
}
o.buf = append(o.buf, p.tagcode...)
p.valEnc(o, uint64(x))
return nil
}
func size_ref_bool(p *Properties, base structPointer) int {
return len(p.tagcode) + 1 // each bool takes exactly one byte
}
// Encode a reference to int32 pointer.
func (o *Buffer) enc_ref_int32(p *Properties, base structPointer) error {
v := structPointer_Word32Val(base, p.field)
x := int32(word32Val_Get(v))
o.buf = append(o.buf, p.tagcode...)
p.valEnc(o, uint64(x))
return nil
}
func size_ref_int32(p *Properties, base structPointer) (n int) {
v := structPointer_Word32Val(base, p.field)
x := int32(word32Val_Get(v))
n += len(p.tagcode)
n += p.valSize(uint64(x))
return
}
func (o *Buffer) enc_ref_uint32(p *Properties, base structPointer) error {
v := structPointer_Word32Val(base, p.field)
x := word32Val_Get(v)
o.buf = append(o.buf, p.tagcode...)
p.valEnc(o, uint64(x))
return nil
}
func size_ref_uint32(p *Properties, base structPointer) (n int) {
v := structPointer_Word32Val(base, p.field)
x := word32Val_Get(v)
n += len(p.tagcode)
n += p.valSize(uint64(x))
return
}
// Encode a reference to an int64 pointer.
func (o *Buffer) enc_ref_int64(p *Properties, base structPointer) error {
v := structPointer_Word64Val(base, p.field)
x := word64Val_Get(v)
o.buf = append(o.buf, p.tagcode...)
p.valEnc(o, x)
return nil
}
func size_ref_int64(p *Properties, base structPointer) (n int) {
v := structPointer_Word64Val(base, p.field)
x := word64Val_Get(v)
n += len(p.tagcode)
n += p.valSize(x)
return
}
// Encode a reference to a string pointer.
func (o *Buffer) enc_ref_string(p *Properties, base structPointer) error {
v := *structPointer_StringVal(base, p.field)
o.buf = append(o.buf, p.tagcode...)
o.EncodeStringBytes(v)
return nil
}
func size_ref_string(p *Properties, base structPointer) (n int) {
v := *structPointer_StringVal(base, p.field)
n += len(p.tagcode)
n += sizeStringBytes(v)
return
}
// Encode a reference to a message struct.
func (o *Buffer) enc_ref_struct_message(p *Properties, base structPointer) error {
var state errorState
structp := structPointer_GetRefStructPointer(base, p.field)
if structPointer_IsNil(structp) {
return ErrNil
}
// Can the object marshal itself?
if p.isMarshaler {
m := structPointer_Interface(structp, p.stype).(Marshaler)
data, err := m.Marshal()
if err != nil && !state.shouldContinue(err, nil) {
return err
}
o.buf = append(o.buf, p.tagcode...)
o.EncodeRawBytes(data)
return nil
}
o.buf = append(o.buf, p.tagcode...)
return o.enc_len_struct(p.sprop, structp, &state)
}
//TODO this is only copied, please fix this
func size_ref_struct_message(p *Properties, base structPointer) int {
structp := structPointer_GetRefStructPointer(base, p.field)
if structPointer_IsNil(structp) {
return 0
}
// Can the object marshal itself?
if p.isMarshaler {
m := structPointer_Interface(structp, p.stype).(Marshaler)
data, _ := m.Marshal()
n0 := len(p.tagcode)
n1 := sizeRawBytes(data)
return n0 + n1
}
n0 := len(p.tagcode)
n1 := size_struct(p.sprop, structp)
n2 := sizeVarint(uint64(n1)) // size of encoded length
return n0 + n1 + n2
}
// Encode a slice of references to message struct pointers ([]struct).
func (o *Buffer) enc_slice_ref_struct_message(p *Properties, base structPointer) error {
var state errorState
ss := structPointer_StructRefSlice(base, p.field, p.stype.Size())
l := ss.Len()
for i := 0; i < l; i++ {
structp := ss.Index(i)
if structPointer_IsNil(structp) {
return errRepeatedHasNil
}
// Can the object marshal itself?
if p.isMarshaler {
m := structPointer_Interface(structp, p.stype).(Marshaler)
data, err := m.Marshal()
if err != nil && !state.shouldContinue(err, nil) {
return err
}
o.buf = append(o.buf, p.tagcode...)
o.EncodeRawBytes(data)
continue
}
o.buf = append(o.buf, p.tagcode...)
err := o.enc_len_struct(p.sprop, structp, &state)
if err != nil && !state.shouldContinue(err, nil) {
if err == ErrNil {
return errRepeatedHasNil
}
return err
}
}
return state.err
}
//TODO this is only copied, please fix this
func size_slice_ref_struct_message(p *Properties, base structPointer) (n int) {
ss := structPointer_StructRefSlice(base, p.field, p.stype.Size())
l := ss.Len()
n += l * len(p.tagcode)
for i := 0; i < l; i++ {
structp := ss.Index(i)
if structPointer_IsNil(structp) {
return // return the size up to this point
}
// Can the object marshal itself?
if p.isMarshaler {
m := structPointer_Interface(structp, p.stype).(Marshaler)
data, _ := m.Marshal()
n += len(p.tagcode)
n += sizeRawBytes(data)
continue
}
n0 := size_struct(p.sprop, structp)
n1 := sizeVarint(uint64(n0)) // size of encoded length
n += n0 + n1
}
return
}
func (o *Buffer) enc_custom_bytes(p *Properties, base structPointer) error {
i := structPointer_InterfaceRef(base, p.field, p.ctype)
if i == nil {
return ErrNil
}
custom := i.(Marshaler)
data, err := custom.Marshal()
if err != nil {
return err
}
if data == nil {
return ErrNil
}
o.buf = append(o.buf, p.tagcode...)
o.EncodeRawBytes(data)
return nil
}
func size_custom_bytes(p *Properties, base structPointer) (n int) {
n += len(p.tagcode)
i := structPointer_InterfaceRef(base, p.field, p.ctype)
if i == nil {
return 0
}
custom := i.(Marshaler)
data, _ := custom.Marshal()
n += sizeRawBytes(data)
return
}
func (o *Buffer) enc_custom_ref_bytes(p *Properties, base structPointer) error {
custom := structPointer_InterfaceAt(base, p.field, p.ctype).(Marshaler)
data, err := custom.Marshal()
if err != nil {
return err
}
if data == nil {
return ErrNil
}
o.buf = append(o.buf, p.tagcode...)
o.EncodeRawBytes(data)
return nil
}
func size_custom_ref_bytes(p *Properties, base structPointer) (n int) {
n += len(p.tagcode)
i := structPointer_InterfaceAt(base, p.field, p.ctype)
if i == nil {
return 0
}
custom := i.(Marshaler)
data, _ := custom.Marshal()
n += sizeRawBytes(data)
return
}
func (o *Buffer) enc_custom_slice_bytes(p *Properties, base structPointer) error {
inter := structPointer_InterfaceRef(base, p.field, p.ctype)
if inter == nil {
return ErrNil
}
slice := reflect.ValueOf(inter)
l := slice.Len()
for i := 0; i < l; i++ {
v := slice.Index(i)
custom := v.Interface().(Marshaler)
data, err := custom.Marshal()
if err != nil {
return err
}
o.buf = append(o.buf, p.tagcode...)
o.EncodeRawBytes(data)
}
return nil
}
func size_custom_slice_bytes(p *Properties, base structPointer) (n int) {
inter := structPointer_InterfaceRef(base, p.field, p.ctype)
if inter == nil {
return 0
}
slice := reflect.ValueOf(inter)
l := slice.Len()
n += l * len(p.tagcode)
for i := 0; i < l; i++ {
v := slice.Index(i)
custom := v.Interface().(Marshaler)
data, _ := custom.Marshal()
n += sizeRawBytes(data)
}
return
}

View file

@ -109,15 +109,6 @@ func equalStruct(v1, v2 reflect.Value) bool {
// set/unset mismatch
return false
}
b1, ok := f1.Interface().(raw)
if ok {
b2 := f2.Interface().(raw)
// RawMessage
if !bytes.Equal(b1.Bytes(), b2.Bytes()) {
return false
}
continue
}
f1, f2 = f1.Elem(), f2.Elem()
}
if !equalAny(f1, f2, sprop.Prop[i]) {
@ -146,11 +137,7 @@ func equalStruct(v1, v2 reflect.Value) bool {
u1 := uf.Bytes()
u2 := v2.FieldByName("XXX_unrecognized").Bytes()
if !bytes.Equal(u1, u2) {
return false
}
return true
return bytes.Equal(u1, u2)
}
// v1 and v2 are known to have the same type.
@ -261,6 +248,15 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
m1, m2 := e1.value, e2.value
if m1 == nil && m2 == nil {
// Both have only encoded form.
if bytes.Equal(e1.enc, e2.enc) {
continue
}
// The bytes are different, but the extensions might still be
// equal. We need to decode them to compare.
}
if m1 != nil && m2 != nil {
// Both are unencoded.
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
@ -276,8 +272,12 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
desc = m[extNum]
}
if desc == nil {
// If both have only encoded form and the bytes are the same,
// it is handled above. We get here when the bytes are different.
// We don't know how to decode it, so just compare them as byte
// slices.
log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
continue
return false
}
var err error
if m1 == nil {

View file

@ -36,7 +36,7 @@ import (
. "github.com/gogo/protobuf/proto"
proto3pb "github.com/gogo/protobuf/proto/proto3_proto"
pb "github.com/gogo/protobuf/proto/testdata"
pb "github.com/gogo/protobuf/proto/test_proto"
)
// Four identical base messages.
@ -45,6 +45,9 @@ var messageWithoutExtension = &pb.MyMessage{Count: Int32(7)}
var messageWithExtension1a = &pb.MyMessage{Count: Int32(7)}
var messageWithExtension1b = &pb.MyMessage{Count: Int32(7)}
var messageWithExtension2 = &pb.MyMessage{Count: Int32(7)}
var messageWithExtension3a = &pb.MyMessage{Count: Int32(7)}
var messageWithExtension3b = &pb.MyMessage{Count: Int32(7)}
var messageWithExtension3c = &pb.MyMessage{Count: Int32(7)}
// Two messages with non-message extensions.
var messageWithInt32Extension1 = &pb.MyMessage{Count: Int32(8)}
@ -83,6 +86,20 @@ func init() {
if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(24)); err != nil {
panic("SetExtension on Int32-2 failed: " + err.Error())
}
// messageWithExtension3{a,b,c} has unregistered extension.
if RegisteredExtensions(messageWithExtension3a)[200] != nil {
panic("expect extension 200 unregistered")
}
bytes := []byte{
0xc0, 0x0c, 0x01, // id=200, wiretype=0 (varint), data=1
}
bytes2 := []byte{
0xc0, 0x0c, 0x02, // id=200, wiretype=0 (varint), data=2
}
SetRawExtension(messageWithExtension3a, 200, bytes)
SetRawExtension(messageWithExtension3b, 200, bytes)
SetRawExtension(messageWithExtension3c, 200, bytes2)
}
var EqualTests = []struct {
@ -142,6 +159,9 @@ var EqualTests = []struct {
{"int32 extension vs. itself", messageWithInt32Extension1, messageWithInt32Extension1, true},
{"int32 extension vs. a different int32", messageWithInt32Extension1, messageWithInt32Extension2, false},
{"unregistered extension same", messageWithExtension3a, messageWithExtension3b, true},
{"unregistered extension different", messageWithExtension3a, messageWithExtension3c, false},
{
"message with group",
&pb.MyMessage{

View file

@ -38,6 +38,7 @@ package proto
import (
"errors"
"fmt"
"io"
"reflect"
"strconv"
"sync"
@ -69,12 +70,6 @@ type extendableProtoV1 interface {
ExtensionMap() map[int32]Extension
}
type extensionsBytes interface {
Message
ExtensionRangeArray() []ExtensionRange
GetExtensions() *[]byte
}
// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto.
type extensionAdapter struct {
extendableProtoV1
@ -97,14 +92,31 @@ func (n notLocker) Unlock() {}
// extendable returns the extendableProto interface for the given generated proto message.
// If the proto message has the old extension format, it returns a wrapper that implements
// the extendableProto interface.
func extendable(p interface{}) (extendableProto, bool) {
if ep, ok := p.(extendableProto); ok {
return ep, ok
func extendable(p interface{}) (extendableProto, error) {
switch p := p.(type) {
case extendableProto:
if isNilPtr(p) {
return nil, fmt.Errorf("proto: nil %T is not extendable", p)
}
return p, nil
case extendableProtoV1:
if isNilPtr(p) {
return nil, fmt.Errorf("proto: nil %T is not extendable", p)
}
return extensionAdapter{p}, nil
case extensionsBytes:
return slowExtensionAdapter{p}, nil
}
if ep, ok := p.(extendableProtoV1); ok {
return extensionAdapter{ep}, ok
}
return nil, false
// Don't allocate a specific error containing %T:
// this is the hot path for Clone and MarshalText.
return nil, errNotExtendable
}
var errNotExtendable = errors.New("proto: not an extendable proto.Message")
func isNilPtr(x interface{}) bool {
v := reflect.ValueOf(x)
return v.Kind() == reflect.Ptr && v.IsNil()
}
// XXX_InternalExtensions is an internal representation of proto extensions.
@ -149,16 +161,6 @@ func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Loc
return e.p.extensionMap, &e.p.mu
}
type extensionRange interface {
Message
ExtensionRangeArray() []ExtensionRange
}
var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem()
var extendableBytesType = reflect.TypeOf((*extensionsBytes)(nil)).Elem()
var extensionRangeType = reflect.TypeOf((*extensionRange)(nil)).Elem()
// ExtensionDesc represents an extension specification.
// Used in generated code from the protocol compiler.
type ExtensionDesc struct {
@ -198,8 +200,8 @@ func SetRawExtension(base Message, id int32, b []byte) {
*ext = append(*ext, b...)
return
}
epb, ok := extendable(base)
if !ok {
epb, err := extendable(base)
if err != nil {
return
}
extmap := epb.extensionsWrite()
@ -207,7 +209,7 @@ func SetRawExtension(base Message, id int32, b []byte) {
}
// isExtensionField returns true iff the given field number is in an extension range.
func isExtensionField(pb extensionRange, field int32) bool {
func isExtensionField(pb extendableProto, field int32) bool {
for _, er := range pb.ExtensionRangeArray() {
if er.Start <= field && field <= er.End {
return true
@ -223,8 +225,11 @@ func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
if ea, ok := pbi.(extensionAdapter); ok {
pbi = ea.extendableProtoV1
}
if ea, ok := pbi.(slowExtensionAdapter); ok {
pbi = ea.extensionsBytes
}
if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a)
}
// Check the range.
if !isExtensionField(pb, extension.Field) {
@ -269,80 +274,6 @@ func extensionProperties(ed *ExtensionDesc) *Properties {
return prop
}
// encode encodes any unmarshaled (unencoded) extensions in e.
func encodeExtensions(e *XXX_InternalExtensions) error {
m, mu := e.extensionsRead()
if m == nil {
return nil // fast path
}
mu.Lock()
defer mu.Unlock()
return encodeExtensionsMap(m)
}
// encode encodes any unmarshaled (unencoded) extensions in e.
func encodeExtensionsMap(m map[int32]Extension) error {
for k, e := range m {
if e.value == nil || e.desc == nil {
// Extension is only in its encoded form.
continue
}
// We don't skip extensions that have an encoded form set,
// because the extension value may have been mutated after
// the last time this function was called.
et := reflect.TypeOf(e.desc.ExtensionType)
props := extensionProperties(e.desc)
p := NewBuffer(nil)
// If e.value has type T, the encoder expects a *struct{ X T }.
// Pass a *T with a zero field and hope it all works out.
x := reflect.New(et)
x.Elem().Set(reflect.ValueOf(e.value))
if err := props.enc(p, props, toStructPointer(x)); err != nil {
return err
}
e.enc = p.buf
m[k] = e
}
return nil
}
func extensionsSize(e *XXX_InternalExtensions) (n int) {
m, mu := e.extensionsRead()
if m == nil {
return 0
}
mu.Lock()
defer mu.Unlock()
return extensionsMapSize(m)
}
func extensionsMapSize(m map[int32]Extension) (n int) {
for _, e := range m {
if e.value == nil || e.desc == nil {
// Extension is only in its encoded form.
n += len(e.enc)
continue
}
// We don't skip extensions that have an encoded form set,
// because the extension value may have been mutated after
// the last time this function was called.
et := reflect.TypeOf(e.desc.ExtensionType)
props := extensionProperties(e.desc)
// If e.value has type T, the encoder expects a *struct{ X T }.
// Pass a *T with a zero field and hope it all works out.
x := reflect.New(et)
x.Elem().Set(reflect.ValueOf(e.value))
n += props.size(props, toStructPointer(x))
}
return
}
// HasExtension returns whether the given extension is present in pb.
func HasExtension(pb Message, extension *ExtensionDesc) bool {
if epb, doki := pb.(extensionsBytes); doki {
@ -366,8 +297,8 @@ func HasExtension(pb Message, extension *ExtensionDesc) bool {
return false
}
// TODO: Check types, field numbers, etc.?
epb, ok := extendable(pb)
if !ok {
epb, err := extendable(pb)
if err != nil {
return false
}
extmap, mu := epb.extensionsRead()
@ -375,46 +306,26 @@ func HasExtension(pb Message, extension *ExtensionDesc) bool {
return false
}
mu.Lock()
_, ok = extmap[extension.Field]
_, ok := extmap[extension.Field]
mu.Unlock()
return ok
}
func deleteExtension(pb extensionsBytes, theFieldNum int32, offset int) int {
ext := pb.GetExtensions()
for offset < len(*ext) {
tag, n1 := DecodeVarint((*ext)[offset:])
fieldNum := int32(tag >> 3)
wireType := int(tag & 0x7)
n2, err := size((*ext)[offset+n1:], wireType)
if err != nil {
panic(err)
}
newOffset := offset + n1 + n2
if fieldNum == theFieldNum {
*ext = append((*ext)[:offset], (*ext)[newOffset:]...)
return offset
}
offset = newOffset
}
return -1
}
// ClearExtension removes the given extension from pb.
func ClearExtension(pb Message, extension *ExtensionDesc) {
clearExtension(pb, extension.Field)
}
func clearExtension(pb Message, fieldNum int32) {
if epb, doki := pb.(extensionsBytes); doki {
if epb, ok := pb.(extensionsBytes); ok {
offset := 0
for offset != -1 {
offset = deleteExtension(epb, fieldNum, offset)
}
return
}
epb, ok := extendable(pb)
if !ok {
epb, err := extendable(pb)
if err != nil {
return
}
// TODO: Check types, field numbers, etc.?
@ -422,39 +333,33 @@ func clearExtension(pb Message, fieldNum int32) {
delete(extmap, fieldNum)
}
// GetExtension parses and returns the given extension of pb.
// If the extension is not present and has no default value it returns ErrMissingExtension.
// GetExtension retrieves a proto2 extended field from pb.
//
// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
// then GetExtension parses the encoded field and returns a Go value of the specified type.
// If the field is not present, then the default value is returned (if one is specified),
// otherwise ErrMissingExtension is reported.
//
// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil),
// then GetExtension returns the raw encoded bytes of the field extension.
func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
if epb, doki := pb.(extensionsBytes); doki {
ext := epb.GetExtensions()
o := 0
for o < len(*ext) {
tag, n := DecodeVarint((*ext)[o:])
fieldNum := int32(tag >> 3)
wireType := int(tag & 0x7)
l, err := size((*ext)[o+n:], wireType)
if err != nil {
return nil, err
}
if int32(fieldNum) == extension.Field {
v, err := decodeExtension((*ext)[o:o+n+l], extension)
if err != nil {
return nil, err
}
return v, nil
}
o += n + l
}
return defaultExtensionValue(extension)
return decodeExtensionFromBytes(extension, *ext)
}
epb, ok := extendable(pb)
if !ok {
return nil, errors.New("proto: not an extendable proto")
}
if err := checkExtensionTypes(epb, extension); err != nil {
epb, err := extendable(pb)
if err != nil {
return nil, err
}
if extension.ExtendedType != nil {
// can only check type if this is a complete descriptor
if cerr := checkExtensionTypes(epb, extension); cerr != nil {
return nil, cerr
}
}
emap, mu := epb.extensionsRead()
if emap == nil {
return defaultExtensionValue(extension)
@ -479,6 +384,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
return e.value, nil
}
if extension.ExtensionType == nil {
// incomplete descriptor
return e.enc, nil
}
v, err := decodeExtension(e.enc, extension)
if err != nil {
return nil, err
@ -496,6 +406,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
// defaultExtensionValue returns the default value for extension.
// If no default for an extension is defined ErrMissingExtension is returned.
func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
if extension.ExtensionType == nil {
// incomplete descriptor, so no default
return nil, ErrMissingExtension
}
t := reflect.TypeOf(extension.ExtensionType)
props := extensionProperties(extension)
@ -530,31 +445,28 @@ func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
// decodeExtension decodes an extension encoded in b.
func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
o := NewBuffer(b)
t := reflect.TypeOf(extension.ExtensionType)
props := extensionProperties(extension)
unmarshal := typeUnmarshaler(t, extension.Tag)
// t is a pointer to a struct, pointer to basic type or a slice.
// Allocate a "field" to store the pointer/slice itself; the
// pointer/slice will be stored here. We pass
// the address of this field to props.dec.
// This passes a zero field and a *t and lets props.dec
// interpret it as a *struct{ x t }.
// Allocate space to store the pointer/slice.
value := reflect.New(t).Elem()
var err error
for {
// Discard wire type and field number varint. It isn't needed.
if _, err := o.DecodeVarint(); err != nil {
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
wire := int(x) & 7
b, err = unmarshal(b, valToPointer(value.Addr()), wire)
if err != nil {
return nil, err
}
if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil {
return nil, err
}
if o.index >= len(o.buf) {
if len(b) == 0 {
break
}
}
@ -564,9 +476,13 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
// The returned slice has the same length as es; missing extensions will appear as nil elements.
func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
epb, err := extendable(pb)
if err != nil {
return nil, err
}
extensions = make([]interface{}, len(es))
for i, e := range es {
extensions[i], err = GetExtension(pb, e)
extensions[i], err = GetExtension(epb, e)
if err == ErrMissingExtension {
err = nil
}
@ -581,9 +497,9 @@ func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, e
// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
// just the Field field, which defines the extension's field number.
func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
epb, ok := extendable(pb)
if !ok {
return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb)
epb, err := extendable(pb)
if err != nil {
return nil, err
}
registeredExtensions := RegisteredExtensions(pb)
@ -610,23 +526,18 @@ func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
// SetExtension sets the specified extension of pb to the specified value.
func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
if epb, doki := pb.(extensionsBytes); doki {
ClearExtension(pb, extension)
ext := epb.GetExtensions()
et := reflect.TypeOf(extension.ExtensionType)
props := extensionProperties(extension)
p := NewBuffer(nil)
x := reflect.New(et)
x.Elem().Set(reflect.ValueOf(value))
if err := props.enc(p, props, toStructPointer(x)); err != nil {
if epb, ok := pb.(extensionsBytes); ok {
newb, err := encodeExtension(extension, value)
if err != nil {
return err
}
*ext = append(*ext, p.buf...)
bb := epb.GetExtensions()
*bb = append(*bb, newb...)
return nil
}
epb, ok := extendable(pb)
if !ok {
return errors.New("proto: not an extendable proto")
epb, err := extendable(pb)
if err != nil {
return err
}
if err := checkExtensionTypes(epb, extension); err != nil {
return err
@ -656,8 +567,8 @@ func ClearAllExtensions(pb Message) {
*ext = []byte{}
return
}
epb, ok := extendable(pb)
if !ok {
epb, err := extendable(pb)
if err != nil {
return
}
m := epb.extensionsWrite()

View file

@ -32,12 +32,36 @@ import (
"bytes"
"errors"
"fmt"
"io"
"reflect"
"sort"
"strings"
"sync"
)
type extensionsBytes interface {
Message
ExtensionRangeArray() []ExtensionRange
GetExtensions() *[]byte
}
type slowExtensionAdapter struct {
extensionsBytes
}
func (s slowExtensionAdapter) extensionsWrite() map[int32]Extension {
panic("Please report a bug to github.com/gogo/protobuf if you see this message: Writing extensions is not supported for extensions stored in a byte slice field.")
}
func (s slowExtensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) {
b := s.GetExtensions()
m, err := BytesToExtensionsMap(*b)
if err != nil {
panic(err)
}
return m, notLocker{}
}
func GetBoolExtension(pb Message, extension *ExtensionDesc, ifnotset bool) bool {
if reflect.ValueOf(pb).IsNil() {
return ifnotset
@ -56,19 +80,28 @@ func GetBoolExtension(pb Message, extension *ExtensionDesc, ifnotset bool) bool
}
func (this *Extension) Equal(that *Extension) bool {
if err := this.Encode(); err != nil {
return false
}
if err := that.Encode(); err != nil {
return false
}
return bytes.Equal(this.enc, that.enc)
}
func (this *Extension) Compare(that *Extension) int {
if err := this.Encode(); err != nil {
return 1
}
if err := that.Encode(); err != nil {
return -1
}
return bytes.Compare(this.enc, that.enc)
}
func SizeOfInternalExtension(m extendableProto) (n int) {
return SizeOfExtensionMap(m.extensionsWrite())
}
func SizeOfExtensionMap(m map[int32]Extension) (n int) {
return extensionsMapSize(m)
info := getMarshalInfo(reflect.TypeOf(m))
return info.sizeV1Extensions(m.extensionsWrite())
}
type sortableMapElem struct {
@ -122,28 +155,26 @@ func EncodeInternalExtension(m extendableProto, data []byte) (n int, err error)
}
func EncodeExtensionMap(m map[int32]Extension, data []byte) (n int, err error) {
if err := encodeExtensionsMap(m); err != nil {
return 0, err
o := 0
for _, e := range m {
if err := e.Encode(); err != nil {
return 0, err
}
n := copy(data[o:], e.enc)
if n != len(e.enc) {
return 0, io.ErrShortBuffer
}
o += n
}
keys := make([]int, 0, len(m))
for k := range m {
keys = append(keys, int(k))
}
sort.Ints(keys)
for _, k := range keys {
n += copy(data[n:], m[int32(k)].enc)
}
return n, nil
return o, nil
}
func GetRawExtension(m map[int32]Extension, id int32) ([]byte, error) {
if m[id].value == nil || m[id].desc == nil {
return m[id].enc, nil
}
if err := encodeExtensionsMap(m); err != nil {
e := m[id]
if err := e.Encode(); err != nil {
return nil, err
}
return m[id].enc, nil
return e.enc, nil
}
func size(buf []byte, wire int) (int, error) {
@ -218,35 +249,58 @@ func AppendExtension(e Message, tag int32, buf []byte) {
}
}
func encodeExtension(e *Extension) error {
if e.value == nil || e.desc == nil {
// Extension is only in its encoded form.
return nil
}
// We don't skip extensions that have an encoded form set,
// because the extension value may have been mutated after
// the last time this function was called.
func encodeExtension(extension *ExtensionDesc, value interface{}) ([]byte, error) {
u := getMarshalInfo(reflect.TypeOf(extension.ExtendedType))
ei := u.getExtElemInfo(extension)
v := value
p := toAddrPointer(&v, ei.isptr)
siz := ei.sizer(p, SizeVarint(ei.wiretag))
buf := make([]byte, 0, siz)
return ei.marshaler(buf, p, ei.wiretag, false)
}
et := reflect.TypeOf(e.desc.ExtensionType)
props := extensionProperties(e.desc)
p := NewBuffer(nil)
// If e.value has type T, the encoder expects a *struct{ X T }.
// Pass a *T with a zero field and hope it all works out.
x := reflect.New(et)
x.Elem().Set(reflect.ValueOf(e.value))
if err := props.enc(p, props, toStructPointer(x)); err != nil {
return err
func decodeExtensionFromBytes(extension *ExtensionDesc, buf []byte) (interface{}, error) {
o := 0
for o < len(buf) {
tag, n := DecodeVarint((buf)[o:])
fieldNum := int32(tag >> 3)
wireType := int(tag & 0x7)
if o+n > len(buf) {
return nil, fmt.Errorf("unable to decode extension")
}
l, err := size((buf)[o+n:], wireType)
if err != nil {
return nil, err
}
if int32(fieldNum) == extension.Field {
if o+n+l > len(buf) {
return nil, fmt.Errorf("unable to decode extension")
}
v, err := decodeExtension((buf)[o:o+n+l], extension)
if err != nil {
return nil, err
}
return v, nil
}
o += n + l
}
return defaultExtensionValue(extension)
}
func (this *Extension) Encode() error {
if this.enc == nil {
var err error
this.enc, err = encodeExtension(this.desc, this.value)
if err != nil {
return err
}
}
e.enc = p.buf
return nil
}
func (this Extension) GoString() string {
if this.enc == nil {
if err := encodeExtension(&this); err != nil {
panic(err)
}
if err := this.Encode(); err != nil {
return fmt.Sprintf("error encoding extension: %v", err)
}
return fmt.Sprintf("proto.NewExtension(%#v)", this.enc)
}
@ -292,3 +346,23 @@ func GetUnsafeExtensionsMap(extendable Message) map[int32]Extension {
pb := extendable.(extendableProto)
return pb.extensionsWrite()
}
func deleteExtension(pb extensionsBytes, theFieldNum int32, offset int) int {
ext := pb.GetExtensions()
for offset < len(*ext) {
tag, n1 := DecodeVarint((*ext)[offset:])
fieldNum := int32(tag >> 3)
wireType := int(tag & 0x7)
n2, err := size((*ext)[offset+n1:], wireType)
if err != nil {
panic(err)
}
newOffset := offset + n1 + n2
if fieldNum == theFieldNum {
*ext = append((*ext)[:offset], (*ext)[newOffset:]...)
return offset
}
offset = newOffset
}
return -1
}

View file

@ -34,12 +34,14 @@ package proto_test
import (
"bytes"
"fmt"
"io"
"reflect"
"sort"
"strings"
"testing"
"github.com/gogo/protobuf/proto"
pb "github.com/gogo/protobuf/proto/testdata"
pb "github.com/gogo/protobuf/proto/test_proto"
)
func TestGetExtensionsWithMissingExtensions(t *testing.T) {
@ -63,7 +65,107 @@ func TestGetExtensionsWithMissingExtensions(t *testing.T) {
}
}
func TestExtensionDescsWithMissingExtensions(t *testing.T) {
func TestGetExtensionWithEmptyBuffer(t *testing.T) {
// Make sure that GetExtension returns an error if its
// undecoded buffer is empty.
msg := &pb.MyMessage{}
proto.SetRawExtension(msg, pb.E_Ext_More.Field, []byte{})
_, err := proto.GetExtension(msg, pb.E_Ext_More)
if want := io.ErrUnexpectedEOF; err != want {
t.Errorf("unexpected error in GetExtension from empty buffer: got %v, want %v", err, want)
}
}
func TestGetExtensionForIncompleteDesc(t *testing.T) {
msg := &pb.MyMessage{Count: proto.Int32(0)}
extdesc1 := &proto.ExtensionDesc{
ExtendedType: (*pb.MyMessage)(nil),
ExtensionType: (*bool)(nil),
Field: 123456789,
Name: "a.b",
Tag: "varint,123456789,opt",
}
ext1 := proto.Bool(true)
if err := proto.SetExtension(msg, extdesc1, ext1); err != nil {
t.Fatalf("Could not set ext1: %s", err)
}
extdesc2 := &proto.ExtensionDesc{
ExtendedType: (*pb.MyMessage)(nil),
ExtensionType: ([]byte)(nil),
Field: 123456790,
Name: "a.c",
Tag: "bytes,123456790,opt",
}
ext2 := []byte{0, 1, 2, 3, 4, 5, 6, 7}
if err := proto.SetExtension(msg, extdesc2, ext2); err != nil {
t.Fatalf("Could not set ext2: %s", err)
}
extdesc3 := &proto.ExtensionDesc{
ExtendedType: (*pb.MyMessage)(nil),
ExtensionType: (*pb.Ext)(nil),
Field: 123456791,
Name: "a.d",
Tag: "bytes,123456791,opt",
}
ext3 := &pb.Ext{Data: proto.String("foo")}
if err := proto.SetExtension(msg, extdesc3, ext3); err != nil {
t.Fatalf("Could not set ext3: %s", err)
}
b, err := proto.Marshal(msg)
if err != nil {
t.Fatalf("Could not marshal msg: %v", err)
}
if err := proto.Unmarshal(b, msg); err != nil {
t.Fatalf("Could not unmarshal into msg: %v", err)
}
var expected proto.Buffer
if err := expected.EncodeVarint(uint64((extdesc1.Field << 3) | proto.WireVarint)); err != nil {
t.Fatalf("failed to compute expected prefix for ext1: %s", err)
}
if err := expected.EncodeVarint(1 /* bool true */); err != nil {
t.Fatalf("failed to compute expected value for ext1: %s", err)
}
if b, err := proto.GetExtension(msg, &proto.ExtensionDesc{Field: extdesc1.Field}); err != nil {
t.Fatalf("Failed to get raw value for ext1: %s", err)
} else if !reflect.DeepEqual(b, expected.Bytes()) {
t.Fatalf("Raw value for ext1: got %v, want %v", b, expected.Bytes())
}
expected = proto.Buffer{} // reset
if err := expected.EncodeVarint(uint64((extdesc2.Field << 3) | proto.WireBytes)); err != nil {
t.Fatalf("failed to compute expected prefix for ext2: %s", err)
}
if err := expected.EncodeRawBytes(ext2); err != nil {
t.Fatalf("failed to compute expected value for ext2: %s", err)
}
if b, err := proto.GetExtension(msg, &proto.ExtensionDesc{Field: extdesc2.Field}); err != nil {
t.Fatalf("Failed to get raw value for ext2: %s", err)
} else if !reflect.DeepEqual(b, expected.Bytes()) {
t.Fatalf("Raw value for ext2: got %v, want %v", b, expected.Bytes())
}
expected = proto.Buffer{} // reset
if err := expected.EncodeVarint(uint64((extdesc3.Field << 3) | proto.WireBytes)); err != nil {
t.Fatalf("failed to compute expected prefix for ext3: %s", err)
}
if b, err := proto.Marshal(ext3); err != nil {
t.Fatalf("failed to compute expected value for ext3: %s", err)
} else if err := expected.EncodeRawBytes(b); err != nil {
t.Fatalf("failed to compute expected value for ext3: %s", err)
}
if b, err := proto.GetExtension(msg, &proto.ExtensionDesc{Field: extdesc3.Field}); err != nil {
t.Fatalf("Failed to get raw value for ext3: %s", err)
} else if !reflect.DeepEqual(b, expected.Bytes()) {
t.Fatalf("Raw value for ext3: got %v, want %v", b, expected.Bytes())
}
}
func TestExtensionDescsWithUnregisteredExtensions(t *testing.T) {
msg := &pb.MyMessage{Count: proto.Int32(0)}
extdesc1 := pb.E_Ext_More
if descs, err := proto.ExtensionDescs(msg); len(descs) != 0 || err != nil {
@ -199,7 +301,7 @@ func TestGetExtensionDefaults(t *testing.T) {
{pb.E_DefaultSfixed64, setInt64, int64(51)},
{pb.E_DefaultBool, setBool, true},
{pb.E_DefaultBool, setBool2, true},
{pb.E_DefaultString, setString, "Hello, string"},
{pb.E_DefaultString, setString, "Hello, string,def=foo"},
{pb.E_DefaultBytes, setBytes, []byte("Hello, bytes")},
{pb.E_DefaultEnum, setEnum, pb.DefaultsMessage_ONE},
}
@ -286,6 +388,44 @@ func TestGetExtensionDefaults(t *testing.T) {
}
}
func TestNilMessage(t *testing.T) {
name := "nil interface"
if got, err := proto.GetExtension(nil, pb.E_Ext_More); err == nil {
t.Errorf("%s: got %T %v, expected to fail", name, got, got)
} else if !strings.Contains(err.Error(), "extendable") {
t.Errorf("%s: got error %v, expected not-extendable error", name, err)
}
// Regression tests: all functions of the Extension API
// used to panic when passed (*M)(nil), where M is a concrete message
// type. Now they handle this gracefully as a no-op or reported error.
var nilMsg *pb.MyMessage
desc := pb.E_Ext_More
isNotExtendable := func(err error) bool {
return strings.Contains(fmt.Sprint(err), "not extendable")
}
if proto.HasExtension(nilMsg, desc) {
t.Error("HasExtension(nil) = true")
}
if _, err := proto.GetExtensions(nilMsg, []*proto.ExtensionDesc{desc}); !isNotExtendable(err) {
t.Errorf("GetExtensions(nil) = %q (wrong error)", err)
}
if _, err := proto.ExtensionDescs(nilMsg); !isNotExtendable(err) {
t.Errorf("ExtensionDescs(nil) = %q (wrong error)", err)
}
if err := proto.SetExtension(nilMsg, desc, nil); !isNotExtendable(err) {
t.Errorf("SetExtension(nil) = %q (wrong error)", err)
}
proto.ClearExtension(nilMsg, desc) // no-op
proto.ClearAllExtensions(nilMsg) // no-op
}
func TestExtensionsRoundTrip(t *testing.T) {
msg := &pb.MyMessage{}
ext1 := &pb.Ext{
@ -310,7 +450,7 @@ func TestExtensionsRoundTrip(t *testing.T) {
}
x, ok := e.(*pb.Ext)
if !ok {
t.Errorf("e has type %T, expected testdata.Ext", e)
t.Errorf("e has type %T, expected test_proto.Ext", e)
} else if *x.Data != "there" {
t.Errorf("SetExtension failed to overwrite, got %+v, not 'there'", x)
}
@ -338,7 +478,7 @@ func TestNilExtension(t *testing.T) {
}
if err := proto.SetExtension(msg, pb.E_Ext_More, (*pb.Ext)(nil)); err == nil {
t.Error("expected SetExtension to fail due to a nil extension")
} else if want := "proto: SetExtension called with nil value of type *testdata.Ext"; err.Error() != want {
} else if want := fmt.Sprintf("proto: SetExtension called with nil value of type %T", new(pb.Ext)); err.Error() != want {
t.Errorf("expected error %v, got %v", want, err)
}
// Note: if the behavior of Marshal is ever changed to ignore nil extensions, update
@ -401,8 +541,13 @@ func TestMarshalUnmarshalRepeatedExtension(t *testing.T) {
if ext == nil {
t.Fatalf("[%s] Invalid extension", test.name)
}
if !reflect.DeepEqual(ext, test.ext) {
t.Errorf("[%s] Wrong value for ComplexExtension: got: %v want: %v\n", test.name, ext, test.ext)
if len(ext) != len(test.ext) {
t.Errorf("[%s] Wrong length of ComplexExtension: got: %v want: %v\n", test.name, len(ext), len(test.ext))
}
for i := range test.ext {
if !proto.Equal(ext[i], test.ext[i]) {
t.Errorf("[%s] Wrong value for ComplexExtension[%d]: got: %v want: %v\n", test.name, i, ext[i], test.ext[i])
}
}
}
}
@ -476,8 +621,9 @@ func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) {
if ext == nil {
t.Fatalf("[%s] Invalid extension", test.name)
}
if !reflect.DeepEqual(*ext, want) {
t.Errorf("[%s] Wrong value for ComplexExtension: got: %v want: %v\n", test.name, ext, want)
if !proto.Equal(ext, &want) {
t.Errorf("[%s] Wrong value for ComplexExtension: got: %v want: %v\n", test.name, ext, &want)
}
}
}
@ -508,28 +654,35 @@ func TestClearAllExtensions(t *testing.T) {
}
func TestMarshalRace(t *testing.T) {
// unregistered extension
desc := &proto.ExtensionDesc{
ExtendedType: (*pb.MyMessage)(nil),
ExtensionType: (*bool)(nil),
Field: 101010100,
Name: "emptyextension",
Tag: "varint,0,opt",
}
ext := &pb.Ext{}
m := &pb.MyMessage{Count: proto.Int32(4)}
if err := proto.SetExtension(m, desc, proto.Bool(true)); err != nil {
t.Errorf("proto.SetExtension(m, desc, true): got error %q, want nil", err)
if err := proto.SetExtension(m, pb.E_Ext_More, ext); err != nil {
t.Fatalf("proto.SetExtension(m, desc, true): got error %q, want nil", err)
}
errChan := make(chan error, 3)
b, err := proto.Marshal(m)
if err != nil {
t.Fatalf("Could not marshal message: %v", err)
}
if err := proto.Unmarshal(b, m); err != nil {
t.Fatalf("Could not unmarshal message: %v", err)
}
// after Unmarshal, the extension is in undecoded form.
// GetExtension will decode it lazily. Make sure this does
// not race against Marshal.
errChan := make(chan error, 6)
for n := 3; n > 0; n-- {
go func() {
_, err := proto.Marshal(m)
errChan <- err
}()
go func() {
_, err := proto.GetExtension(m, pb.E_Ext_More)
errChan <- err
}()
}
for i := 0; i < 3; i++ {
for i := 0; i < 6; i++ {
err := <-errChan
if err != nil {
t.Fatal(err)

View file

@ -265,6 +265,7 @@ package proto
import (
"encoding/json"
"errors"
"fmt"
"log"
"reflect"
@ -273,6 +274,8 @@ import (
"sync"
)
var errInvalidUTF8 = errors.New("proto: invalid UTF-8 string")
// Message is implemented by generated protocol buffer messages.
type Message interface {
Reset()
@ -309,16 +312,7 @@ type Buffer struct {
buf []byte // encode/decode byte stream
index int // read point
// pools of basic types to amortize allocation.
bools []bool
uint32s []uint32
uint64s []uint64
// extra pools, only used with pointer_reflect.go
int32s []int32
int64s []int64
float32s []float32
float64s []float64
deterministic bool
}
// NewBuffer allocates a new Buffer and initializes its internal data to
@ -343,6 +337,30 @@ func (p *Buffer) SetBuf(s []byte) {
// Bytes returns the contents of the Buffer.
func (p *Buffer) Bytes() []byte { return p.buf }
// SetDeterministic sets whether to use deterministic serialization.
//
// Deterministic serialization guarantees that for a given binary, equal
// messages will always be serialized to the same bytes. This implies:
//
// - Repeated serialization of a message will return the same bytes.
// - Different processes of the same binary (which may be executing on
// different machines) will serialize equal messages to the same bytes.
//
// Note that the deterministic serialization is NOT canonical across
// languages. It is not guaranteed to remain stable over time. It is unstable
// across different builds with schema changes due to unknown fields.
// Users who need canonical serialization (e.g., persistent storage in a
// canonical form, fingerprinting, etc.) should define their own
// canonicalization specification and implement their own serializer rather
// than relying on this API.
//
// If deterministic serialization is requested, map entries will be sorted
// by keys in lexographical order. This is an implementation detail and
// subject to change.
func (p *Buffer) SetDeterministic(deterministic bool) {
p.deterministic = deterministic
}
/*
* Helper routines for simplifying the creation of optional fields of basic type.
*/
@ -831,22 +849,12 @@ func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMes
return sf, false, nil
}
// mapKeys returns a sort.Interface to be used for sorting the map keys.
// Map fields may have key types of non-float scalars, strings and enums.
// The easiest way to sort them in some deterministic order is to use fmt.
// If this turns out to be inefficient we can always consider other options,
// such as doing a Schwartzian transform.
func mapKeys(vs []reflect.Value) sort.Interface {
s := mapKeySorter{
vs: vs,
// default Less function: textual comparison
less: func(a, b reflect.Value) bool {
return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface())
},
}
s := mapKeySorter{vs: vs}
// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps;
// numeric keys are sorted numerically.
// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps.
if len(vs) == 0 {
return s
}
@ -855,6 +863,12 @@ func mapKeys(vs []reflect.Value) sort.Interface {
s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
case reflect.Uint32, reflect.Uint64:
s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
case reflect.Bool:
s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true
case reflect.String:
s.less = func(a, b reflect.Value) bool { return a.String() < b.String() }
default:
panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind()))
}
return s
@ -895,3 +909,13 @@ const GoGoProtoPackageIsVersion2 = true
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
const GoGoProtoPackageIsVersion1 = true
// InternalMessageInfo is a type used internally by generated .pb.go files.
// This type is not intended to be used by non-generated code.
// This type is not subject to any compatibility guarantee.
type InternalMessageInfo struct {
marshal *marshalInfo
unmarshal *unmarshalInfo
merge *mergeInfo
discard *discardInfo
}

View file

@ -33,6 +33,14 @@ import (
"strconv"
)
type Sizer interface {
Size() int
}
type ProtoSizer interface {
ProtoSize() int
}
func MarshalJSONEnum(m map[int32]string, value int32) ([]byte, error) {
s, ok := m[value]
if !ok {

View file

@ -2,12 +2,36 @@ package proto_test
import (
"fmt"
"reflect"
"testing"
"github.com/gogo/protobuf/proto"
ppb "github.com/gogo/protobuf/proto/proto3_proto"
)
func TestMap(t *testing.T) {
var b []byte
fmt.Sscanf("a2010c0a044b657931120456616c31a201130a044b657932120556616c3261120456616c32a201240a044b6579330d05000000120556616c33621a0556616c3361120456616c331505000000a20100a201260a044b657934130a07536f6d6555524c1209536f6d655469746c651a08536e69707065743114", "%x", &b)
var m ppb.Message
if err := proto.Unmarshal(b, &m); err != nil {
t.Fatalf("proto.Unmarshal error: %v", err)
}
got := m.StringMap
want := map[string]string{
"": "",
"Key1": "Val1",
"Key2": "Val2",
"Key3": "Val3",
"Key4": "",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("maps differ:\ngot %#v\nwant %#v", got, want)
}
}
func marshalled() []byte {
m := &ppb.IntMaps{}
for i := 0; i < 1000; i++ {

View file

@ -42,6 +42,7 @@ import (
"fmt"
"reflect"
"sort"
"sync"
)
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
@ -94,10 +95,7 @@ func (ms *messageSet) find(pb Message) *_MessageSet_Item {
}
func (ms *messageSet) Has(pb Message) bool {
if ms.find(pb) != nil {
return true
}
return false
return ms.find(pb) != nil
}
func (ms *messageSet) Unmarshal(pb Message) error {
@ -150,46 +148,42 @@ func skipVarint(buf []byte) []byte {
// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
func MarshalMessageSet(exts interface{}) ([]byte, error) {
var m map[int32]Extension
return marshalMessageSet(exts, false)
}
// marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal.
func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) {
switch exts := exts.(type) {
case *XXX_InternalExtensions:
if err := encodeExtensions(exts); err != nil {
return nil, err
}
m, _ = exts.extensionsRead()
var u marshalInfo
siz := u.sizeMessageSet(exts)
b := make([]byte, 0, siz)
return u.appendMessageSet(b, exts, deterministic)
case map[int32]Extension:
if err := encodeExtensionsMap(exts); err != nil {
return nil, err
// This is an old-style extension map.
// Wrap it in a new-style XXX_InternalExtensions.
ie := XXX_InternalExtensions{
p: &struct {
mu sync.Mutex
extensionMap map[int32]Extension
}{
extensionMap: exts,
},
}
m = exts
var u marshalInfo
siz := u.sizeMessageSet(&ie)
b := make([]byte, 0, siz)
return u.appendMessageSet(b, &ie, deterministic)
default:
return nil, errors.New("proto: not an extension map")
}
// Sort extension IDs to provide a deterministic encoding.
// See also enc_map in encode.go.
ids := make([]int, 0, len(m))
for id := range m {
ids = append(ids, int(id))
}
sort.Ints(ids)
ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
for _, id := range ids {
e := m[int32(id)]
// Remove the wire type and field number varint, as well as the length varint.
msg := skipVarint(skipVarint(e.enc))
ms.Item = append(ms.Item, &_MessageSet_Item{
TypeId: Int32(int32(id)),
Message: msg,
})
}
return Marshal(ms)
}
// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
func UnmarshalMessageSet(buf []byte, exts interface{}) error {
var m map[int32]Extension
switch exts := exts.(type) {
@ -235,7 +229,15 @@ func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
var m map[int32]Extension
switch exts := exts.(type) {
case *XXX_InternalExtensions:
m, _ = exts.extensionsRead()
var mu sync.Locker
m, mu = exts.extensionsRead()
if m != nil {
// Keep the extensions map locked until we're done marshaling to prevent
// races between marshaling and unmarshaling the lazily-{en,de}coded
// values.
mu.Lock()
defer mu.Unlock()
}
case map[int32]Extension:
m = exts
default:
@ -253,15 +255,16 @@ func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
for i, id := range ids {
ext := m[id]
if i > 0 {
b.WriteByte(',')
}
msd, ok := messageSetMap[id]
if !ok {
// Unknown type; we can't render it, so skip it.
continue
}
if i > 0 && b.Len() > 1 {
b.WriteByte(',')
}
fmt.Fprintf(&b, `"[%s]":`, msd.name)
x := ext.value

View file

@ -64,3 +64,14 @@ func TestUnmarshalMessageSetWithDuplicate(t *testing.T) {
t.Errorf("Combined extension is %q, want %q", got, want)
}
}
func TestMarshalMessageSetJSON_UnknownType(t *testing.T) {
extMap := map[int32]Extension{12345: {}}
got, err := MarshalMessageSetJSON(extMap)
if err != nil {
t.Fatalf("MarshalMessageSetJSON: %v", err)
}
if want := []byte("{}"); !bytes.Equal(got, want) {
t.Errorf("MarshalMessageSetJSON(%v) = %q, want %q", extMap, got, want)
}
}

View file

@ -29,7 +29,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// +build appengine js
// +build purego appengine js
// This file contains an implementation of proto field accesses using package reflect.
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
@ -38,32 +38,13 @@
package proto
import (
"math"
"reflect"
"sync"
)
// A structPointer is a pointer to a struct.
type structPointer struct {
v reflect.Value
}
const unsafeAllowed = false
// toStructPointer returns a structPointer equivalent to the given reflect value.
// The reflect value must itself be a pointer to a struct.
func toStructPointer(v reflect.Value) structPointer {
return structPointer{v}
}
// IsNil reports whether p is nil.
func structPointer_IsNil(p structPointer) bool {
return p.v.IsNil()
}
// Interface returns the struct pointer as an interface value.
func structPointer_Interface(p structPointer, _ reflect.Type) interface{} {
return p.v.Interface()
}
// A field identifies a field in a struct, accessible from a structPointer.
// A field identifies a field in a struct, accessible from a pointer.
// In this implementation, a field is identified by the sequence of field indices
// passed to reflect's FieldByIndex.
type field []int
@ -76,409 +57,301 @@ func toField(f *reflect.StructField) field {
// invalidField is an invalid field identifier.
var invalidField = field(nil)
// zeroField is a noop when calling pointer.offset.
var zeroField = field([]int{})
// IsValid reports whether the field identifier is valid.
func (f field) IsValid() bool { return f != nil }
// field returns the given field in the struct as a reflect value.
func structPointer_field(p structPointer, f field) reflect.Value {
// Special case: an extension map entry with a value of type T
// passes a *T to the struct-handling code with a zero field,
// expecting that it will be treated as equivalent to *struct{ X T },
// which has the same memory layout. We have to handle that case
// specially, because reflect will panic if we call FieldByIndex on a
// non-struct.
if f == nil {
return p.v.Elem()
}
return p.v.Elem().FieldByIndex(f)
}
// ifield returns the given field in the struct as an interface value.
func structPointer_ifield(p structPointer, f field) interface{} {
return structPointer_field(p, f).Addr().Interface()
}
// Bytes returns the address of a []byte field in the struct.
func structPointer_Bytes(p structPointer, f field) *[]byte {
return structPointer_ifield(p, f).(*[]byte)
}
// BytesSlice returns the address of a [][]byte field in the struct.
func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
return structPointer_ifield(p, f).(*[][]byte)
}
// Bool returns the address of a *bool field in the struct.
func structPointer_Bool(p structPointer, f field) **bool {
return structPointer_ifield(p, f).(**bool)
}
// BoolVal returns the address of a bool field in the struct.
func structPointer_BoolVal(p structPointer, f field) *bool {
return structPointer_ifield(p, f).(*bool)
}
// BoolSlice returns the address of a []bool field in the struct.
func structPointer_BoolSlice(p structPointer, f field) *[]bool {
return structPointer_ifield(p, f).(*[]bool)
}
// String returns the address of a *string field in the struct.
func structPointer_String(p structPointer, f field) **string {
return structPointer_ifield(p, f).(**string)
}
// StringVal returns the address of a string field in the struct.
func structPointer_StringVal(p structPointer, f field) *string {
return structPointer_ifield(p, f).(*string)
}
// StringSlice returns the address of a []string field in the struct.
func structPointer_StringSlice(p structPointer, f field) *[]string {
return structPointer_ifield(p, f).(*[]string)
}
// Extensions returns the address of an extension map field in the struct.
func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
return structPointer_ifield(p, f).(*XXX_InternalExtensions)
}
// ExtMap returns the address of an extension map field in the struct.
func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
return structPointer_ifield(p, f).(*map[int32]Extension)
}
// NewAt returns the reflect.Value for a pointer to a field in the struct.
func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
return structPointer_field(p, f).Addr()
}
// SetStructPointer writes a *struct field in the struct.
func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
structPointer_field(p, f).Set(q.v)
}
// GetStructPointer reads a *struct field in the struct.
func structPointer_GetStructPointer(p structPointer, f field) structPointer {
return structPointer{structPointer_field(p, f)}
}
// StructPointerSlice the address of a []*struct field in the struct.
func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice {
return structPointerSlice{structPointer_field(p, f)}
}
// A structPointerSlice represents the address of a slice of pointers to structs
// (themselves messages or groups). That is, v.Type() is *[]*struct{...}.
type structPointerSlice struct {
// The pointer type is for the table-driven decoder.
// The implementation here uses a reflect.Value of pointer type to
// create a generic pointer. In pointer_unsafe.go we use unsafe
// instead of reflect to implement the same (but faster) interface.
type pointer struct {
v reflect.Value
}
func (p structPointerSlice) Len() int { return p.v.Len() }
func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} }
func (p structPointerSlice) Append(q structPointer) {
p.v.Set(reflect.Append(p.v, q.v))
// toPointer converts an interface of pointer type to a pointer
// that points to the same target.
func toPointer(i *Message) pointer {
return pointer{v: reflect.ValueOf(*i)}
}
var (
int32Type = reflect.TypeOf(int32(0))
uint32Type = reflect.TypeOf(uint32(0))
float32Type = reflect.TypeOf(float32(0))
int64Type = reflect.TypeOf(int64(0))
uint64Type = reflect.TypeOf(uint64(0))
float64Type = reflect.TypeOf(float64(0))
)
// A word32 represents a field of type *int32, *uint32, *float32, or *enum.
// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable.
type word32 struct {
v reflect.Value
// toAddrPointer converts an interface to a pointer that points to
// the interface data.
func toAddrPointer(i *interface{}, isptr bool) pointer {
v := reflect.ValueOf(*i)
u := reflect.New(v.Type())
u.Elem().Set(v)
return pointer{v: u}
}
// IsNil reports whether p is nil.
func word32_IsNil(p word32) bool {
// valToPointer converts v to a pointer. v must be of pointer type.
func valToPointer(v reflect.Value) pointer {
return pointer{v: v}
}
// offset converts from a pointer to a structure to a pointer to
// one of its fields.
func (p pointer) offset(f field) pointer {
return pointer{v: p.v.Elem().FieldByIndex(f).Addr()}
}
func (p pointer) isNil() bool {
return p.v.IsNil()
}
// Set sets p to point at a newly allocated word with bits set to x.
func word32_Set(p word32, o *Buffer, x uint32) {
t := p.v.Type().Elem()
switch t {
case int32Type:
if len(o.int32s) == 0 {
o.int32s = make([]int32, uint32PoolSize)
}
o.int32s[0] = int32(x)
p.v.Set(reflect.ValueOf(&o.int32s[0]))
o.int32s = o.int32s[1:]
return
case uint32Type:
if len(o.uint32s) == 0 {
o.uint32s = make([]uint32, uint32PoolSize)
}
o.uint32s[0] = x
p.v.Set(reflect.ValueOf(&o.uint32s[0]))
o.uint32s = o.uint32s[1:]
return
case float32Type:
if len(o.float32s) == 0 {
o.float32s = make([]float32, uint32PoolSize)
}
o.float32s[0] = math.Float32frombits(x)
p.v.Set(reflect.ValueOf(&o.float32s[0]))
o.float32s = o.float32s[1:]
return
}
// must be enum
p.v.Set(reflect.New(t))
p.v.Elem().SetInt(int64(int32(x)))
}
// Get gets the bits pointed at by p, as a uint32.
func word32_Get(p word32) uint32 {
elem := p.v.Elem()
switch elem.Kind() {
case reflect.Int32:
return uint32(elem.Int())
case reflect.Uint32:
return uint32(elem.Uint())
case reflect.Float32:
return math.Float32bits(float32(elem.Float()))
}
panic("unreachable")
}
// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct.
func structPointer_Word32(p structPointer, f field) word32 {
return word32{structPointer_field(p, f)}
}
// A word32Val represents a field of type int32, uint32, float32, or enum.
// That is, v.Type() is int32, uint32, float32, or enum and v is assignable.
type word32Val struct {
v reflect.Value
}
// Set sets *p to x.
func word32Val_Set(p word32Val, x uint32) {
switch p.v.Type() {
case int32Type:
p.v.SetInt(int64(x))
return
case uint32Type:
p.v.SetUint(uint64(x))
return
case float32Type:
p.v.SetFloat(float64(math.Float32frombits(x)))
return
}
// must be enum
p.v.SetInt(int64(int32(x)))
}
// Get gets the bits pointed at by p, as a uint32.
func word32Val_Get(p word32Val) uint32 {
elem := p.v
switch elem.Kind() {
case reflect.Int32:
return uint32(elem.Int())
case reflect.Uint32:
return uint32(elem.Uint())
case reflect.Float32:
return math.Float32bits(float32(elem.Float()))
}
panic("unreachable")
}
// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct.
func structPointer_Word32Val(p structPointer, f field) word32Val {
return word32Val{structPointer_field(p, f)}
}
// A word32Slice is a slice of 32-bit values.
// That is, v.Type() is []int32, []uint32, []float32, or []enum.
type word32Slice struct {
v reflect.Value
}
func (p word32Slice) Append(x uint32) {
n, m := p.v.Len(), p.v.Cap()
// grow updates the slice s in place to make it one element longer.
// s must be addressable.
// Returns the (addressable) new element.
func grow(s reflect.Value) reflect.Value {
n, m := s.Len(), s.Cap()
if n < m {
p.v.SetLen(n + 1)
s.SetLen(n + 1)
} else {
t := p.v.Type().Elem()
p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem())))
}
elem := p.v.Index(n)
switch elem.Kind() {
case reflect.Int32:
elem.SetInt(int64(int32(x)))
case reflect.Uint32:
elem.SetUint(uint64(x))
case reflect.Float32:
elem.SetFloat(float64(math.Float32frombits(x)))
return s.Index(n)
}
func (p pointer) toInt64() *int64 {
return p.v.Interface().(*int64)
}
func (p pointer) toInt64Ptr() **int64 {
return p.v.Interface().(**int64)
}
func (p pointer) toInt64Slice() *[]int64 {
return p.v.Interface().(*[]int64)
}
var int32ptr = reflect.TypeOf((*int32)(nil))
func (p pointer) toInt32() *int32 {
return p.v.Convert(int32ptr).Interface().(*int32)
}
// The toInt32Ptr/Slice methods don't work because of enums.
// Instead, we must use set/get methods for the int32ptr/slice case.
/*
func (p pointer) toInt32Ptr() **int32 {
return p.v.Interface().(**int32)
}
func (p pointer) toInt32Slice() *[]int32 {
return p.v.Interface().(*[]int32)
}
*/
func (p pointer) getInt32Ptr() *int32 {
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
// raw int32 type
return p.v.Elem().Interface().(*int32)
}
// an enum
return p.v.Elem().Convert(int32PtrType).Interface().(*int32)
}
func (p pointer) setInt32Ptr(v int32) {
// Allocate value in a *int32. Possibly convert that to a *enum.
// Then assign it to a **int32 or **enum.
// Note: we can convert *int32 to *enum, but we can't convert
// **int32 to **enum!
p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem()))
}
func (p word32Slice) Len() int {
return p.v.Len()
}
func (p word32Slice) Index(i int) uint32 {
elem := p.v.Index(i)
switch elem.Kind() {
case reflect.Int32:
return uint32(elem.Int())
case reflect.Uint32:
return uint32(elem.Uint())
case reflect.Float32:
return math.Float32bits(float32(elem.Float()))
// getInt32Slice copies []int32 from p as a new slice.
// This behavior differs from the implementation in pointer_unsafe.go.
func (p pointer) getInt32Slice() []int32 {
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
// raw int32 type
return p.v.Elem().Interface().([]int32)
}
panic("unreachable")
// an enum
// Allocate a []int32, then assign []enum's values into it.
// Note: we can't convert []enum to []int32.
slice := p.v.Elem()
s := make([]int32, slice.Len())
for i := 0; i < slice.Len(); i++ {
s[i] = int32(slice.Index(i).Int())
}
return s
}
// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct.
func structPointer_Word32Slice(p structPointer, f field) word32Slice {
return word32Slice{structPointer_field(p, f)}
}
// word64 is like word32 but for 64-bit values.
type word64 struct {
v reflect.Value
}
func word64_Set(p word64, o *Buffer, x uint64) {
t := p.v.Type().Elem()
switch t {
case int64Type:
if len(o.int64s) == 0 {
o.int64s = make([]int64, uint64PoolSize)
}
o.int64s[0] = int64(x)
p.v.Set(reflect.ValueOf(&o.int64s[0]))
o.int64s = o.int64s[1:]
return
case uint64Type:
if len(o.uint64s) == 0 {
o.uint64s = make([]uint64, uint64PoolSize)
}
o.uint64s[0] = x
p.v.Set(reflect.ValueOf(&o.uint64s[0]))
o.uint64s = o.uint64s[1:]
return
case float64Type:
if len(o.float64s) == 0 {
o.float64s = make([]float64, uint64PoolSize)
}
o.float64s[0] = math.Float64frombits(x)
p.v.Set(reflect.ValueOf(&o.float64s[0]))
o.float64s = o.float64s[1:]
// setInt32Slice copies []int32 into p as a new slice.
// This behavior differs from the implementation in pointer_unsafe.go.
func (p pointer) setInt32Slice(v []int32) {
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
// raw int32 type
p.v.Elem().Set(reflect.ValueOf(v))
return
}
panic("unreachable")
}
func word64_IsNil(p word64) bool {
return p.v.IsNil()
}
func word64_Get(p word64) uint64 {
elem := p.v.Elem()
switch elem.Kind() {
case reflect.Int64:
return uint64(elem.Int())
case reflect.Uint64:
return elem.Uint()
case reflect.Float64:
return math.Float64bits(elem.Float())
// an enum
// Allocate a []enum, then assign []int32's values into it.
// Note: we can't convert []enum to []int32.
slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v))
for i, x := range v {
slice.Index(i).SetInt(int64(x))
}
panic("unreachable")
p.v.Elem().Set(slice)
}
func (p pointer) appendInt32Slice(v int32) {
grow(p.v.Elem()).SetInt(int64(v))
}
func structPointer_Word64(p structPointer, f field) word64 {
return word64{structPointer_field(p, f)}
func (p pointer) toUint64() *uint64 {
return p.v.Interface().(*uint64)
}
func (p pointer) toUint64Ptr() **uint64 {
return p.v.Interface().(**uint64)
}
func (p pointer) toUint64Slice() *[]uint64 {
return p.v.Interface().(*[]uint64)
}
func (p pointer) toUint32() *uint32 {
return p.v.Interface().(*uint32)
}
func (p pointer) toUint32Ptr() **uint32 {
return p.v.Interface().(**uint32)
}
func (p pointer) toUint32Slice() *[]uint32 {
return p.v.Interface().(*[]uint32)
}
func (p pointer) toBool() *bool {
return p.v.Interface().(*bool)
}
func (p pointer) toBoolPtr() **bool {
return p.v.Interface().(**bool)
}
func (p pointer) toBoolSlice() *[]bool {
return p.v.Interface().(*[]bool)
}
func (p pointer) toFloat64() *float64 {
return p.v.Interface().(*float64)
}
func (p pointer) toFloat64Ptr() **float64 {
return p.v.Interface().(**float64)
}
func (p pointer) toFloat64Slice() *[]float64 {
return p.v.Interface().(*[]float64)
}
func (p pointer) toFloat32() *float32 {
return p.v.Interface().(*float32)
}
func (p pointer) toFloat32Ptr() **float32 {
return p.v.Interface().(**float32)
}
func (p pointer) toFloat32Slice() *[]float32 {
return p.v.Interface().(*[]float32)
}
func (p pointer) toString() *string {
return p.v.Interface().(*string)
}
func (p pointer) toStringPtr() **string {
return p.v.Interface().(**string)
}
func (p pointer) toStringSlice() *[]string {
return p.v.Interface().(*[]string)
}
func (p pointer) toBytes() *[]byte {
return p.v.Interface().(*[]byte)
}
func (p pointer) toBytesSlice() *[][]byte {
return p.v.Interface().(*[][]byte)
}
func (p pointer) toExtensions() *XXX_InternalExtensions {
return p.v.Interface().(*XXX_InternalExtensions)
}
func (p pointer) toOldExtensions() *map[int32]Extension {
return p.v.Interface().(*map[int32]Extension)
}
func (p pointer) getPointer() pointer {
return pointer{v: p.v.Elem()}
}
func (p pointer) setPointer(q pointer) {
p.v.Elem().Set(q.v)
}
func (p pointer) appendPointer(q pointer) {
grow(p.v.Elem()).Set(q.v)
}
// word64Val is like word32Val but for 64-bit values.
type word64Val struct {
v reflect.Value
// getPointerSlice copies []*T from p as a new []pointer.
// This behavior differs from the implementation in pointer_unsafe.go.
func (p pointer) getPointerSlice() []pointer {
if p.v.IsNil() {
return nil
}
n := p.v.Elem().Len()
s := make([]pointer, n)
for i := 0; i < n; i++ {
s[i] = pointer{v: p.v.Elem().Index(i)}
}
return s
}
func word64Val_Set(p word64Val, o *Buffer, x uint64) {
switch p.v.Type() {
case int64Type:
p.v.SetInt(int64(x))
return
case uint64Type:
p.v.SetUint(x)
return
case float64Type:
p.v.SetFloat(math.Float64frombits(x))
// setPointerSlice copies []pointer into p as a new []*T.
// This behavior differs from the implementation in pointer_unsafe.go.
func (p pointer) setPointerSlice(v []pointer) {
if v == nil {
p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem())
return
}
panic("unreachable")
}
func word64Val_Get(p word64Val) uint64 {
elem := p.v
switch elem.Kind() {
case reflect.Int64:
return uint64(elem.Int())
case reflect.Uint64:
return elem.Uint()
case reflect.Float64:
return math.Float64bits(elem.Float())
s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v))
for _, p := range v {
s = reflect.Append(s, p.v)
}
panic("unreachable")
p.v.Elem().Set(s)
}
func structPointer_Word64Val(p structPointer, f field) word64Val {
return word64Val{structPointer_field(p, f)}
}
type word64Slice struct {
v reflect.Value
}
func (p word64Slice) Append(x uint64) {
n, m := p.v.Len(), p.v.Cap()
if n < m {
p.v.SetLen(n + 1)
} else {
t := p.v.Type().Elem()
p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
}
elem := p.v.Index(n)
switch elem.Kind() {
case reflect.Int64:
elem.SetInt(int64(int64(x)))
case reflect.Uint64:
elem.SetUint(uint64(x))
case reflect.Float64:
elem.SetFloat(float64(math.Float64frombits(x)))
// getInterfacePointer returns a pointer that points to the
// interface data of the interface pointed by p.
func (p pointer) getInterfacePointer() pointer {
if p.v.Elem().IsNil() {
return pointer{v: p.v.Elem()}
}
return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct
}
func (p word64Slice) Len() int {
return p.v.Len()
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
// TODO: check that p.v.Type().Elem() == t?
return p.v
}
func (p word64Slice) Index(i int) uint64 {
elem := p.v.Index(i)
switch elem.Kind() {
case reflect.Int64:
return uint64(elem.Int())
case reflect.Uint64:
return uint64(elem.Uint())
case reflect.Float64:
return math.Float64bits(float64(elem.Float()))
}
panic("unreachable")
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
atomicLock.Lock()
defer atomicLock.Unlock()
return *p
}
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
atomicLock.Lock()
defer atomicLock.Unlock()
*p = v
}
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
atomicLock.Lock()
defer atomicLock.Unlock()
return *p
}
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
atomicLock.Lock()
defer atomicLock.Unlock()
*p = v
}
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
atomicLock.Lock()
defer atomicLock.Unlock()
return *p
}
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
atomicLock.Lock()
defer atomicLock.Unlock()
*p = v
}
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
atomicLock.Lock()
defer atomicLock.Unlock()
return *p
}
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
atomicLock.Lock()
defer atomicLock.Unlock()
*p = v
}
func structPointer_Word64Slice(p structPointer, f field) word64Slice {
return word64Slice{structPointer_field(p, f)}
}
var atomicLock sync.Mutex

View file

@ -1,6 +1,6 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2016, The GoGo Authors. All rights reserved.
// Copyright (c) 2018, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
@ -26,7 +26,11 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// +build appengine js
// +build purego appengine js
// This file contains an implementation of proto field accesses using package reflect.
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
// be used on App Engine.
package proto
@ -34,52 +38,22 @@ import (
"reflect"
)
func structPointer_FieldPointer(p structPointer, f field) structPointer {
panic("not implemented")
// TODO: untested, so probably incorrect.
func (p pointer) getRef() pointer {
return pointer{v: p.v.Addr()}
}
func appendStructPointer(base structPointer, f field, typ reflect.Type) structPointer {
panic("not implemented")
func (p pointer) appendRef(v pointer, typ reflect.Type) {
slice := p.getSlice(typ)
elem := v.asPointerTo(typ).Elem()
newSlice := reflect.Append(slice, elem)
slice.Set(newSlice)
}
func structPointer_InterfaceAt(p structPointer, f field, t reflect.Type) interface{} {
panic("not implemented")
}
func structPointer_InterfaceRef(p structPointer, f field, t reflect.Type) interface{} {
panic("not implemented")
}
func structPointer_GetRefStructPointer(p structPointer, f field) structPointer {
panic("not implemented")
}
func structPointer_Add(p structPointer, size field) structPointer {
panic("not implemented")
}
func structPointer_Len(p structPointer, f field) int {
panic("not implemented")
}
func structPointer_GetSliceHeader(p structPointer, f field) *reflect.SliceHeader {
panic("not implemented")
}
func structPointer_Copy(oldptr structPointer, newptr structPointer, size int) {
panic("not implemented")
}
func structPointer_StructRefSlice(p structPointer, f field, size uintptr) *structRefSlice {
panic("not implemented")
}
type structRefSlice struct{}
func (v *structRefSlice) Len() int {
panic("not implemented")
}
func (v *structRefSlice) Index(i int) structPointer {
panic("not implemented")
func (p pointer) getSlice(typ reflect.Type) reflect.Value {
sliceTyp := reflect.SliceOf(typ)
slice := p.asPointerTo(sliceTyp)
slice = slice.Elem()
return slice
}

View file

@ -29,7 +29,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// +build !appengine,!js
// +build !purego,!appengine,!js
// This file contains the implementation of the proto field accesses using package unsafe.
@ -37,38 +37,13 @@ package proto
import (
"reflect"
"sync/atomic"
"unsafe"
)
// NOTE: These type_Foo functions would more idiomatically be methods,
// but Go does not allow methods on pointer types, and we must preserve
// some pointer type for the garbage collector. We use these
// funcs with clunky names as our poor approximation to methods.
//
// An alternative would be
// type structPointer struct { p unsafe.Pointer }
// but that does not registerize as well.
const unsafeAllowed = true
// A structPointer is a pointer to a struct.
type structPointer unsafe.Pointer
// toStructPointer returns a structPointer equivalent to the given reflect value.
func toStructPointer(v reflect.Value) structPointer {
return structPointer(unsafe.Pointer(v.Pointer()))
}
// IsNil reports whether p is nil.
func structPointer_IsNil(p structPointer) bool {
return p == nil
}
// Interface returns the struct pointer, assumed to have element type t,
// as an interface value.
func structPointer_Interface(p structPointer, t reflect.Type) interface{} {
return reflect.NewAt(t, unsafe.Pointer(p)).Interface()
}
// A field identifies a field in a struct, accessible from a structPointer.
// A field identifies a field in a struct, accessible from a pointer.
// In this implementation, a field is identified by its byte offset from the start of the struct.
type field uintptr
@ -80,191 +55,254 @@ func toField(f *reflect.StructField) field {
// invalidField is an invalid field identifier.
const invalidField = ^field(0)
// zeroField is a noop when calling pointer.offset.
const zeroField = field(0)
// IsValid reports whether the field identifier is valid.
func (f field) IsValid() bool {
return f != ^field(0)
return f != invalidField
}
// Bytes returns the address of a []byte field in the struct.
func structPointer_Bytes(p structPointer, f field) *[]byte {
return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
// The pointer type below is for the new table-driven encoder/decoder.
// The implementation here uses unsafe.Pointer to create a generic pointer.
// In pointer_reflect.go we use reflect instead of unsafe to implement
// the same (but slower) interface.
type pointer struct {
p unsafe.Pointer
}
// BytesSlice returns the address of a [][]byte field in the struct.
func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
// size of pointer
var ptrSize = unsafe.Sizeof(uintptr(0))
// toPointer converts an interface of pointer type to a pointer
// that points to the same target.
func toPointer(i *Message) pointer {
// Super-tricky - read pointer out of data word of interface value.
// Saves ~25ns over the equivalent:
// return valToPointer(reflect.ValueOf(*i))
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
}
// Bool returns the address of a *bool field in the struct.
func structPointer_Bool(p structPointer, f field) **bool {
return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
// BoolVal returns the address of a bool field in the struct.
func structPointer_BoolVal(p structPointer, f field) *bool {
return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
// BoolSlice returns the address of a []bool field in the struct.
func structPointer_BoolSlice(p structPointer, f field) *[]bool {
return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
// String returns the address of a *string field in the struct.
func structPointer_String(p structPointer, f field) **string {
return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
// StringVal returns the address of a string field in the struct.
func structPointer_StringVal(p structPointer, f field) *string {
return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
// StringSlice returns the address of a []string field in the struct.
func structPointer_StringSlice(p structPointer, f field) *[]string {
return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
// ExtMap returns the address of an extension map field in the struct.
func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
// NewAt returns the reflect.Value for a pointer to a field in the struct.
func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f)))
}
// SetStructPointer writes a *struct field in the struct.
func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
*(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q
}
// GetStructPointer reads a *struct field in the struct.
func structPointer_GetStructPointer(p structPointer, f field) structPointer {
return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
// StructPointerSlice the address of a []*struct field in the struct.
func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice {
return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups).
type structPointerSlice []structPointer
func (v *structPointerSlice) Len() int { return len(*v) }
func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] }
func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) }
// A word32 is the address of a "pointer to 32-bit value" field.
type word32 **uint32
// IsNil reports whether *v is nil.
func word32_IsNil(p word32) bool {
return *p == nil
}
// Set sets *v to point at a newly allocated word set to x.
func word32_Set(p word32, o *Buffer, x uint32) {
if len(o.uint32s) == 0 {
o.uint32s = make([]uint32, uint32PoolSize)
// toAddrPointer converts an interface to a pointer that points to
// the interface data.
func toAddrPointer(i *interface{}, isptr bool) pointer {
// Super-tricky - read or get the address of data word of interface value.
if isptr {
// The interface is of pointer type, thus it is a direct interface.
// The data word is the pointer data itself. We take its address.
return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
}
o.uint32s[0] = x
*p = &o.uint32s[0]
o.uint32s = o.uint32s[1:]
// The interface is not of pointer type. The data word is the pointer
// to the data.
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
}
// Get gets the value pointed at by *v.
func word32_Get(p word32) uint32 {
return **p
// valToPointer converts v to a pointer. v must be of pointer type.
func valToPointer(v reflect.Value) pointer {
return pointer{p: unsafe.Pointer(v.Pointer())}
}
// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
func structPointer_Word32(p structPointer, f field) word32 {
return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
// offset converts from a pointer to a structure to a pointer to
// one of its fields.
func (p pointer) offset(f field) pointer {
// For safety, we should panic if !f.IsValid, however calling panic causes
// this to no longer be inlineable, which is a serious performance cost.
/*
if !f.IsValid() {
panic("invalid field")
}
*/
return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
}
// A word32Val is the address of a 32-bit value field.
type word32Val *uint32
// Set sets *p to x.
func word32Val_Set(p word32Val, x uint32) {
*p = x
func (p pointer) isNil() bool {
return p.p == nil
}
// Get gets the value pointed at by p.
func word32Val_Get(p word32Val) uint32 {
return *p
func (p pointer) toInt64() *int64 {
return (*int64)(p.p)
}
func (p pointer) toInt64Ptr() **int64 {
return (**int64)(p.p)
}
func (p pointer) toInt64Slice() *[]int64 {
return (*[]int64)(p.p)
}
func (p pointer) toInt32() *int32 {
return (*int32)(p.p)
}
// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
func structPointer_Word32Val(p structPointer, f field) word32Val {
return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
}
// A word32Slice is a slice of 32-bit values.
type word32Slice []uint32
func (v *word32Slice) Append(x uint32) { *v = append(*v, x) }
func (v *word32Slice) Len() int { return len(*v) }
func (v *word32Slice) Index(i int) uint32 { return (*v)[i] }
// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct.
func structPointer_Word32Slice(p structPointer, f field) *word32Slice {
return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
// word64 is like word32 but for 64-bit values.
type word64 **uint64
func word64_Set(p word64, o *Buffer, x uint64) {
if len(o.uint64s) == 0 {
o.uint64s = make([]uint64, uint64PoolSize)
// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist.
/*
func (p pointer) toInt32Ptr() **int32 {
return (**int32)(p.p)
}
o.uint64s[0] = x
*p = &o.uint64s[0]
o.uint64s = o.uint64s[1:]
func (p pointer) toInt32Slice() *[]int32 {
return (*[]int32)(p.p)
}
*/
func (p pointer) getInt32Ptr() *int32 {
return *(**int32)(p.p)
}
func (p pointer) setInt32Ptr(v int32) {
*(**int32)(p.p) = &v
}
func word64_IsNil(p word64) bool {
return *p == nil
// getInt32Slice loads a []int32 from p.
// The value returned is aliased with the original slice.
// This behavior differs from the implementation in pointer_reflect.go.
func (p pointer) getInt32Slice() []int32 {
return *(*[]int32)(p.p)
}
func word64_Get(p word64) uint64 {
return **p
// setInt32Slice stores a []int32 to p.
// The value set is aliased with the input slice.
// This behavior differs from the implementation in pointer_reflect.go.
func (p pointer) setInt32Slice(v []int32) {
*(*[]int32)(p.p) = v
}
func structPointer_Word64(p structPointer, f field) word64 {
return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead?
func (p pointer) appendInt32Slice(v int32) {
s := (*[]int32)(p.p)
*s = append(*s, v)
}
// word64Val is like word32Val but for 64-bit values.
type word64Val *uint64
func word64Val_Set(p word64Val, o *Buffer, x uint64) {
*p = x
func (p pointer) toUint64() *uint64 {
return (*uint64)(p.p)
}
func (p pointer) toUint64Ptr() **uint64 {
return (**uint64)(p.p)
}
func (p pointer) toUint64Slice() *[]uint64 {
return (*[]uint64)(p.p)
}
func (p pointer) toUint32() *uint32 {
return (*uint32)(p.p)
}
func (p pointer) toUint32Ptr() **uint32 {
return (**uint32)(p.p)
}
func (p pointer) toUint32Slice() *[]uint32 {
return (*[]uint32)(p.p)
}
func (p pointer) toBool() *bool {
return (*bool)(p.p)
}
func (p pointer) toBoolPtr() **bool {
return (**bool)(p.p)
}
func (p pointer) toBoolSlice() *[]bool {
return (*[]bool)(p.p)
}
func (p pointer) toFloat64() *float64 {
return (*float64)(p.p)
}
func (p pointer) toFloat64Ptr() **float64 {
return (**float64)(p.p)
}
func (p pointer) toFloat64Slice() *[]float64 {
return (*[]float64)(p.p)
}
func (p pointer) toFloat32() *float32 {
return (*float32)(p.p)
}
func (p pointer) toFloat32Ptr() **float32 {
return (**float32)(p.p)
}
func (p pointer) toFloat32Slice() *[]float32 {
return (*[]float32)(p.p)
}
func (p pointer) toString() *string {
return (*string)(p.p)
}
func (p pointer) toStringPtr() **string {
return (**string)(p.p)
}
func (p pointer) toStringSlice() *[]string {
return (*[]string)(p.p)
}
func (p pointer) toBytes() *[]byte {
return (*[]byte)(p.p)
}
func (p pointer) toBytesSlice() *[][]byte {
return (*[][]byte)(p.p)
}
func (p pointer) toExtensions() *XXX_InternalExtensions {
return (*XXX_InternalExtensions)(p.p)
}
func (p pointer) toOldExtensions() *map[int32]Extension {
return (*map[int32]Extension)(p.p)
}
func word64Val_Get(p word64Val) uint64 {
return *p
// getPointerSlice loads []*T from p as a []pointer.
// The value returned is aliased with the original slice.
// This behavior differs from the implementation in pointer_reflect.go.
func (p pointer) getPointerSlice() []pointer {
// Super-tricky - p should point to a []*T where T is a
// message type. We load it as []pointer.
return *(*[]pointer)(p.p)
}
func structPointer_Word64Val(p structPointer, f field) word64Val {
return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
// setPointerSlice stores []pointer into p as a []*T.
// The value set is aliased with the input slice.
// This behavior differs from the implementation in pointer_reflect.go.
func (p pointer) setPointerSlice(v []pointer) {
// Super-tricky - p should point to a []*T where T is a
// message type. We store it as []pointer.
*(*[]pointer)(p.p) = v
}
// word64Slice is like word32Slice but for 64-bit values.
type word64Slice []uint64
func (v *word64Slice) Append(x uint64) { *v = append(*v, x) }
func (v *word64Slice) Len() int { return len(*v) }
func (v *word64Slice) Index(i int) uint64 { return (*v)[i] }
func structPointer_Word64Slice(p structPointer, f field) *word64Slice {
return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
// getPointer loads the pointer at p and returns it.
func (p pointer) getPointer() pointer {
return pointer{p: *(*unsafe.Pointer)(p.p)}
}
// setPointer stores the pointer q at p.
func (p pointer) setPointer(q pointer) {
*(*unsafe.Pointer)(p.p) = q.p
}
// append q to the slice pointed to by p.
func (p pointer) appendPointer(q pointer) {
s := (*[]unsafe.Pointer)(p.p)
*s = append(*s, q.p)
}
// getInterfacePointer returns a pointer that points to the
// interface data of the interface pointed by p.
func (p pointer) getInterfacePointer() pointer {
// Super-tricky - read pointer out of data word of interface value.
return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]}
}
// asPointerTo returns a reflect.Value that is a pointer to an
// object of type t stored at p.
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
return reflect.NewAt(t, p.p)
}
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
}
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
}
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
}
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
}
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
}
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
}
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
}
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
}

View file

@ -1,6 +1,6 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// Copyright (c) 2018, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
@ -26,7 +26,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// +build !appengine,!js
// +build !purego !appengine,!js
// This file contains the implementation of the proto field accesses using package unsafe.
@ -37,92 +37,20 @@ import (
"unsafe"
)
func structPointer_InterfaceAt(p structPointer, f field, t reflect.Type) interface{} {
point := unsafe.Pointer(uintptr(p) + uintptr(f))
r := reflect.NewAt(t, point)
return r.Interface()
func (p pointer) getRef() pointer {
return pointer{p: (unsafe.Pointer)(&p.p)}
}
func structPointer_InterfaceRef(p structPointer, f field, t reflect.Type) interface{} {
point := unsafe.Pointer(uintptr(p) + uintptr(f))
r := reflect.NewAt(t, point)
if r.Elem().IsNil() {
return nil
}
return r.Elem().Interface()
func (p pointer) appendRef(v pointer, typ reflect.Type) {
slice := p.getSlice(typ)
elem := v.asPointerTo(typ).Elem()
newSlice := reflect.Append(slice, elem)
slice.Set(newSlice)
}
func copyUintPtr(oldptr, newptr uintptr, size int) {
oldbytes := make([]byte, 0)
oldslice := (*reflect.SliceHeader)(unsafe.Pointer(&oldbytes))
oldslice.Data = oldptr
oldslice.Len = size
oldslice.Cap = size
newbytes := make([]byte, 0)
newslice := (*reflect.SliceHeader)(unsafe.Pointer(&newbytes))
newslice.Data = newptr
newslice.Len = size
newslice.Cap = size
copy(newbytes, oldbytes)
}
func structPointer_Copy(oldptr structPointer, newptr structPointer, size int) {
copyUintPtr(uintptr(oldptr), uintptr(newptr), size)
}
func appendStructPointer(base structPointer, f field, typ reflect.Type) structPointer {
size := typ.Elem().Size()
oldHeader := structPointer_GetSliceHeader(base, f)
oldSlice := reflect.NewAt(typ, unsafe.Pointer(oldHeader)).Elem()
newLen := oldHeader.Len + 1
newSlice := reflect.MakeSlice(typ, newLen, newLen)
reflect.Copy(newSlice, oldSlice)
bas := toStructPointer(newSlice)
oldHeader.Data = uintptr(bas)
oldHeader.Len = newLen
oldHeader.Cap = newLen
return structPointer(unsafe.Pointer(uintptr(unsafe.Pointer(bas)) + uintptr(uintptr(newLen-1)*size)))
}
func structPointer_FieldPointer(p structPointer, f field) structPointer {
return structPointer(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
func structPointer_GetRefStructPointer(p structPointer, f field) structPointer {
return structPointer((*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))))
}
func structPointer_GetSliceHeader(p structPointer, f field) *reflect.SliceHeader {
return (*reflect.SliceHeader)(unsafe.Pointer(uintptr(p) + uintptr(f)))
}
func structPointer_Add(p structPointer, size field) structPointer {
return structPointer(unsafe.Pointer(uintptr(p) + uintptr(size)))
}
func structPointer_Len(p structPointer, f field) int {
return len(*(*[]interface{})(unsafe.Pointer(structPointer_GetRefStructPointer(p, f))))
}
func structPointer_StructRefSlice(p structPointer, f field, size uintptr) *structRefSlice {
return &structRefSlice{p: p, f: f, size: size}
}
// A structRefSlice represents a slice of structs (themselves submessages or groups).
type structRefSlice struct {
p structPointer
f field
size uintptr
}
func (v *structRefSlice) Len() int {
return structPointer_Len(v.p, v.f)
}
func (v *structRefSlice) Index(i int) structPointer {
ss := structPointer_GetStructPointer(v.p, v.f)
ss1 := structPointer_GetRefStructPointer(ss, 0)
return structPointer_Add(ss1, field(uintptr(i)*v.size))
func (p pointer) getSlice(typ reflect.Type) reflect.Value {
sliceTyp := reflect.SliceOf(typ)
slice := p.asPointerTo(sliceTyp)
slice = slice.Elem()
return slice
}

View file

@ -63,42 +63,6 @@ const (
WireFixed32 = 5
)
const startSize = 10 // initial slice/string sizes
// Encoders are defined in encode.go
// An encoder outputs the full representation of a field, including its
// tag and encoder type.
type encoder func(p *Buffer, prop *Properties, base structPointer) error
// A valueEncoder encodes a single integer in a particular encoding.
type valueEncoder func(o *Buffer, x uint64) error
// Sizers are defined in encode.go
// A sizer returns the encoded size of a field, including its tag and encoder
// type.
type sizer func(prop *Properties, base structPointer) int
// A valueSizer returns the encoded size of a single integer in a particular
// encoding.
type valueSizer func(x uint64) int
// Decoders are defined in decode.go
// A decoder creates a value from its wire representation.
// Unrecognized subelements are saved in unrec.
type decoder func(p *Buffer, prop *Properties, base structPointer) error
// A valueDecoder decodes a single integer in a particular encoding.
type valueDecoder func(o *Buffer) (x uint64, err error)
// A oneofMarshaler does the marshaling for all oneof fields in a message.
type oneofMarshaler func(Message, *Buffer) error
// A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
// A oneofSizer does the sizing for all oneof fields in a message.
type oneofSizer func(Message) int
// tagMap is an optimization over map[int]int for typical protocol buffer
// use-cases. Encoded protocol buffers are often in tag order with small tag
// numbers.
@ -145,13 +109,6 @@ type StructProperties struct {
decoderTags tagMap // map from proto tag to struct field number
decoderOrigNames map[string]int // map from original name to struct field number
order []int // list of struct field numbers in tag order
unrecField field // field id of the XXX_unrecognized []byte field
extendable bool // is this an extendable proto
oneofMarshaler oneofMarshaler
oneofUnmarshaler oneofUnmarshaler
oneofSizer oneofSizer
stype reflect.Type
// OneofTypes contains information about the oneof fields in this message.
// It is keyed by the original name of a field.
@ -197,36 +154,19 @@ type Properties struct {
StdTime bool
StdDuration bool
enc encoder
valEnc valueEncoder // set for bool and numeric types only
field field
tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType)
tagbuf [8]byte
stype reflect.Type // set for struct types only
sstype reflect.Type // set for slices of structs types only
ctype reflect.Type // set for custom types only
sprop *StructProperties // set for struct types only
isMarshaler bool
isUnmarshaler bool
stype reflect.Type // set for struct types only
ctype reflect.Type // set for custom types only
sprop *StructProperties // set for struct types only
mtype reflect.Type // set for map types only
mkeyprop *Properties // set for map types only
mvalprop *Properties // set for map types only
size sizer
valSize valueSizer // set for bool and numeric types only
dec decoder
valDec valueDecoder // set for bool and numeric types only
// If this is a packable field, this will be the decoder for the packed version of the field.
packedDec decoder
}
// String formats the properties in the protobuf struct field tag style.
func (p *Properties) String() string {
s := p.Wire
s = ","
s += ","
s += strconv.Itoa(p.Tag)
if p.Required {
s += ",req"
@ -272,29 +212,14 @@ func (p *Properties) Parse(s string) {
switch p.Wire {
case "varint":
p.WireType = WireVarint
p.valEnc = (*Buffer).EncodeVarint
p.valDec = (*Buffer).DecodeVarint
p.valSize = sizeVarint
case "fixed32":
p.WireType = WireFixed32
p.valEnc = (*Buffer).EncodeFixed32
p.valDec = (*Buffer).DecodeFixed32
p.valSize = sizeFixed32
case "fixed64":
p.WireType = WireFixed64
p.valEnc = (*Buffer).EncodeFixed64
p.valDec = (*Buffer).DecodeFixed64
p.valSize = sizeFixed64
case "zigzag32":
p.WireType = WireVarint
p.valEnc = (*Buffer).EncodeZigzag32
p.valDec = (*Buffer).DecodeZigzag32
p.valSize = sizeZigzag32
case "zigzag64":
p.WireType = WireVarint
p.valEnc = (*Buffer).EncodeZigzag64
p.valDec = (*Buffer).DecodeZigzag64
p.valSize = sizeZigzag64
case "bytes", "group":
p.WireType = WireBytes
// no numeric converter for non-numeric types
@ -309,6 +234,7 @@ func (p *Properties) Parse(s string) {
return
}
outer:
for i := 2; i < len(fields); i++ {
f := fields[i]
switch {
@ -336,7 +262,7 @@ func (p *Properties) Parse(s string) {
if i+1 < len(fields) {
// Commas aren't escaped, and def is always last.
p.Default += "," + strings.Join(fields[i+1:], ",")
break
break outer
}
case strings.HasPrefix(f, "embedded="):
p.OrigName = strings.Split(f, "=")[1]
@ -352,292 +278,43 @@ func (p *Properties) Parse(s string) {
}
}
func logNoSliceEnc(t1, t2 reflect.Type) {
fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
}
var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
// Initialize the fields for encoding and decoding.
func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
p.enc = nil
p.dec = nil
p.size = nil
// setFieldProps initializes the field properties for submessages and maps.
func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
isMap := typ.Kind() == reflect.Map
if len(p.CustomType) > 0 && !isMap {
p.setCustomEncAndDec(typ)
p.ctype = typ
p.setTag(lockGetProp)
return
}
if p.StdTime && !isMap {
p.setTimeEncAndDec(typ)
p.setTag(lockGetProp)
return
}
if p.StdDuration && !isMap {
p.setDurationEncAndDec(typ)
p.setTag(lockGetProp)
return
}
switch t1 := typ; t1.Kind() {
default:
fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1)
// proto3 scalar types
case reflect.Bool:
if p.proto3 {
p.enc = (*Buffer).enc_proto3_bool
p.dec = (*Buffer).dec_proto3_bool
p.size = size_proto3_bool
} else {
p.enc = (*Buffer).enc_ref_bool
p.dec = (*Buffer).dec_proto3_bool
p.size = size_ref_bool
}
case reflect.Int32:
if p.proto3 {
p.enc = (*Buffer).enc_proto3_int32
p.dec = (*Buffer).dec_proto3_int32
p.size = size_proto3_int32
} else {
p.enc = (*Buffer).enc_ref_int32
p.dec = (*Buffer).dec_proto3_int32
p.size = size_ref_int32
}
case reflect.Uint32:
if p.proto3 {
p.enc = (*Buffer).enc_proto3_uint32
p.dec = (*Buffer).dec_proto3_int32 // can reuse
p.size = size_proto3_uint32
} else {
p.enc = (*Buffer).enc_ref_uint32
p.dec = (*Buffer).dec_proto3_int32 // can reuse
p.size = size_ref_uint32
}
case reflect.Int64, reflect.Uint64:
if p.proto3 {
p.enc = (*Buffer).enc_proto3_int64
p.dec = (*Buffer).dec_proto3_int64
p.size = size_proto3_int64
} else {
p.enc = (*Buffer).enc_ref_int64
p.dec = (*Buffer).dec_proto3_int64
p.size = size_ref_int64
}
case reflect.Float32:
if p.proto3 {
p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits
p.dec = (*Buffer).dec_proto3_int32
p.size = size_proto3_uint32
} else {
p.enc = (*Buffer).enc_ref_uint32 // can just treat them as bits
p.dec = (*Buffer).dec_proto3_int32
p.size = size_ref_uint32
}
case reflect.Float64:
if p.proto3 {
p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits
p.dec = (*Buffer).dec_proto3_int64
p.size = size_proto3_int64
} else {
p.enc = (*Buffer).enc_ref_int64 // can just treat them as bits
p.dec = (*Buffer).dec_proto3_int64
p.size = size_ref_int64
}
case reflect.String:
if p.proto3 {
p.enc = (*Buffer).enc_proto3_string
p.dec = (*Buffer).dec_proto3_string
p.size = size_proto3_string
} else {
p.enc = (*Buffer).enc_ref_string
p.dec = (*Buffer).dec_proto3_string
p.size = size_ref_string
}
case reflect.Struct:
p.stype = typ
p.isMarshaler = isMarshaler(typ)
p.isUnmarshaler = isUnmarshaler(typ)
if p.Wire == "bytes" {
p.enc = (*Buffer).enc_ref_struct_message
p.dec = (*Buffer).dec_ref_struct_message
p.size = size_ref_struct_message
} else {
fmt.Fprintf(os.Stderr, "proto: no coders for struct %T\n", typ)
}
case reflect.Ptr:
switch t2 := t1.Elem(); t2.Kind() {
default:
fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2)
break
case reflect.Bool:
p.enc = (*Buffer).enc_bool
p.dec = (*Buffer).dec_bool
p.size = size_bool
case reflect.Int32:
p.enc = (*Buffer).enc_int32
p.dec = (*Buffer).dec_int32
p.size = size_int32
case reflect.Uint32:
p.enc = (*Buffer).enc_uint32
p.dec = (*Buffer).dec_int32 // can reuse
p.size = size_uint32
case reflect.Int64, reflect.Uint64:
p.enc = (*Buffer).enc_int64
p.dec = (*Buffer).dec_int64
p.size = size_int64
case reflect.Float32:
p.enc = (*Buffer).enc_uint32 // can just treat them as bits
p.dec = (*Buffer).dec_int32
p.size = size_uint32
case reflect.Float64:
p.enc = (*Buffer).enc_int64 // can just treat them as bits
p.dec = (*Buffer).dec_int64
p.size = size_int64
case reflect.String:
p.enc = (*Buffer).enc_string
p.dec = (*Buffer).dec_string
p.size = size_string
case reflect.Struct:
if t1.Elem().Kind() == reflect.Struct {
p.stype = t1.Elem()
p.isMarshaler = isMarshaler(t1)
p.isUnmarshaler = isUnmarshaler(t1)
if p.Wire == "bytes" {
p.enc = (*Buffer).enc_struct_message
p.dec = (*Buffer).dec_struct_message
p.size = size_struct_message
} else {
p.enc = (*Buffer).enc_struct_group
p.dec = (*Buffer).dec_struct_group
p.size = size_struct_group
}
}
case reflect.Slice:
switch t2 := t1.Elem(); t2.Kind() {
default:
logNoSliceEnc(t1, t2)
break
case reflect.Bool:
if p.Packed {
p.enc = (*Buffer).enc_slice_packed_bool
p.size = size_slice_packed_bool
} else {
p.enc = (*Buffer).enc_slice_bool
p.size = size_slice_bool
}
p.dec = (*Buffer).dec_slice_bool
p.packedDec = (*Buffer).dec_slice_packed_bool
case reflect.Int32:
if p.Packed {
p.enc = (*Buffer).enc_slice_packed_int32
p.size = size_slice_packed_int32
} else {
p.enc = (*Buffer).enc_slice_int32
p.size = size_slice_int32
}
p.dec = (*Buffer).dec_slice_int32
p.packedDec = (*Buffer).dec_slice_packed_int32
case reflect.Uint32:
if p.Packed {
p.enc = (*Buffer).enc_slice_packed_uint32
p.size = size_slice_packed_uint32
} else {
p.enc = (*Buffer).enc_slice_uint32
p.size = size_slice_uint32
}
p.dec = (*Buffer).dec_slice_int32
p.packedDec = (*Buffer).dec_slice_packed_int32
case reflect.Int64, reflect.Uint64:
if p.Packed {
p.enc = (*Buffer).enc_slice_packed_int64
p.size = size_slice_packed_int64
} else {
p.enc = (*Buffer).enc_slice_int64
p.size = size_slice_int64
}
p.dec = (*Buffer).dec_slice_int64
p.packedDec = (*Buffer).dec_slice_packed_int64
case reflect.Uint8:
p.dec = (*Buffer).dec_slice_byte
if p.proto3 {
p.enc = (*Buffer).enc_proto3_slice_byte
p.size = size_proto3_slice_byte
} else {
p.enc = (*Buffer).enc_slice_byte
p.size = size_slice_byte
}
case reflect.Float32, reflect.Float64:
switch t2.Bits() {
case 32:
// can just treat them as bits
if p.Packed {
p.enc = (*Buffer).enc_slice_packed_uint32
p.size = size_slice_packed_uint32
} else {
p.enc = (*Buffer).enc_slice_uint32
p.size = size_slice_uint32
}
p.dec = (*Buffer).dec_slice_int32
p.packedDec = (*Buffer).dec_slice_packed_int32
case 64:
// can just treat them as bits
if p.Packed {
p.enc = (*Buffer).enc_slice_packed_int64
p.size = size_slice_packed_int64
} else {
p.enc = (*Buffer).enc_slice_int64
p.size = size_slice_int64
}
p.dec = (*Buffer).dec_slice_int64
p.packedDec = (*Buffer).dec_slice_packed_int64
default:
logNoSliceEnc(t1, t2)
break
}
case reflect.String:
p.enc = (*Buffer).enc_slice_string
p.dec = (*Buffer).dec_slice_string
p.size = size_slice_string
case reflect.Ptr:
switch t3 := t2.Elem(); t3.Kind() {
default:
fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
break
case reflect.Struct:
p.stype = t2.Elem()
p.isMarshaler = isMarshaler(t2)
p.isUnmarshaler = isUnmarshaler(t2)
if p.Wire == "bytes" {
p.enc = (*Buffer).enc_slice_struct_message
p.dec = (*Buffer).dec_slice_struct_message
p.size = size_slice_struct_message
} else {
p.enc = (*Buffer).enc_slice_struct_group
p.dec = (*Buffer).dec_slice_struct_group
p.size = size_slice_struct_group
}
}
case reflect.Slice:
switch t2.Elem().Kind() {
default:
fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
break
case reflect.Uint8:
p.enc = (*Buffer).enc_slice_slice_byte
p.dec = (*Buffer).dec_slice_slice_byte
p.size = size_slice_slice_byte
p.stype = t3
}
case reflect.Struct:
p.setSliceOfNonPointerStructs(t1)
p.stype = t2
}
case reflect.Map:
p.enc = (*Buffer).enc_new_map
p.dec = (*Buffer).dec_new_map
p.size = size_new_map
p.mtype = t1
p.mkeyprop = &Properties{}
@ -659,20 +336,6 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock
}
func (p *Properties) setTag(lockGetProp bool) {
// precalculate tag code
wire := p.WireType
if p.Packed {
wire = WireBytes
}
x := uint32(p.Tag)<<3 | uint32(wire)
i := 0
for i = 0; x > 127; i++ {
p.tagbuf[i] = 0x80 | uint8(x&0x7F)
x >>= 7
}
p.tagbuf[i] = uint8(x)
p.tagcode = p.tagbuf[0 : i+1]
if p.stype != nil {
if lockGetProp {
p.sprop = GetProperties(p.stype)
@ -683,20 +346,9 @@ func (p *Properties) setTag(lockGetProp bool) {
}
var (
marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
)
// isMarshaler reports whether type t implements Marshaler.
func isMarshaler(t reflect.Type) bool {
return t.Implements(marshalerType)
}
// isUnmarshaler reports whether type t implements Unmarshaler.
func isUnmarshaler(t reflect.Type) bool {
return t.Implements(unmarshalerType)
}
// Init populates the properties from a protocol buffer struct tag.
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
p.init(typ, name, tag, f, true)
@ -706,14 +358,11 @@ func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructF
// "bytes,49,opt,def=hello!"
p.Name = name
p.OrigName = name
if f != nil {
p.field = toField(f)
}
if tag == "" {
return
}
p.Parse(tag)
p.setEncAndDec(typ, f, lockGetProp)
p.setFieldProps(typ, f, lockGetProp)
}
var (
@ -763,10 +412,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
propertiesMap[t] = prop
// build properties
prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) ||
reflect.PtrTo(t).Implements(extendableProtoV1Type) ||
reflect.PtrTo(t).Implements(extendableBytesType)
prop.unrecField = invalidField
prop.Prop = make([]*Properties, t.NumField())
prop.order = make([]int, t.NumField())
@ -777,23 +422,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
name := f.Name
p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
if f.Name == "XXX_InternalExtensions" { // special case
p.enc = (*Buffer).enc_exts
p.dec = nil // not needed
p.size = size_exts
} else if f.Name == "XXX_extensions" { // special case
if len(f.Tag.Get("protobuf")) > 0 {
p.enc = (*Buffer).enc_ext_slice_byte
p.dec = nil // not needed
p.size = size_ext_slice_byte
} else {
p.enc = (*Buffer).enc_map
p.dec = nil // not needed
p.size = size_map
}
} else if f.Name == "XXX_unrecognized" { // special case
prop.unrecField = toField(&f)
}
oneof := f.Tag.Get("protobuf_oneof") // special case
if oneof != "" {
isOneofMessage = true
@ -809,9 +437,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
}
print("\n")
}
if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" {
fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
}
}
// Re-order prop.order.
@ -822,8 +447,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
}
if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); isOneofMessage && ok {
var oots []interface{}
prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs()
prop.stype = t
_, _, _, oots = om.XXX_OneofFuncs()
// Interpret oneof metadata.
prop.OneofTypes = make(map[string]*OneofProperties)
@ -873,30 +497,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
return prop
}
// Return the Properties object for the x[0]'th field of the structure.
func propByIndex(t reflect.Type, x []int) *Properties {
if len(x) != 1 {
fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
return nil
}
prop := GetProperties(t)
return prop.Prop[x[0]]
}
// Get the address and type of a pointer to a struct from an interface.
func getbase(pb Message) (t reflect.Type, b structPointer, err error) {
if pb == nil {
err = ErrNil
return
}
// get the reflect type of the pointer to the struct.
t = reflect.TypeOf(pb)
// get the address of the struct.
value := reflect.ValueOf(pb)
b = toStructPointer(value)
return
}
// A global registry of enum types.
// The generated code will register the generated maps by calling RegisterEnum.
@ -925,20 +525,42 @@ func EnumValueMap(enumType string) map[string]int32 {
// A registry of all linked message types.
// The string is a fully-qualified proto name ("pkg.Message").
var (
protoTypes = make(map[string]reflect.Type)
revProtoTypes = make(map[reflect.Type]string)
protoTypedNils = make(map[string]Message) // a map from proto names to typed nil pointers
protoMapTypes = make(map[string]reflect.Type) // a map from proto names to map types
revProtoTypes = make(map[reflect.Type]string)
)
// RegisterType is called from generated code and maps from the fully qualified
// proto name to the type (pointer to struct) of the protocol buffer.
func RegisterType(x Message, name string) {
if _, ok := protoTypes[name]; ok {
if _, ok := protoTypedNils[name]; ok {
// TODO: Some day, make this a panic.
log.Printf("proto: duplicate proto type registered: %s", name)
return
}
t := reflect.TypeOf(x)
protoTypes[name] = t
if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
// Generated code always calls RegisterType with nil x.
// This check is just for extra safety.
protoTypedNils[name] = x
} else {
protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
}
revProtoTypes[t] = name
}
// RegisterMapType is called from generated code and maps from the fully qualified
// proto name to the native map type of the proto map definition.
func RegisterMapType(x interface{}, name string) {
if reflect.TypeOf(x).Kind() != reflect.Map {
panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
}
if _, ok := protoMapTypes[name]; ok {
log.Printf("proto: duplicate proto type registered: %s", name)
return
}
t := reflect.TypeOf(x)
protoMapTypes[name] = t
revProtoTypes[t] = name
}
@ -954,7 +576,14 @@ func MessageName(x Message) string {
}
// MessageType returns the message type (pointer to struct) for a named message.
func MessageType(name string) reflect.Type { return protoTypes[name] }
// The type is not guaranteed to implement proto.Message if the name refers to a
// map entry.
func MessageType(name string) reflect.Type {
if t, ok := protoTypedNils[name]; ok {
return reflect.TypeOf(t)
}
return protoMapTypes[name]
}
// A registry of all linked proto files.
var (

View file

@ -1,6 +1,6 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// Copyright (c) 2018, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
@ -29,83 +29,8 @@
package proto
import (
"fmt"
"os"
"reflect"
)
func (p *Properties) setCustomEncAndDec(typ reflect.Type) {
p.ctype = typ
if p.Repeated {
p.enc = (*Buffer).enc_custom_slice_bytes
p.dec = (*Buffer).dec_custom_slice_bytes
p.size = size_custom_slice_bytes
} else if typ.Kind() == reflect.Ptr {
p.enc = (*Buffer).enc_custom_bytes
p.dec = (*Buffer).dec_custom_bytes
p.size = size_custom_bytes
} else {
p.enc = (*Buffer).enc_custom_ref_bytes
p.dec = (*Buffer).dec_custom_ref_bytes
p.size = size_custom_ref_bytes
}
}
func (p *Properties) setDurationEncAndDec(typ reflect.Type) {
if p.Repeated {
if typ.Elem().Kind() == reflect.Ptr {
p.enc = (*Buffer).enc_slice_duration
p.dec = (*Buffer).dec_slice_duration
p.size = size_slice_duration
} else {
p.enc = (*Buffer).enc_slice_ref_duration
p.dec = (*Buffer).dec_slice_ref_duration
p.size = size_slice_ref_duration
}
} else if typ.Kind() == reflect.Ptr {
p.enc = (*Buffer).enc_duration
p.dec = (*Buffer).dec_duration
p.size = size_duration
} else {
p.enc = (*Buffer).enc_ref_duration
p.dec = (*Buffer).dec_ref_duration
p.size = size_ref_duration
}
}
func (p *Properties) setTimeEncAndDec(typ reflect.Type) {
if p.Repeated {
if typ.Elem().Kind() == reflect.Ptr {
p.enc = (*Buffer).enc_slice_time
p.dec = (*Buffer).dec_slice_time
p.size = size_slice_time
} else {
p.enc = (*Buffer).enc_slice_ref_time
p.dec = (*Buffer).dec_slice_ref_time
p.size = size_slice_ref_time
}
} else if typ.Kind() == reflect.Ptr {
p.enc = (*Buffer).enc_time
p.dec = (*Buffer).dec_time
p.size = size_time
} else {
p.enc = (*Buffer).enc_ref_time
p.dec = (*Buffer).dec_ref_time
p.size = size_ref_time
}
}
func (p *Properties) setSliceOfNonPointerStructs(typ reflect.Type) {
t2 := typ.Elem()
p.sstype = typ
p.stype = t2
p.isMarshaler = isMarshaler(t2)
p.isUnmarshaler = isUnmarshaler(t2)
p.enc = (*Buffer).enc_slice_ref_struct_message
p.dec = (*Buffer).dec_slice_ref_struct_message
p.size = size_slice_ref_struct_message
if p.Wire != "bytes" {
fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T \n", typ, t2)
}
}
var sizerType = reflect.TypeOf((*Sizer)(nil)).Elem()
var protosizerType = reflect.TypeOf((*ProtoSizer)(nil)).Elem()

View file

@ -0,0 +1,7 @@
regenerate:
go install github.com/gogo/protobuf/protoc-min-version
protoc-min-version --version="3.0.0" --gogo_out=\
Mtest_proto/test.proto=github.com/gogo/protobuf/proto/test_proto,\
Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types:. \
--proto_path=../../protobuf:../:. proto3.proto

View file

@ -1,26 +1,13 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: proto3_proto/proto3.proto
// source: proto3.proto
/*
Package proto3_proto is a generated protocol buffer package.
It is generated from these files:
proto3_proto/proto3.proto
It has these top-level messages:
Message
Nested
MessageWithMap
IntMap
IntMaps
*/
package proto3_proto
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import google_protobuf "github.com/gogo/protobuf/types"
import testdata "github.com/gogo/protobuf/proto/testdata"
import test_proto "github.com/gogo/protobuf/proto/test_proto"
import types "github.com/gogo/protobuf/types"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
@ -58,33 +45,58 @@ var Message_Humour_value = map[string]int32{
func (x Message_Humour) String() string {
return proto.EnumName(Message_Humour_name, int32(x))
}
func (Message_Humour) EnumDescriptor() ([]byte, []int) { return fileDescriptorProto3, []int{0, 0} }
type Message struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,proto3,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"`
HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,json=heightInCm,proto3" json:"height_in_cm,omitempty"`
Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
ResultCount int64 `protobuf:"varint,7,opt,name=result_count,json=resultCount,proto3" json:"result_count,omitempty"`
TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,json=trueScotsman,proto3" json:"true_scotsman,omitempty"`
Score float32 `protobuf:"fixed32,9,opt,name=score,proto3" json:"score,omitempty"`
Key []uint64 `protobuf:"varint,5,rep,packed,name=key" json:"key,omitempty"`
ShortKey []int32 `protobuf:"varint,19,rep,packed,name=short_key,json=shortKey" json:"short_key,omitempty"`
Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"`
RFunny []Message_Humour `protobuf:"varint,16,rep,packed,name=r_funny,json=rFunny,enum=proto3_proto.Message_Humour" json:"r_funny,omitempty"`
Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
Proto2Field *testdata.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field,json=proto2Field" json:"proto2_field,omitempty"`
Proto2Value map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value,json=proto2Value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
Anything *google_protobuf.Any `protobuf:"bytes,14,opt,name=anything" json:"anything,omitempty"`
ManyThings []*google_protobuf.Any `protobuf:"bytes,15,rep,name=many_things,json=manyThings" json:"many_things,omitempty"`
Submessage *Message `protobuf:"bytes,17,opt,name=submessage" json:"submessage,omitempty"`
Children []*Message `protobuf:"bytes,18,rep,name=children" json:"children,omitempty"`
func (Message_Humour) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_proto3_15962acfc6007607, []int{0, 0}
}
func (m *Message) Reset() { *m = Message{} }
func (m *Message) String() string { return proto.CompactTextString(m) }
func (*Message) ProtoMessage() {}
func (*Message) Descriptor() ([]byte, []int) { return fileDescriptorProto3, []int{0} }
type Message struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,proto3,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"`
HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,json=heightInCm,proto3" json:"height_in_cm,omitempty"`
Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
ResultCount int64 `protobuf:"varint,7,opt,name=result_count,json=resultCount,proto3" json:"result_count,omitempty"`
TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,json=trueScotsman,proto3" json:"true_scotsman,omitempty"`
Score float32 `protobuf:"fixed32,9,opt,name=score,proto3" json:"score,omitempty"`
Key []uint64 `protobuf:"varint,5,rep,packed,name=key" json:"key,omitempty"`
ShortKey []int32 `protobuf:"varint,19,rep,packed,name=short_key,json=shortKey" json:"short_key,omitempty"`
Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"`
RFunny []Message_Humour `protobuf:"varint,16,rep,packed,name=r_funny,json=rFunny,enum=proto3_proto.Message_Humour" json:"r_funny,omitempty"`
Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
Proto2Field *test_proto.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field,json=proto2Field" json:"proto2_field,omitempty"`
Proto2Value map[string]*test_proto.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value,json=proto2Value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
Anything *types.Any `protobuf:"bytes,14,opt,name=anything" json:"anything,omitempty"`
ManyThings []*types.Any `protobuf:"bytes,15,rep,name=many_things,json=manyThings" json:"many_things,omitempty"`
Submessage *Message `protobuf:"bytes,17,opt,name=submessage" json:"submessage,omitempty"`
Children []*Message `protobuf:"bytes,18,rep,name=children" json:"children,omitempty"`
StringMap map[string]string `protobuf:"bytes,20,rep,name=string_map,json=stringMap" json:"string_map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Message) Reset() { *m = Message{} }
func (m *Message) String() string { return proto.CompactTextString(m) }
func (*Message) ProtoMessage() {}
func (*Message) Descriptor() ([]byte, []int) {
return fileDescriptor_proto3_15962acfc6007607, []int{0}
}
func (m *Message) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Message.Unmarshal(m, b)
}
func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Message.Marshal(b, m, deterministic)
}
func (dst *Message) XXX_Merge(src proto.Message) {
xxx_messageInfo_Message.Merge(dst, src)
}
func (m *Message) XXX_Size() int {
return xxx_messageInfo_Message.Size(m)
}
func (m *Message) XXX_DiscardUnknown() {
xxx_messageInfo_Message.DiscardUnknown(m)
}
var xxx_messageInfo_Message proto.InternalMessageInfo
func (m *Message) GetName() string {
if m != nil {
@ -170,28 +182,28 @@ func (m *Message) GetTerrain() map[string]*Nested {
return nil
}
func (m *Message) GetProto2Field() *testdata.SubDefaults {
func (m *Message) GetProto2Field() *test_proto.SubDefaults {
if m != nil {
return m.Proto2Field
}
return nil
}
func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults {
func (m *Message) GetProto2Value() map[string]*test_proto.SubDefaults {
if m != nil {
return m.Proto2Value
}
return nil
}
func (m *Message) GetAnything() *google_protobuf.Any {
func (m *Message) GetAnything() *types.Any {
if m != nil {
return m.Anything
}
return nil
}
func (m *Message) GetManyThings() []*google_protobuf.Any {
func (m *Message) GetManyThings() []*types.Any {
if m != nil {
return m.ManyThings
}
@ -212,15 +224,44 @@ func (m *Message) GetChildren() []*Message {
return nil
}
type Nested struct {
Bunny string `protobuf:"bytes,1,opt,name=bunny,proto3" json:"bunny,omitempty"`
Cute bool `protobuf:"varint,2,opt,name=cute,proto3" json:"cute,omitempty"`
func (m *Message) GetStringMap() map[string]string {
if m != nil {
return m.StringMap
}
return nil
}
func (m *Nested) Reset() { *m = Nested{} }
func (m *Nested) String() string { return proto.CompactTextString(m) }
func (*Nested) ProtoMessage() {}
func (*Nested) Descriptor() ([]byte, []int) { return fileDescriptorProto3, []int{1} }
type Nested struct {
Bunny string `protobuf:"bytes,1,opt,name=bunny,proto3" json:"bunny,omitempty"`
Cute bool `protobuf:"varint,2,opt,name=cute,proto3" json:"cute,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Nested) Reset() { *m = Nested{} }
func (m *Nested) String() string { return proto.CompactTextString(m) }
func (*Nested) ProtoMessage() {}
func (*Nested) Descriptor() ([]byte, []int) {
return fileDescriptor_proto3_15962acfc6007607, []int{1}
}
func (m *Nested) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Nested.Unmarshal(m, b)
}
func (m *Nested) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Nested.Marshal(b, m, deterministic)
}
func (dst *Nested) XXX_Merge(src proto.Message) {
xxx_messageInfo_Nested.Merge(dst, src)
}
func (m *Nested) XXX_Size() int {
return xxx_messageInfo_Nested.Size(m)
}
func (m *Nested) XXX_DiscardUnknown() {
xxx_messageInfo_Nested.DiscardUnknown(m)
}
var xxx_messageInfo_Nested proto.InternalMessageInfo
func (m *Nested) GetBunny() string {
if m != nil {
@ -237,13 +278,35 @@ func (m *Nested) GetCute() bool {
}
type MessageWithMap struct {
ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping,json=byteMapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping,json=byteMapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *MessageWithMap) Reset() { *m = MessageWithMap{} }
func (m *MessageWithMap) String() string { return proto.CompactTextString(m) }
func (*MessageWithMap) ProtoMessage() {}
func (*MessageWithMap) Descriptor() ([]byte, []int) { return fileDescriptorProto3, []int{2} }
func (m *MessageWithMap) Reset() { *m = MessageWithMap{} }
func (m *MessageWithMap) String() string { return proto.CompactTextString(m) }
func (*MessageWithMap) ProtoMessage() {}
func (*MessageWithMap) Descriptor() ([]byte, []int) {
return fileDescriptor_proto3_15962acfc6007607, []int{2}
}
func (m *MessageWithMap) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_MessageWithMap.Unmarshal(m, b)
}
func (m *MessageWithMap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_MessageWithMap.Marshal(b, m, deterministic)
}
func (dst *MessageWithMap) XXX_Merge(src proto.Message) {
xxx_messageInfo_MessageWithMap.Merge(dst, src)
}
func (m *MessageWithMap) XXX_Size() int {
return xxx_messageInfo_MessageWithMap.Size(m)
}
func (m *MessageWithMap) XXX_DiscardUnknown() {
xxx_messageInfo_MessageWithMap.DiscardUnknown(m)
}
var xxx_messageInfo_MessageWithMap proto.InternalMessageInfo
func (m *MessageWithMap) GetByteMapping() map[bool][]byte {
if m != nil {
@ -253,13 +316,35 @@ func (m *MessageWithMap) GetByteMapping() map[bool][]byte {
}
type IntMap struct {
Rtt map[int32]int32 `protobuf:"bytes,1,rep,name=rtt" json:"rtt,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
Rtt map[int32]int32 `protobuf:"bytes,1,rep,name=rtt" json:"rtt,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *IntMap) Reset() { *m = IntMap{} }
func (m *IntMap) String() string { return proto.CompactTextString(m) }
func (*IntMap) ProtoMessage() {}
func (*IntMap) Descriptor() ([]byte, []int) { return fileDescriptorProto3, []int{3} }
func (m *IntMap) Reset() { *m = IntMap{} }
func (m *IntMap) String() string { return proto.CompactTextString(m) }
func (*IntMap) ProtoMessage() {}
func (*IntMap) Descriptor() ([]byte, []int) {
return fileDescriptor_proto3_15962acfc6007607, []int{3}
}
func (m *IntMap) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_IntMap.Unmarshal(m, b)
}
func (m *IntMap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_IntMap.Marshal(b, m, deterministic)
}
func (dst *IntMap) XXX_Merge(src proto.Message) {
xxx_messageInfo_IntMap.Merge(dst, src)
}
func (m *IntMap) XXX_Size() int {
return xxx_messageInfo_IntMap.Size(m)
}
func (m *IntMap) XXX_DiscardUnknown() {
xxx_messageInfo_IntMap.DiscardUnknown(m)
}
var xxx_messageInfo_IntMap proto.InternalMessageInfo
func (m *IntMap) GetRtt() map[int32]int32 {
if m != nil {
@ -269,13 +354,35 @@ func (m *IntMap) GetRtt() map[int32]int32 {
}
type IntMaps struct {
Maps []*IntMap `protobuf:"bytes,1,rep,name=maps" json:"maps,omitempty"`
Maps []*IntMap `protobuf:"bytes,1,rep,name=maps" json:"maps,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *IntMaps) Reset() { *m = IntMaps{} }
func (m *IntMaps) String() string { return proto.CompactTextString(m) }
func (*IntMaps) ProtoMessage() {}
func (*IntMaps) Descriptor() ([]byte, []int) { return fileDescriptorProto3, []int{4} }
func (m *IntMaps) Reset() { *m = IntMaps{} }
func (m *IntMaps) String() string { return proto.CompactTextString(m) }
func (*IntMaps) ProtoMessage() {}
func (*IntMaps) Descriptor() ([]byte, []int) {
return fileDescriptor_proto3_15962acfc6007607, []int{4}
}
func (m *IntMaps) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_IntMaps.Unmarshal(m, b)
}
func (m *IntMaps) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_IntMaps.Marshal(b, m, deterministic)
}
func (dst *IntMaps) XXX_Merge(src proto.Message) {
xxx_messageInfo_IntMaps.Merge(dst, src)
}
func (m *IntMaps) XXX_Size() int {
return xxx_messageInfo_IntMaps.Size(m)
}
func (m *IntMaps) XXX_DiscardUnknown() {
xxx_messageInfo_IntMaps.DiscardUnknown(m)
}
var xxx_messageInfo_IntMaps proto.InternalMessageInfo
func (m *IntMaps) GetMaps() []*IntMap {
if m != nil {
@ -286,61 +393,69 @@ func (m *IntMaps) GetMaps() []*IntMap {
func init() {
proto.RegisterType((*Message)(nil), "proto3_proto.Message")
proto.RegisterMapType((map[string]*test_proto.SubDefaults)(nil), "proto3_proto.Message.Proto2ValueEntry")
proto.RegisterMapType((map[string]string)(nil), "proto3_proto.Message.StringMapEntry")
proto.RegisterMapType((map[string]*Nested)(nil), "proto3_proto.Message.TerrainEntry")
proto.RegisterType((*Nested)(nil), "proto3_proto.Nested")
proto.RegisterType((*MessageWithMap)(nil), "proto3_proto.MessageWithMap")
proto.RegisterMapType((map[bool][]byte)(nil), "proto3_proto.MessageWithMap.ByteMappingEntry")
proto.RegisterType((*IntMap)(nil), "proto3_proto.IntMap")
proto.RegisterMapType((map[int32]int32)(nil), "proto3_proto.IntMap.RttEntry")
proto.RegisterType((*IntMaps)(nil), "proto3_proto.IntMaps")
proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value)
}
func init() { proto.RegisterFile("proto3_proto/proto3.proto", fileDescriptorProto3) }
func init() { proto.RegisterFile("proto3.proto", fileDescriptor_proto3_15962acfc6007607) }
var fileDescriptorProto3 = []byte{
// 733 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x53, 0x6d, 0x6f, 0xf3, 0x34,
0x14, 0x25, 0x4d, 0x5f, 0xd2, 0x9b, 0x74, 0x0b, 0x5e, 0x91, 0xbc, 0x02, 0x52, 0x28, 0x12, 0x8a,
0x78, 0x49, 0xa1, 0xd3, 0xd0, 0x84, 0x10, 0x68, 0x1b, 0x9b, 0xa8, 0xd6, 0x95, 0xca, 0xdd, 0x98,
0xf8, 0x14, 0xa5, 0xad, 0xdb, 0x46, 0x34, 0x4e, 0x49, 0x1c, 0xa4, 0xfc, 0x1d, 0xfe, 0x28, 0x8f,
0x6c, 0xa7, 0x5d, 0x36, 0x65, 0xcf, 0xf3, 0x29, 0xf6, 0xf1, 0xb9, 0xf7, 0x9c, 0x1c, 0x5f, 0xc3,
0xe9, 0x2e, 0x89, 0x79, 0x7c, 0xe6, 0xcb, 0xcf, 0x40, 0x6d, 0x3c, 0xf9, 0x41, 0x56, 0xf9, 0xa8,
0x77, 0xba, 0x8e, 0xe3, 0xf5, 0x96, 0x2a, 0xca, 0x3c, 0x5b, 0x0d, 0x02, 0x96, 0x2b, 0x62, 0xef,
0x84, 0xd3, 0x94, 0x2f, 0x03, 0x1e, 0x0c, 0xc4, 0x42, 0x81, 0xfd, 0xff, 0x5b, 0xd0, 0xba, 0xa7,
0x69, 0x1a, 0xac, 0x29, 0x42, 0x50, 0x67, 0x41, 0x44, 0xb1, 0xe6, 0x68, 0x6e, 0x9b, 0xc8, 0x35,
0xba, 0x00, 0x63, 0x13, 0x6e, 0x83, 0x24, 0xe4, 0x39, 0xae, 0x39, 0x9a, 0x7b, 0x34, 0xfc, 0xcc,
0x2b, 0x0b, 0x7a, 0x45, 0xb1, 0xf7, 0x7b, 0x16, 0xc5, 0x59, 0x42, 0x0e, 0x6c, 0xe4, 0x80, 0xb5,
0xa1, 0xe1, 0x7a, 0xc3, 0xfd, 0x90, 0xf9, 0x8b, 0x08, 0xeb, 0x8e, 0xe6, 0x76, 0x08, 0x28, 0x6c,
0xc4, 0xae, 0x23, 0xa1, 0x27, 0xec, 0xe0, 0xba, 0xa3, 0xb9, 0x16, 0x91, 0x6b, 0xf4, 0x05, 0x58,
0x09, 0x4d, 0xb3, 0x2d, 0xf7, 0x17, 0x71, 0xc6, 0x38, 0x6e, 0x39, 0x9a, 0xab, 0x13, 0x53, 0x61,
0xd7, 0x02, 0x42, 0x5f, 0x42, 0x87, 0x27, 0x19, 0xf5, 0xd3, 0x45, 0xcc, 0xd3, 0x28, 0x60, 0xd8,
0x70, 0x34, 0xd7, 0x20, 0x96, 0x00, 0x67, 0x05, 0x86, 0xba, 0xd0, 0x48, 0x17, 0x71, 0x42, 0x71,
0xdb, 0xd1, 0xdc, 0x1a, 0x51, 0x1b, 0x64, 0x83, 0xfe, 0x37, 0xcd, 0x71, 0xc3, 0xd1, 0xdd, 0x3a,
0x11, 0x4b, 0xf4, 0x29, 0xb4, 0xd3, 0x4d, 0x9c, 0x70, 0x5f, 0xe0, 0x27, 0x8e, 0xee, 0x36, 0x88,
0x21, 0x81, 0x3b, 0x9a, 0xa3, 0x6f, 0xa1, 0xc9, 0x68, 0xca, 0xe9, 0x12, 0x37, 0x1d, 0xcd, 0x35,
0x87, 0xdd, 0x97, 0xbf, 0x3e, 0x91, 0x67, 0xa4, 0xe0, 0xa0, 0x73, 0x68, 0x25, 0xfe, 0x2a, 0x63,
0x2c, 0xc7, 0xb6, 0xa3, 0x7f, 0x30, 0xa9, 0x66, 0x72, 0x2b, 0xb8, 0xe8, 0x67, 0x68, 0x71, 0x9a,
0x24, 0x41, 0xc8, 0x30, 0x38, 0xba, 0x6b, 0x0e, 0xfb, 0xd5, 0x65, 0x0f, 0x8a, 0x74, 0xc3, 0x78,
0x92, 0x93, 0x7d, 0x09, 0xba, 0x00, 0x75, 0xff, 0x43, 0x7f, 0x15, 0xd2, 0xed, 0x12, 0x9b, 0xd2,
0xe8, 0x27, 0xde, 0xfe, 0xae, 0xbd, 0x59, 0x36, 0xff, 0x8d, 0xae, 0x82, 0x6c, 0xcb, 0x53, 0x62,
0x2a, 0xea, 0xad, 0x60, 0xa2, 0xd1, 0xa1, 0xf2, 0xdf, 0x60, 0x9b, 0x51, 0xdc, 0x91, 0xe2, 0x5f,
0x55, 0x8b, 0x4f, 0x25, 0xf3, 0x4f, 0x41, 0x54, 0x06, 0x8a, 0x56, 0x12, 0x41, 0xdf, 0x83, 0x11,
0xb0, 0x9c, 0x6f, 0x42, 0xb6, 0xc6, 0x47, 0x45, 0x52, 0x6a, 0x0e, 0xbd, 0xfd, 0x1c, 0x7a, 0x97,
0x2c, 0x27, 0x07, 0x16, 0x3a, 0x07, 0x33, 0x0a, 0x58, 0xee, 0xcb, 0x5d, 0x8a, 0x8f, 0xa5, 0x76,
0x75, 0x11, 0x08, 0xe2, 0x83, 0xe4, 0xa1, 0x73, 0x80, 0x34, 0x9b, 0x47, 0xca, 0x14, 0xfe, 0xb8,
0xf8, 0xd7, 0x2a, 0xc7, 0xa4, 0x44, 0x44, 0x3f, 0x80, 0xb1, 0xd8, 0x84, 0xdb, 0x65, 0x42, 0x19,
0x46, 0x52, 0xea, 0x8d, 0xa2, 0x03, 0xad, 0x37, 0x05, 0xab, 0x1c, 0xf8, 0x7e, 0x72, 0xd4, 0xd3,
0x90, 0x93, 0xf3, 0x35, 0x34, 0x54, 0x70, 0xb5, 0xf7, 0xcc, 0x86, 0xa2, 0xfc, 0x54, 0xbb, 0xd0,
0x7a, 0x8f, 0x60, 0xbf, 0x4e, 0xb1, 0xa2, 0xeb, 0x37, 0x2f, 0xbb, 0xbe, 0x71, 0x91, 0xcf, 0x6d,
0xfb, 0xbf, 0x42, 0x53, 0x0d, 0x14, 0x32, 0xa1, 0xf5, 0x38, 0xb9, 0x9b, 0xfc, 0xf1, 0x34, 0xb1,
0x3f, 0x42, 0x06, 0xd4, 0xa7, 0x8f, 0x93, 0x99, 0xad, 0xa1, 0x0e, 0xb4, 0x67, 0xe3, 0xcb, 0xe9,
0xec, 0x61, 0x74, 0x7d, 0x67, 0xd7, 0xd0, 0x31, 0x98, 0x57, 0xa3, 0xf1, 0xd8, 0xbf, 0xba, 0x1c,
0x8d, 0x6f, 0xfe, 0xb2, 0xf5, 0xfe, 0x10, 0x9a, 0xca, 0xac, 0x78, 0x33, 0x73, 0x39, 0xbe, 0xca,
0x8f, 0xda, 0x88, 0x57, 0xba, 0xc8, 0xb8, 0x32, 0x64, 0x10, 0xb9, 0xee, 0xff, 0xa7, 0xc1, 0x51,
0x91, 0xd9, 0x53, 0xc8, 0x37, 0xf7, 0xc1, 0x0e, 0x4d, 0xc1, 0x9a, 0xe7, 0x9c, 0xfa, 0x51, 0xb0,
0xdb, 0x89, 0x39, 0xd0, 0x64, 0xce, 0xdf, 0x55, 0xe6, 0x5c, 0xd4, 0x78, 0x57, 0x39, 0xa7, 0xf7,
0x8a, 0x5f, 0x4c, 0xd5, 0xfc, 0x19, 0xe9, 0xfd, 0x02, 0xf6, 0x6b, 0x42, 0x39, 0x30, 0x43, 0x05,
0xd6, 0x2d, 0x07, 0x66, 0x95, 0x93, 0xf9, 0x07, 0x9a, 0x23, 0xc6, 0x85, 0xb7, 0x01, 0xe8, 0x09,
0xe7, 0x85, 0xa5, 0xcf, 0x5f, 0x5a, 0x52, 0x14, 0x8f, 0x70, 0xae, 0x2c, 0x08, 0x66, 0xef, 0x47,
0x30, 0xf6, 0x40, 0x59, 0xb2, 0x51, 0x21, 0xd9, 0x28, 0x4b, 0x9e, 0x41, 0x4b, 0xf5, 0x4b, 0x91,
0x0b, 0xf5, 0x28, 0xd8, 0xa5, 0x85, 0x68, 0xb7, 0x4a, 0x94, 0x48, 0xc6, 0xbc, 0xa9, 0x8e, 0xde,
0x05, 0x00, 0x00, 0xff, 0xff, 0x75, 0x38, 0xad, 0x84, 0xe4, 0x05, 0x00, 0x00,
var fileDescriptor_proto3_15962acfc6007607 = []byte{
// 771 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x94, 0xff, 0x6e, 0xe3, 0x44,
0x10, 0xc7, 0x71, 0x9c, 0x1f, 0xce, 0xd8, 0xed, 0x99, 0x25, 0x27, 0x96, 0x00, 0x92, 0x09, 0x08,
0x59, 0x88, 0x73, 0x21, 0xa7, 0xa2, 0xd3, 0xe9, 0x04, 0x6a, 0xcb, 0x9d, 0x88, 0xda, 0x86, 0x68,
0xd3, 0xa3, 0xe2, 0x2f, 0x6b, 0x93, 0x6e, 0x12, 0x8b, 0x78, 0x1d, 0xbc, 0x6b, 0x24, 0xbf, 0x00,
0x0f, 0xc2, 0x93, 0xa2, 0xdd, 0x75, 0x72, 0xce, 0xc9, 0x85, 0xbf, 0xbc, 0x33, 0xfe, 0xcc, 0x7c,
0x67, 0x67, 0xc6, 0x06, 0x6f, 0x97, 0x67, 0x32, 0x7b, 0x1e, 0xe9, 0x07, 0xaa, 0xac, 0x58, 0x3f,
0x86, 0x9f, 0xac, 0xb3, 0x6c, 0xbd, 0x65, 0x67, 0xda, 0x5a, 0x14, 0xab, 0x33, 0xca, 0x4b, 0x03,
0x0e, 0x9f, 0x4a, 0x26, 0xa4, 0xc1, 0xce, 0xd4, 0xd1, 0xb8, 0x47, 0x7f, 0xf7, 0xa1, 0x77, 0xcb,
0x84, 0xa0, 0x6b, 0x86, 0x10, 0xb4, 0x39, 0x4d, 0x19, 0xb6, 0x02, 0x2b, 0xec, 0x13, 0x7d, 0x46,
0x2f, 0xc0, 0xd9, 0x24, 0x5b, 0x9a, 0x27, 0xb2, 0xc4, 0xad, 0xc0, 0x0a, 0x4f, 0xc7, 0x9f, 0x45,
0x75, 0xc9, 0xa8, 0x0a, 0x8e, 0x7e, 0x29, 0xd2, 0xac, 0xc8, 0xc9, 0x81, 0x46, 0x01, 0x78, 0x1b,
0x96, 0xac, 0x37, 0x32, 0x4e, 0x78, 0xbc, 0x4c, 0xb1, 0x1d, 0x58, 0xe1, 0x09, 0x01, 0xe3, 0x9b,
0xf0, 0xab, 0x54, 0xe9, 0x3d, 0x50, 0x49, 0x71, 0x3b, 0xb0, 0x42, 0x8f, 0xe8, 0x33, 0xfa, 0x02,
0xbc, 0x9c, 0x89, 0x62, 0x2b, 0xe3, 0x65, 0x56, 0x70, 0x89, 0x7b, 0x81, 0x15, 0xda, 0xc4, 0x35,
0xbe, 0x2b, 0xe5, 0x42, 0x5f, 0xc2, 0x89, 0xcc, 0x0b, 0x16, 0x8b, 0x65, 0x26, 0x45, 0x4a, 0x39,
0x76, 0x02, 0x2b, 0x74, 0x88, 0xa7, 0x9c, 0xf3, 0xca, 0x87, 0x06, 0xd0, 0x11, 0xcb, 0x2c, 0x67,
0xb8, 0x1f, 0x58, 0x61, 0x8b, 0x18, 0x03, 0xf9, 0x60, 0xff, 0xc1, 0x4a, 0xdc, 0x09, 0xec, 0xb0,
0x4d, 0xd4, 0x11, 0x7d, 0x0a, 0x7d, 0xb1, 0xc9, 0x72, 0x19, 0x2b, 0xff, 0x47, 0x81, 0x1d, 0x76,
0x88, 0xa3, 0x1d, 0xd7, 0xac, 0x44, 0xdf, 0x42, 0x97, 0x33, 0x21, 0xd9, 0x03, 0xee, 0x06, 0x56,
0xe8, 0x8e, 0x07, 0xc7, 0x57, 0x9f, 0xea, 0x77, 0xa4, 0x62, 0xd0, 0x39, 0xf4, 0xf2, 0x78, 0x55,
0x70, 0x5e, 0x62, 0x3f, 0xb0, 0xff, 0xb7, 0x53, 0xdd, 0xfc, 0x8d, 0x62, 0xd1, 0x2b, 0xe8, 0x49,
0x96, 0xe7, 0x34, 0xe1, 0x18, 0x02, 0x3b, 0x74, 0xc7, 0xa3, 0xe6, 0xb0, 0x3b, 0x03, 0xbd, 0xe6,
0x32, 0x2f, 0xc9, 0x3e, 0x04, 0xbd, 0xac, 0xf6, 0x61, 0x1c, 0xaf, 0x12, 0xb6, 0x7d, 0xc0, 0xae,
0x2e, 0xf4, 0xe3, 0xe8, 0xdd, 0xb4, 0xa3, 0x79, 0xb1, 0xf8, 0x99, 0xad, 0x68, 0xb1, 0x95, 0x82,
0xb8, 0x06, 0x7e, 0xa3, 0x58, 0x34, 0x39, 0xc4, 0xfe, 0x45, 0xb7, 0x05, 0xc3, 0x27, 0x5a, 0xfe,
0xeb, 0x66, 0xf9, 0x99, 0x26, 0x7f, 0x53, 0xa0, 0x29, 0xa1, 0x4a, 0xa5, 0x3d, 0xe8, 0x3b, 0x70,
0x28, 0x2f, 0xe5, 0x26, 0xe1, 0x6b, 0x7c, 0x5a, 0xf5, 0xca, 0xec, 0x62, 0xb4, 0xdf, 0xc5, 0xe8,
0x82, 0x97, 0xe4, 0x40, 0xa1, 0x73, 0x70, 0x53, 0xca, 0xcb, 0x58, 0x5b, 0x02, 0x3f, 0xd1, 0xda,
0xcd, 0x41, 0xa0, 0xc0, 0x3b, 0xcd, 0xa1, 0x73, 0x00, 0x51, 0x2c, 0x52, 0x53, 0x14, 0xfe, 0x50,
0x4b, 0x3d, 0x6d, 0xac, 0x98, 0xd4, 0x40, 0xf4, 0x3d, 0x38, 0xcb, 0x4d, 0xb2, 0x7d, 0xc8, 0x19,
0xc7, 0x48, 0x4b, 0x3d, 0x12, 0x74, 0xc0, 0xd0, 0x15, 0x80, 0x90, 0x79, 0xc2, 0xd7, 0x71, 0x4a,
0x77, 0x78, 0xa0, 0x83, 0xbe, 0x6a, 0xee, 0xcd, 0x5c, 0x73, 0xb7, 0x74, 0x67, 0x3a, 0xd3, 0x17,
0x7b, 0x7b, 0x38, 0x03, 0xaf, 0x3e, 0xb7, 0xfd, 0x02, 0x9a, 0x2f, 0x4c, 0x2f, 0xe0, 0x37, 0xd0,
0x31, 0xdd, 0x6f, 0xfd, 0xc7, 0x8a, 0x19, 0xe4, 0x65, 0xeb, 0x85, 0x35, 0xbc, 0x07, 0xff, 0xfd,
0x51, 0x34, 0x64, 0x7d, 0x76, 0x9c, 0xf5, 0xd1, 0x7d, 0xa8, 0x25, 0x7e, 0x05, 0xa7, 0xc7, 0xf7,
0x68, 0x48, 0x3b, 0xa8, 0xa7, 0xed, 0xd7, 0xa2, 0x47, 0x3f, 0x41, 0xd7, 0xec, 0x35, 0x72, 0xa1,
0xf7, 0x76, 0x7a, 0x3d, 0xfd, 0xf5, 0x7e, 0xea, 0x7f, 0x80, 0x1c, 0x68, 0xcf, 0xde, 0x4e, 0xe7,
0xbe, 0x85, 0x4e, 0xa0, 0x3f, 0xbf, 0xb9, 0x98, 0xcd, 0xef, 0x26, 0x57, 0xd7, 0x7e, 0x0b, 0x3d,
0x01, 0xf7, 0x72, 0x72, 0x73, 0x13, 0x5f, 0x5e, 0x4c, 0x6e, 0x5e, 0xff, 0xee, 0xdb, 0xa3, 0x31,
0x74, 0xcd, 0x65, 0x95, 0xc8, 0x42, 0x7f, 0x45, 0x46, 0xd8, 0x18, 0xea, 0x67, 0xb1, 0x2c, 0xa4,
0x51, 0x76, 0x88, 0x3e, 0x8f, 0xfe, 0xb1, 0xe0, 0xb4, 0x9a, 0xc1, 0x7d, 0x22, 0x37, 0xb7, 0x74,
0x87, 0x66, 0xe0, 0x2d, 0x4a, 0xc9, 0xd4, 0xcc, 0x76, 0x6a, 0x19, 0x2d, 0x3d, 0xb7, 0x67, 0x8d,
0x73, 0xab, 0x62, 0xa2, 0xcb, 0x52, 0xb2, 0x5b, 0xc3, 0x57, 0xab, 0xbd, 0x78, 0xe7, 0x19, 0xfe,
0x08, 0xfe, 0xfb, 0x40, 0xbd, 0x33, 0x4e, 0x43, 0x67, 0xbc, 0x7a, 0x67, 0xfe, 0x84, 0xee, 0x84,
0x4b, 0x55, 0xdb, 0x19, 0xd8, 0xb9, 0x94, 0x55, 0x49, 0x9f, 0x1f, 0x97, 0x64, 0x90, 0x88, 0x48,
0x69, 0x4a, 0x50, 0xe4, 0xf0, 0x07, 0x70, 0xf6, 0x8e, 0xba, 0x64, 0xa7, 0x41, 0xb2, 0x53, 0x97,
0x7c, 0x0e, 0x3d, 0x93, 0x4f, 0xa0, 0x10, 0xda, 0x29, 0xdd, 0x89, 0x4a, 0x74, 0xd0, 0x24, 0x4a,
0x34, 0xb1, 0xe8, 0x9a, 0x57, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x90, 0xaf, 0xe7, 0x60,
0x06, 0x00, 0x00,
}

View file

@ -32,7 +32,7 @@
syntax = "proto3";
import "google/protobuf/any.proto";
import "testdata/test.proto";
import "test_proto/test.proto";
package proto3_proto;
@ -58,14 +58,16 @@ message Message {
repeated Humour r_funny = 16;
map<string, Nested> terrain = 10;
testdata.SubDefaults proto2_field = 11;
map<string, testdata.SubDefaults> proto2_value = 13;
test_proto.SubDefaults proto2_field = 11;
map<string, test_proto.SubDefaults> proto2_value = 13;
google.protobuf.Any anything = 14;
repeated google.protobuf.Any many_things = 15;
Message submessage = 17;
repeated Message children = 18;
map<string, string> string_map = 20;
}
message Nested {
@ -84,4 +86,4 @@ message IntMap {
message IntMaps {
repeated IntMap maps = 1;
}
}

View file

@ -32,11 +32,12 @@
package proto_test
import (
"bytes"
"testing"
"github.com/gogo/protobuf/proto"
pb "github.com/gogo/protobuf/proto/proto3_proto"
tpb "github.com/gogo/protobuf/proto/testdata"
tpb "github.com/gogo/protobuf/proto/test_proto"
)
func TestProto3ZeroValues(t *testing.T) {
@ -133,3 +134,18 @@ func TestProto3SetDefaults(t *testing.T) {
t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want)
}
}
func TestUnknownFieldPreservation(t *testing.T) {
b1 := "\x0a\x05David" // Known tag 1
b2 := "\xc2\x0c\x06Google" // Unknown tag 200
b := []byte(b1 + b2)
m := new(pb.Message)
if err := proto.Unmarshal(b, m); err != nil {
t.Fatalf("proto.Unmarshal: %v", err)
}
if !bytes.Equal(m.XXX_unrecognized, []byte(b2)) {
t.Fatalf("mismatching unknown fields:\ngot %q\nwant %q", m.XXX_unrecognized, b2)
}
}

View file

@ -55,7 +55,7 @@ func TestVarintSize(t *testing.T) {
{1 << 63, 10},
}
for _, tc := range testCases {
size := sizeVarint(tc.n)
size := SizeVarint(tc.n)
if size != tc.size {
t.Errorf("sizeVarint(%d) = %d, want %d", tc.n, size, tc.size)
}

View file

@ -38,7 +38,7 @@ import (
. "github.com/gogo/protobuf/proto"
proto3pb "github.com/gogo/protobuf/proto/proto3_proto"
pb "github.com/gogo/protobuf/proto/testdata"
pb "github.com/gogo/protobuf/proto/test_proto"
)
var messageWithExtension1 = &pb.MyMessage{Count: Int32(7)}
@ -59,6 +59,30 @@ func init() {
}
// non-pointer custom message
type nonptrMessage struct{}
func (m nonptrMessage) ProtoMessage() {}
func (m nonptrMessage) Reset() {}
func (m nonptrMessage) String() string { return "" }
func (m nonptrMessage) Marshal() ([]byte, error) {
return []byte{42}, nil
}
// custom message embedding a proto.Message
type messageWithEmbedding struct {
*pb.OtherMessage
}
func (m *messageWithEmbedding) ProtoMessage() {}
func (m *messageWithEmbedding) Reset() {}
func (m *messageWithEmbedding) String() string { return "" }
func (m *messageWithEmbedding) Marshal() ([]byte, error) {
return []byte{42}, nil
}
var SizeTests = []struct {
desc string
pb Message
@ -146,6 +170,8 @@ var SizeTests = []struct {
{"oneof group", &pb.Oneof{Union: &pb.Oneof_FGroup{FGroup: &pb.Oneof_F_Group{X: Int32(52)}}}},
{"oneof largest tag", &pb.Oneof{Union: &pb.Oneof_F_Largest_Tag{F_Largest_Tag: 1}}},
{"multiple oneofs", &pb.Oneof{Union: &pb.Oneof_F_Int32{F_Int32: 1}, Tormato: &pb.Oneof_Value{Value: 2}}},
{"non-pointer message", nonptrMessage{}},
{"custom message with embedding", &messageWithEmbedding{&pb.OtherMessage{}}},
}
func TestSize(t *testing.T) {

2799
vendor/github.com/gogo/protobuf/proto/table_marshal.go generated vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,388 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2018, 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 proto
import (
"reflect"
"time"
)
// makeMessageRefMarshaler differs a bit from makeMessageMarshaler
// It marshal a message T instead of a *T
func makeMessageRefMarshaler(u *marshalInfo) (sizer, marshaler) {
return func(ptr pointer, tagsize int) int {
siz := u.size(ptr)
return siz + SizeVarint(uint64(siz)) + tagsize
},
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
b = appendVarint(b, wiretag)
siz := u.cachedsize(ptr)
b = appendVarint(b, uint64(siz))
return u.marshal(b, ptr, deterministic)
}
}
// makeMessageRefSliceMarshaler differs quite a lot from makeMessageSliceMarshaler
// It marshals a slice of messages []T instead of []*T
func makeMessageRefSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
return func(ptr pointer, tagsize int) int {
s := ptr.getSlice(u.typ)
n := 0
for i := 0; i < s.Len(); i++ {
elem := s.Index(i)
e := elem.Interface()
v := toAddrPointer(&e, false)
siz := u.size(v)
n += siz + SizeVarint(uint64(siz)) + tagsize
}
return n
},
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
s := ptr.getSlice(u.typ)
var err, errreq error
for i := 0; i < s.Len(); i++ {
elem := s.Index(i)
e := elem.Interface()
v := toAddrPointer(&e, false)
b = appendVarint(b, wiretag)
siz := u.size(v)
b = appendVarint(b, uint64(siz))
b, err = u.marshal(b, v, deterministic)
if err != nil {
if _, ok := err.(*RequiredNotSetError); ok {
// Required field in submessage is not set.
// We record the error but keep going, to give a complete marshaling.
if errreq == nil {
errreq = err
}
continue
}
if err == ErrNil {
err = errRepeatedHasNil
}
return b, err
}
}
return b, errreq
}
}
func makeCustomPtrMarshaler(u *marshalInfo) (sizer, marshaler) {
return func(ptr pointer, tagsize int) int {
if ptr.isNil() {
return 0
}
m := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(custom)
siz := m.Size()
return tagsize + SizeVarint(uint64(siz)) + siz
}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
if ptr.isNil() {
return b, nil
}
m := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(custom)
siz := m.Size()
buf, err := m.Marshal()
if err != nil {
return nil, err
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(siz))
b = append(b, buf...)
return b, nil
}
}
func makeCustomMarshaler(u *marshalInfo) (sizer, marshaler) {
return func(ptr pointer, tagsize int) int {
m := ptr.asPointerTo(u.typ).Interface().(custom)
siz := m.Size()
return tagsize + SizeVarint(uint64(siz)) + siz
}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
m := ptr.asPointerTo(u.typ).Interface().(custom)
siz := m.Size()
buf, err := m.Marshal()
if err != nil {
return nil, err
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(siz))
b = append(b, buf...)
return b, nil
}
}
func makeTimeMarshaler(u *marshalInfo) (sizer, marshaler) {
return func(ptr pointer, tagsize int) int {
t := ptr.asPointerTo(u.typ).Interface().(*time.Time)
ts, err := timestampProto(*t)
if err != nil {
return 0
}
siz := Size(ts)
return tagsize + SizeVarint(uint64(siz)) + siz
}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
t := ptr.asPointerTo(u.typ).Interface().(*time.Time)
ts, err := timestampProto(*t)
if err != nil {
return nil, err
}
buf, err := Marshal(ts)
if err != nil {
return nil, err
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(buf)))
b = append(b, buf...)
return b, nil
}
}
func makeTimePtrMarshaler(u *marshalInfo) (sizer, marshaler) {
return func(ptr pointer, tagsize int) int {
if ptr.isNil() {
return 0
}
t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Time)
ts, err := timestampProto(*t)
if err != nil {
return 0
}
siz := Size(ts)
return tagsize + SizeVarint(uint64(siz)) + siz
}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
if ptr.isNil() {
return b, nil
}
t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Time)
ts, err := timestampProto(*t)
if err != nil {
return nil, err
}
buf, err := Marshal(ts)
if err != nil {
return nil, err
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(buf)))
b = append(b, buf...)
return b, nil
}
}
func makeTimeSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
return func(ptr pointer, tagsize int) int {
s := ptr.getSlice(u.typ)
n := 0
for i := 0; i < s.Len(); i++ {
elem := s.Index(i)
t := elem.Interface().(time.Time)
ts, err := timestampProto(t)
if err != nil {
return 0
}
siz := Size(ts)
n += siz + SizeVarint(uint64(siz)) + tagsize
}
return n
},
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
s := ptr.getSlice(u.typ)
for i := 0; i < s.Len(); i++ {
elem := s.Index(i)
t := elem.Interface().(time.Time)
ts, err := timestampProto(t)
if err != nil {
return nil, err
}
siz := Size(ts)
buf, err := Marshal(ts)
if err != nil {
return nil, err
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(siz))
b = append(b, buf...)
}
return b, nil
}
}
func makeTimePtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
return func(ptr pointer, tagsize int) int {
s := ptr.getSlice(reflect.PtrTo(u.typ))
n := 0
for i := 0; i < s.Len(); i++ {
elem := s.Index(i)
t := elem.Interface().(*time.Time)
ts, err := timestampProto(*t)
if err != nil {
return 0
}
siz := Size(ts)
n += siz + SizeVarint(uint64(siz)) + tagsize
}
return n
},
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
s := ptr.getSlice(reflect.PtrTo(u.typ))
for i := 0; i < s.Len(); i++ {
elem := s.Index(i)
t := elem.Interface().(*time.Time)
ts, err := timestampProto(*t)
if err != nil {
return nil, err
}
siz := Size(ts)
buf, err := Marshal(ts)
if err != nil {
return nil, err
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(siz))
b = append(b, buf...)
}
return b, nil
}
}
func makeDurationMarshaler(u *marshalInfo) (sizer, marshaler) {
return func(ptr pointer, tagsize int) int {
d := ptr.asPointerTo(u.typ).Interface().(*time.Duration)
dur := durationProto(*d)
siz := Size(dur)
return tagsize + SizeVarint(uint64(siz)) + siz
}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
d := ptr.asPointerTo(u.typ).Interface().(*time.Duration)
dur := durationProto(*d)
buf, err := Marshal(dur)
if err != nil {
return nil, err
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(buf)))
b = append(b, buf...)
return b, nil
}
}
func makeDurationPtrMarshaler(u *marshalInfo) (sizer, marshaler) {
return func(ptr pointer, tagsize int) int {
if ptr.isNil() {
return 0
}
d := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Duration)
dur := durationProto(*d)
siz := Size(dur)
return tagsize + SizeVarint(uint64(siz)) + siz
}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
if ptr.isNil() {
return b, nil
}
d := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Duration)
dur := durationProto(*d)
buf, err := Marshal(dur)
if err != nil {
return nil, err
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(buf)))
b = append(b, buf...)
return b, nil
}
}
func makeDurationSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
return func(ptr pointer, tagsize int) int {
s := ptr.getSlice(u.typ)
n := 0
for i := 0; i < s.Len(); i++ {
elem := s.Index(i)
d := elem.Interface().(time.Duration)
dur := durationProto(d)
siz := Size(dur)
n += siz + SizeVarint(uint64(siz)) + tagsize
}
return n
},
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
s := ptr.getSlice(u.typ)
for i := 0; i < s.Len(); i++ {
elem := s.Index(i)
d := elem.Interface().(time.Duration)
dur := durationProto(d)
siz := Size(dur)
buf, err := Marshal(dur)
if err != nil {
return nil, err
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(siz))
b = append(b, buf...)
}
return b, nil
}
}
func makeDurationPtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
return func(ptr pointer, tagsize int) int {
s := ptr.getSlice(reflect.PtrTo(u.typ))
n := 0
for i := 0; i < s.Len(); i++ {
elem := s.Index(i)
d := elem.Interface().(*time.Duration)
dur := durationProto(*d)
siz := Size(dur)
n += siz + SizeVarint(uint64(siz)) + tagsize
}
return n
},
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
s := ptr.getSlice(reflect.PtrTo(u.typ))
for i := 0; i < s.Len(); i++ {
elem := s.Index(i)
d := elem.Interface().(*time.Duration)
dur := durationProto(*d)
siz := Size(dur)
buf, err := Marshal(dur)
if err != nil {
return nil, err
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(siz))
b = append(b, buf...)
}
return b, nil
}
}

657
vendor/github.com/gogo/protobuf/proto/table_merge.go generated vendored Normal file
View file

@ -0,0 +1,657 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2016 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 proto
import (
"fmt"
"reflect"
"strings"
"sync"
"sync/atomic"
)
// Merge merges the src message into dst.
// This assumes that dst and src of the same type and are non-nil.
func (a *InternalMessageInfo) Merge(dst, src Message) {
mi := atomicLoadMergeInfo(&a.merge)
if mi == nil {
mi = getMergeInfo(reflect.TypeOf(dst).Elem())
atomicStoreMergeInfo(&a.merge, mi)
}
mi.merge(toPointer(&dst), toPointer(&src))
}
type mergeInfo struct {
typ reflect.Type
initialized int32 // 0: only typ is valid, 1: everything is valid
lock sync.Mutex
fields []mergeFieldInfo
unrecognized field // Offset of XXX_unrecognized
}
type mergeFieldInfo struct {
field field // Offset of field, guaranteed to be valid
// isPointer reports whether the value in the field is a pointer.
// This is true for the following situations:
// * Pointer to struct
// * Pointer to basic type (proto2 only)
// * Slice (first value in slice header is a pointer)
// * String (first value in string header is a pointer)
isPointer bool
// basicWidth reports the width of the field assuming that it is directly
// embedded in the struct (as is the case for basic types in proto3).
// The possible values are:
// 0: invalid
// 1: bool
// 4: int32, uint32, float32
// 8: int64, uint64, float64
basicWidth int
// Where dst and src are pointers to the types being merged.
merge func(dst, src pointer)
}
var (
mergeInfoMap = map[reflect.Type]*mergeInfo{}
mergeInfoLock sync.Mutex
)
func getMergeInfo(t reflect.Type) *mergeInfo {
mergeInfoLock.Lock()
defer mergeInfoLock.Unlock()
mi := mergeInfoMap[t]
if mi == nil {
mi = &mergeInfo{typ: t}
mergeInfoMap[t] = mi
}
return mi
}
// merge merges src into dst assuming they are both of type *mi.typ.
func (mi *mergeInfo) merge(dst, src pointer) {
if dst.isNil() {
panic("proto: nil destination")
}
if src.isNil() {
return // Nothing to do.
}
if atomic.LoadInt32(&mi.initialized) == 0 {
mi.computeMergeInfo()
}
for _, fi := range mi.fields {
sfp := src.offset(fi.field)
// As an optimization, we can avoid the merge function call cost
// if we know for sure that the source will have no effect
// by checking if it is the zero value.
if unsafeAllowed {
if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string
continue
}
if fi.basicWidth > 0 {
switch {
case fi.basicWidth == 1 && !*sfp.toBool():
continue
case fi.basicWidth == 4 && *sfp.toUint32() == 0:
continue
case fi.basicWidth == 8 && *sfp.toUint64() == 0:
continue
}
}
}
dfp := dst.offset(fi.field)
fi.merge(dfp, sfp)
}
// TODO: Make this faster?
out := dst.asPointerTo(mi.typ).Elem()
in := src.asPointerTo(mi.typ).Elem()
if emIn, err := extendable(in.Addr().Interface()); err == nil {
emOut, _ := extendable(out.Addr().Interface())
mIn, muIn := emIn.extensionsRead()
if mIn != nil {
mOut := emOut.extensionsWrite()
muIn.Lock()
mergeExtension(mOut, mIn)
muIn.Unlock()
}
}
if mi.unrecognized.IsValid() {
if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 {
*dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...)
}
}
}
func (mi *mergeInfo) computeMergeInfo() {
mi.lock.Lock()
defer mi.lock.Unlock()
if mi.initialized != 0 {
return
}
t := mi.typ
n := t.NumField()
props := GetProperties(t)
for i := 0; i < n; i++ {
f := t.Field(i)
if strings.HasPrefix(f.Name, "XXX_") {
continue
}
mfi := mergeFieldInfo{field: toField(&f)}
tf := f.Type
// As an optimization, we can avoid the merge function call cost
// if we know for sure that the source will have no effect
// by checking if it is the zero value.
if unsafeAllowed {
switch tf.Kind() {
case reflect.Ptr, reflect.Slice, reflect.String:
// As a special case, we assume slices and strings are pointers
// since we know that the first field in the SliceSlice or
// StringHeader is a data pointer.
mfi.isPointer = true
case reflect.Bool:
mfi.basicWidth = 1
case reflect.Int32, reflect.Uint32, reflect.Float32:
mfi.basicWidth = 4
case reflect.Int64, reflect.Uint64, reflect.Float64:
mfi.basicWidth = 8
}
}
// Unwrap tf to get at its most basic type.
var isPointer, isSlice bool
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
isSlice = true
tf = tf.Elem()
}
if tf.Kind() == reflect.Ptr {
isPointer = true
tf = tf.Elem()
}
if isPointer && isSlice && tf.Kind() != reflect.Struct {
panic("both pointer and slice for basic type in " + tf.Name())
}
switch tf.Kind() {
case reflect.Int32:
switch {
case isSlice: // E.g., []int32
mfi.merge = func(dst, src pointer) {
// NOTE: toInt32Slice is not defined (see pointer_reflect.go).
/*
sfsp := src.toInt32Slice()
if *sfsp != nil {
dfsp := dst.toInt32Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []int64{}
}
}
*/
sfs := src.getInt32Slice()
if sfs != nil {
dfs := dst.getInt32Slice()
dfs = append(dfs, sfs...)
if dfs == nil {
dfs = []int32{}
}
dst.setInt32Slice(dfs)
}
}
case isPointer: // E.g., *int32
mfi.merge = func(dst, src pointer) {
// NOTE: toInt32Ptr is not defined (see pointer_reflect.go).
/*
sfpp := src.toInt32Ptr()
if *sfpp != nil {
dfpp := dst.toInt32Ptr()
if *dfpp == nil {
*dfpp = Int32(**sfpp)
} else {
**dfpp = **sfpp
}
}
*/
sfp := src.getInt32Ptr()
if sfp != nil {
dfp := dst.getInt32Ptr()
if dfp == nil {
dst.setInt32Ptr(*sfp)
} else {
*dfp = *sfp
}
}
}
default: // E.g., int32
mfi.merge = func(dst, src pointer) {
if v := *src.toInt32(); v != 0 {
*dst.toInt32() = v
}
}
}
case reflect.Int64:
switch {
case isSlice: // E.g., []int64
mfi.merge = func(dst, src pointer) {
sfsp := src.toInt64Slice()
if *sfsp != nil {
dfsp := dst.toInt64Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []int64{}
}
}
}
case isPointer: // E.g., *int64
mfi.merge = func(dst, src pointer) {
sfpp := src.toInt64Ptr()
if *sfpp != nil {
dfpp := dst.toInt64Ptr()
if *dfpp == nil {
*dfpp = Int64(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., int64
mfi.merge = func(dst, src pointer) {
if v := *src.toInt64(); v != 0 {
*dst.toInt64() = v
}
}
}
case reflect.Uint32:
switch {
case isSlice: // E.g., []uint32
mfi.merge = func(dst, src pointer) {
sfsp := src.toUint32Slice()
if *sfsp != nil {
dfsp := dst.toUint32Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []uint32{}
}
}
}
case isPointer: // E.g., *uint32
mfi.merge = func(dst, src pointer) {
sfpp := src.toUint32Ptr()
if *sfpp != nil {
dfpp := dst.toUint32Ptr()
if *dfpp == nil {
*dfpp = Uint32(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., uint32
mfi.merge = func(dst, src pointer) {
if v := *src.toUint32(); v != 0 {
*dst.toUint32() = v
}
}
}
case reflect.Uint64:
switch {
case isSlice: // E.g., []uint64
mfi.merge = func(dst, src pointer) {
sfsp := src.toUint64Slice()
if *sfsp != nil {
dfsp := dst.toUint64Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []uint64{}
}
}
}
case isPointer: // E.g., *uint64
mfi.merge = func(dst, src pointer) {
sfpp := src.toUint64Ptr()
if *sfpp != nil {
dfpp := dst.toUint64Ptr()
if *dfpp == nil {
*dfpp = Uint64(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., uint64
mfi.merge = func(dst, src pointer) {
if v := *src.toUint64(); v != 0 {
*dst.toUint64() = v
}
}
}
case reflect.Float32:
switch {
case isSlice: // E.g., []float32
mfi.merge = func(dst, src pointer) {
sfsp := src.toFloat32Slice()
if *sfsp != nil {
dfsp := dst.toFloat32Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []float32{}
}
}
}
case isPointer: // E.g., *float32
mfi.merge = func(dst, src pointer) {
sfpp := src.toFloat32Ptr()
if *sfpp != nil {
dfpp := dst.toFloat32Ptr()
if *dfpp == nil {
*dfpp = Float32(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., float32
mfi.merge = func(dst, src pointer) {
if v := *src.toFloat32(); v != 0 {
*dst.toFloat32() = v
}
}
}
case reflect.Float64:
switch {
case isSlice: // E.g., []float64
mfi.merge = func(dst, src pointer) {
sfsp := src.toFloat64Slice()
if *sfsp != nil {
dfsp := dst.toFloat64Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []float64{}
}
}
}
case isPointer: // E.g., *float64
mfi.merge = func(dst, src pointer) {
sfpp := src.toFloat64Ptr()
if *sfpp != nil {
dfpp := dst.toFloat64Ptr()
if *dfpp == nil {
*dfpp = Float64(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., float64
mfi.merge = func(dst, src pointer) {
if v := *src.toFloat64(); v != 0 {
*dst.toFloat64() = v
}
}
}
case reflect.Bool:
switch {
case isSlice: // E.g., []bool
mfi.merge = func(dst, src pointer) {
sfsp := src.toBoolSlice()
if *sfsp != nil {
dfsp := dst.toBoolSlice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []bool{}
}
}
}
case isPointer: // E.g., *bool
mfi.merge = func(dst, src pointer) {
sfpp := src.toBoolPtr()
if *sfpp != nil {
dfpp := dst.toBoolPtr()
if *dfpp == nil {
*dfpp = Bool(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., bool
mfi.merge = func(dst, src pointer) {
if v := *src.toBool(); v {
*dst.toBool() = v
}
}
}
case reflect.String:
switch {
case isSlice: // E.g., []string
mfi.merge = func(dst, src pointer) {
sfsp := src.toStringSlice()
if *sfsp != nil {
dfsp := dst.toStringSlice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []string{}
}
}
}
case isPointer: // E.g., *string
mfi.merge = func(dst, src pointer) {
sfpp := src.toStringPtr()
if *sfpp != nil {
dfpp := dst.toStringPtr()
if *dfpp == nil {
*dfpp = String(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., string
mfi.merge = func(dst, src pointer) {
if v := *src.toString(); v != "" {
*dst.toString() = v
}
}
}
case reflect.Slice:
isProto3 := props.Prop[i].proto3
switch {
case isPointer:
panic("bad pointer in byte slice case in " + tf.Name())
case tf.Elem().Kind() != reflect.Uint8:
panic("bad element kind in byte slice case in " + tf.Name())
case isSlice: // E.g., [][]byte
mfi.merge = func(dst, src pointer) {
sbsp := src.toBytesSlice()
if *sbsp != nil {
dbsp := dst.toBytesSlice()
for _, sb := range *sbsp {
if sb == nil {
*dbsp = append(*dbsp, nil)
} else {
*dbsp = append(*dbsp, append([]byte{}, sb...))
}
}
if *dbsp == nil {
*dbsp = [][]byte{}
}
}
}
default: // E.g., []byte
mfi.merge = func(dst, src pointer) {
sbp := src.toBytes()
if *sbp != nil {
dbp := dst.toBytes()
if !isProto3 || len(*sbp) > 0 {
*dbp = append([]byte{}, *sbp...)
}
}
}
}
case reflect.Struct:
switch {
case !isPointer:
mergeInfo := getMergeInfo(tf)
mfi.merge = func(dst, src pointer) {
mergeInfo.merge(dst, src)
}
case isSlice: // E.g., []*pb.T
mergeInfo := getMergeInfo(tf)
mfi.merge = func(dst, src pointer) {
sps := src.getPointerSlice()
if sps != nil {
dps := dst.getPointerSlice()
for _, sp := range sps {
var dp pointer
if !sp.isNil() {
dp = valToPointer(reflect.New(tf))
mergeInfo.merge(dp, sp)
}
dps = append(dps, dp)
}
if dps == nil {
dps = []pointer{}
}
dst.setPointerSlice(dps)
}
}
default: // E.g., *pb.T
mergeInfo := getMergeInfo(tf)
mfi.merge = func(dst, src pointer) {
sp := src.getPointer()
if !sp.isNil() {
dp := dst.getPointer()
if dp.isNil() {
dp = valToPointer(reflect.New(tf))
dst.setPointer(dp)
}
mergeInfo.merge(dp, sp)
}
}
}
case reflect.Map:
switch {
case isPointer || isSlice:
panic("bad pointer or slice in map case in " + tf.Name())
default: // E.g., map[K]V
mfi.merge = func(dst, src pointer) {
sm := src.asPointerTo(tf).Elem()
if sm.Len() == 0 {
return
}
dm := dst.asPointerTo(tf).Elem()
if dm.IsNil() {
dm.Set(reflect.MakeMap(tf))
}
switch tf.Elem().Kind() {
case reflect.Ptr: // Proto struct (e.g., *T)
for _, key := range sm.MapKeys() {
val := sm.MapIndex(key)
val = reflect.ValueOf(Clone(val.Interface().(Message)))
dm.SetMapIndex(key, val)
}
case reflect.Slice: // E.g. Bytes type (e.g., []byte)
for _, key := range sm.MapKeys() {
val := sm.MapIndex(key)
val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
dm.SetMapIndex(key, val)
}
default: // Basic type (e.g., string)
for _, key := range sm.MapKeys() {
val := sm.MapIndex(key)
dm.SetMapIndex(key, val)
}
}
}
}
case reflect.Interface:
// Must be oneof field.
switch {
case isPointer || isSlice:
panic("bad pointer or slice in interface case in " + tf.Name())
default: // E.g., interface{}
// TODO: Make this faster?
mfi.merge = func(dst, src pointer) {
su := src.asPointerTo(tf).Elem()
if !su.IsNil() {
du := dst.asPointerTo(tf).Elem()
typ := su.Elem().Type()
if du.IsNil() || du.Elem().Type() != typ {
du.Set(reflect.New(typ.Elem())) // Initialize interface if empty
}
sv := su.Elem().Elem().Field(0)
if sv.Kind() == reflect.Ptr && sv.IsNil() {
return
}
dv := du.Elem().Elem().Field(0)
if dv.Kind() == reflect.Ptr && dv.IsNil() {
dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty
}
switch sv.Type().Kind() {
case reflect.Ptr: // Proto struct (e.g., *T)
Merge(dv.Interface().(Message), sv.Interface().(Message))
case reflect.Slice: // E.g. Bytes type (e.g., []byte)
dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...)))
default: // Basic type (e.g., string)
dv.Set(sv)
}
}
}
}
default:
panic(fmt.Sprintf("merger not found for type:%s", tf))
}
mi.fields = append(mi.fields, mfi)
}
mi.unrecognized = invalidField
if f, ok := t.FieldByName("XXX_unrecognized"); ok {
if f.Type != reflect.TypeOf([]byte{}) {
panic("expected XXX_unrecognized to be of type []byte")
}
mi.unrecognized = toField(&f)
}
atomic.StoreInt32(&mi.initialized, 1)
}

2048
vendor/github.com/gogo/protobuf/proto/table_unmarshal.go generated vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,385 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2018, 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 proto
import (
"io"
"reflect"
)
func makeUnmarshalMessage(sub *unmarshalInfo, name string) unmarshaler {
return func(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return nil, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
// First read the message field to see if something is there.
// The semantics of multiple submessages are weird. Instead of
// the last one winning (as it is for all other fields), multiple
// submessages are merged.
v := f // gogo: changed from v := f.getPointer()
if v.isNil() {
v = valToPointer(reflect.New(sub.typ))
f.setPointer(v)
}
err := sub.unmarshal(v, b[:x])
if err != nil {
if r, ok := err.(*RequiredNotSetError); ok {
r.field = name + "." + r.field
} else {
return nil, err
}
}
return b[x:], err
}
}
func makeUnmarshalMessageSlice(sub *unmarshalInfo, name string) unmarshaler {
return func(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return nil, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
v := valToPointer(reflect.New(sub.typ))
err := sub.unmarshal(v, b[:x])
if err != nil {
if r, ok := err.(*RequiredNotSetError); ok {
r.field = name + "." + r.field
} else {
return nil, err
}
}
f.appendRef(v, sub.typ) // gogo: changed from f.appendPointer(v)
return b[x:], err
}
}
func makeUnmarshalCustomPtr(sub *unmarshalInfo, name string) unmarshaler {
return func(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return nil, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem()
s.Set(reflect.New(sub.typ))
m := s.Interface().(custom)
if err := m.Unmarshal(b[:x]); err != nil {
return nil, err
}
return b[x:], nil
}
}
func makeUnmarshalCustomSlice(sub *unmarshalInfo, name string) unmarshaler {
return func(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return nil, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
m := reflect.New(sub.typ)
c := m.Interface().(custom)
if err := c.Unmarshal(b[:x]); err != nil {
return nil, err
}
v := valToPointer(m)
f.appendRef(v, sub.typ)
return b[x:], nil
}
}
func makeUnmarshalCustom(sub *unmarshalInfo, name string) unmarshaler {
return func(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return nil, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
m := f.asPointerTo(sub.typ).Interface().(custom)
if err := m.Unmarshal(b[:x]); err != nil {
return nil, err
}
return b[x:], nil
}
}
func makeUnmarshalTime(sub *unmarshalInfo, name string) unmarshaler {
return func(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return nil, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
m := &timestamp{}
if err := Unmarshal(b[:x], m); err != nil {
return nil, err
}
t, err := timestampFromProto(m)
if err != nil {
return nil, err
}
s := f.asPointerTo(sub.typ).Elem()
s.Set(reflect.ValueOf(t))
return b[x:], nil
}
}
func makeUnmarshalTimePtr(sub *unmarshalInfo, name string) unmarshaler {
return func(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return nil, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
m := &timestamp{}
if err := Unmarshal(b[:x], m); err != nil {
return nil, err
}
t, err := timestampFromProto(m)
if err != nil {
return nil, err
}
s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem()
s.Set(reflect.ValueOf(&t))
return b[x:], nil
}
}
func makeUnmarshalTimePtrSlice(sub *unmarshalInfo, name string) unmarshaler {
return func(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return nil, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
m := &timestamp{}
if err := Unmarshal(b[:x], m); err != nil {
return nil, err
}
t, err := timestampFromProto(m)
if err != nil {
return nil, err
}
slice := f.getSlice(reflect.PtrTo(sub.typ))
newSlice := reflect.Append(slice, reflect.ValueOf(&t))
slice.Set(newSlice)
return b[x:], nil
}
}
func makeUnmarshalTimeSlice(sub *unmarshalInfo, name string) unmarshaler {
return func(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return nil, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
m := &timestamp{}
if err := Unmarshal(b[:x], m); err != nil {
return nil, err
}
t, err := timestampFromProto(m)
if err != nil {
return nil, err
}
slice := f.getSlice(sub.typ)
newSlice := reflect.Append(slice, reflect.ValueOf(t))
slice.Set(newSlice)
return b[x:], nil
}
}
func makeUnmarshalDurationPtr(sub *unmarshalInfo, name string) unmarshaler {
return func(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return nil, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
m := &duration{}
if err := Unmarshal(b[:x], m); err != nil {
return nil, err
}
d, err := durationFromProto(m)
if err != nil {
return nil, err
}
s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem()
s.Set(reflect.ValueOf(&d))
return b[x:], nil
}
}
func makeUnmarshalDuration(sub *unmarshalInfo, name string) unmarshaler {
return func(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return nil, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
m := &duration{}
if err := Unmarshal(b[:x], m); err != nil {
return nil, err
}
d, err := durationFromProto(m)
if err != nil {
return nil, err
}
s := f.asPointerTo(sub.typ).Elem()
s.Set(reflect.ValueOf(d))
return b[x:], nil
}
}
func makeUnmarshalDurationPtrSlice(sub *unmarshalInfo, name string) unmarshaler {
return func(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return nil, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
m := &duration{}
if err := Unmarshal(b[:x], m); err != nil {
return nil, err
}
d, err := durationFromProto(m)
if err != nil {
return nil, err
}
slice := f.getSlice(reflect.PtrTo(sub.typ))
newSlice := reflect.Append(slice, reflect.ValueOf(&d))
slice.Set(newSlice)
return b[x:], nil
}
}
func makeUnmarshalDurationSlice(sub *unmarshalInfo, name string) unmarshaler {
return func(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return nil, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
m := &duration{}
if err := Unmarshal(b[:x], m); err != nil {
return nil, err
}
d, err := durationFromProto(m)
if err != nil {
return nil, err
}
slice := f.getSlice(sub.typ)
newSlice := reflect.Append(slice, reflect.ValueOf(d))
slice.Set(newSlice)
return b[x:], nil
}
}

View file

@ -33,5 +33,5 @@ all: regenerate
regenerate:
go install github.com/gogo/protobuf/protoc-min-version
protoc-min-version --version="3.0.0" --gogo_out=. test.proto
protoc-min-version --version="3.0.0" --gogo_out=paths=source_relative:. test.proto

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