diff --git a/go/src/themaru/Gopkg.lock b/go/src/themaru/Gopkg.lock new file mode 100644 index 0000000..d408aab --- /dev/null +++ b/go/src/themaru/Gopkg.lock @@ -0,0 +1,113 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + digest = "1:9d957ea60a89df67d3f51eee85812b90e1acb47227977d48cd4c3dce204f3cae" + name = "github.com/gin-contrib/multitemplate" + packages = ["."] + pruneopts = "UT" + revision = "f9896279eead500934dc33f97657bf039781c9d3" + +[[projects]] + branch = "master" + digest = "1:a4b5a6b32f33323c7850fae4ec085a0fbac3be93c057b6b8cef5bcabe24645ac" + name = "github.com/gin-contrib/sse" + packages = ["."] + pruneopts = "UT" + revision = "5545eab6dad3bbbd6c5ae9186383c2a9d23c0dae" + +[[projects]] + digest = "1:d8bd2a337f6ff2188e08f72c614f2f3f0fd48e6a7b37a071b197e427d77d3a47" + name = "github.com/gin-gonic/gin" + packages = [ + ".", + "binding", + "internal/json", + "render", + ] + pruneopts = "UT" + revision = "b75d67cd51eb53c3c3a2fc406524c940021ffbda" + version = "v1.4.0" + +[[projects]] + digest = "1:318f1c959a8a740366fce4b1e1eb2fd914036b4af58fbd0a003349b305f118ad" + name = "github.com/golang/protobuf" + packages = ["proto"] + pruneopts = "UT" + revision = "c823c79ea1570fb5ff454033735a8e68575d1d0f" + version = "v1.3.0" + +[[projects]] + digest = "1:f5a2051c55d05548d2d4fd23d244027b59fbd943217df8aa3b5e170ac2fd6e1b" + name = "github.com/json-iterator/go" + packages = ["."] + pruneopts = "UT" + revision = "0ff49de124c6f76f8494e194af75bde0f1a49a29" + version = "v1.1.6" + +[[projects]] + digest = "1:e150b5fafbd7607e2d638e4e5cf43aa4100124e5593385147b0a74e2733d8b0d" + name = "github.com/mattn/go-isatty" + packages = ["."] + pruneopts = "UT" + revision = "c2a7a6ca930a4cd0bc33a3f298eb71960732a3a7" + version = "v0.0.7" + +[[projects]] + digest = "1:33422d238f147d247752996a26574ac48dcf472976eda7f5134015f06bf16563" + name = "github.com/modern-go/concurrent" + packages = ["."] + pruneopts = "UT" + revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + version = "1.0.3" + +[[projects]] + digest = "1:e32bdbdb7c377a07a9a46378290059822efdce5c8d96fe71940d87cb4f918855" + name = "github.com/modern-go/reflect2" + packages = ["."] + pruneopts = "UT" + revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd" + version = "1.0.1" + +[[projects]] + digest = "1:d0072748c62defde1ad99dde77f6ffce492a0e5aea9204077e497c7edfb86653" + name = "github.com/ugorji/go" + packages = ["codec"] + pruneopts = "UT" + revision = "2adff0894ba3bc2eeb9f9aea45fefd49802e1a13" + version = "v1.1.4" + +[[projects]] + branch = "master" + digest = "1:9ca267f99487ef450fff0c2a49eaf0788d9ff3562bbaeff19f564d380f84bc6d" + name = "golang.org/x/sys" + packages = ["unix"] + pruneopts = "UT" + revision = "791d8a0f4d093bd8fe272dea2cd28991154796fb" + +[[projects]] + digest = "1:cbc72c4c4886a918d6ab4b95e347ffe259846260f99ebdd8a198c2331cf2b2e9" + name = "gopkg.in/go-playground/validator.v8" + packages = ["."] + pruneopts = "UT" + revision = "5f1438d3fca68893a817e4a66806cea46a9e4ebf" + version = "v8.18.2" + +[[projects]] + digest = "1:4d2e5a73dc1500038e504a8d78b986630e3626dc027bc030ba5c75da257cdb96" + name = "gopkg.in/yaml.v2" + packages = ["."] + pruneopts = "UT" + revision = "51d6538a90f86fe93ac480b35f37b2be17fef232" + version = "v2.2.2" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + input-imports = [ + "github.com/gin-contrib/multitemplate", + "github.com/gin-gonic/gin", + ] + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/go/src/themaru/Gopkg.toml b/go/src/themaru/Gopkg.toml new file mode 100644 index 0000000..f8ab90c --- /dev/null +++ b/go/src/themaru/Gopkg.toml @@ -0,0 +1,38 @@ +# Gopkg.toml example +# +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# 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 = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + branch = "master" + name = "github.com/gin-contrib/multitemplate" + +[[constraint]] + name = "github.com/gin-gonic/gin" + version = "1.4.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/go/src/themaru/build.sh b/go/src/themaru/build.sh new file mode 100755 index 0000000..d171cce --- /dev/null +++ b/go/src/themaru/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +GOARCH=arm go build -o webserv -ldflags="-s -w" . && ./upx --ultra-brute webserv diff --git a/go/src/themaru/env.go b/go/src/themaru/env.go new file mode 100644 index 0000000..60f0c78 --- /dev/null +++ b/go/src/themaru/env.go @@ -0,0 +1,74 @@ +package main + +import ( + "bytes" + "fmt" + "os" + "regexp" +) + +func getEnv(blockn int) (map[string]string, error) { + m := make(map[string]string) + + f, err := os.Open("/dev/mmcblk3boot1") + if err != nil { + return m, err + } + defer f.Close() + + b := make([]byte, 512) + f.ReadAt(b, int64(blockn)*512) + + n := bytes.IndexByte(b, 0) + s := string(b[:n]) + + r := regexp.MustCompile(`(.+?)=(.+)\n`) + ss := r.FindAllStringSubmatch(s, -1) + for _, v := range ss { + if len(v) != 3 { + continue + } + + m[v[1]] = v[2] + } + + return m, nil +} + +func setEnv(blockn int, env map[string]string) error { + err := disableReadOnly() + if err != nil { + return err + } + + f, err := os.OpenFile("/dev/mmcblk3boot1", os.O_RDWR, 0666) + if err != nil { + return err + } + defer f.Close() + + var s string + for k, v := range env { + s += fmt.Sprintf("%s=%s\n", k, v) + } + s += "\x00" + + _, err = f.WriteAt([]byte(s), int64(blockn)*512) + if err != nil { + return err + } + + return nil +} + +func disableReadOnly() error { + f, err := os.OpenFile("/sys/block/mmcblk3boot1/force_ro", os.O_RDWR, 0666) + if err != nil { + return err + } + defer f.Close() + + _, err = f.WriteString("0\n") + + return err +} diff --git a/go/src/themaru/http.go b/go/src/themaru/http.go new file mode 100644 index 0000000..8d08871 --- /dev/null +++ b/go/src/themaru/http.go @@ -0,0 +1,183 @@ +package main + +import ( + "html/template" + "net/http" + "os" + "sync" + + "github.com/gin-contrib/multitemplate" + "github.com/gin-gonic/gin" +) + +var mu sync.Mutex + +var indexPage = template.Must(template.New("index.html").Parse(` + + + System Configuration + + + +

{{.Device}} Configuration

+
+

System Version: {{.Version}}

+
+
+

Setting IP Address

+
+
+ + + +
+
+

Updating System

+
+
+ + +
+
+

Updating Application

+
+
+ + +
+
+

Restore System Image

+
+
+ +
+
+ + +`)) + +var rebootPage = template.Must(template.New("reboot.html").Parse(` + + + OK + + +

{{.Message}}

+
+ +
+ + +`)) + +func runHttp() { + gin.SetMode(gin.ReleaseMode) + + g := gin.Default() + + r := multitemplate.NewRenderer() + r.Add("index.html", indexPage) + r.Add("reboot.html", rebootPage) + + g.HTMLRender = r + + g.GET("/", renderIndex) + + g.POST("/address", handleAddress) + g.POST("/system", handleSystem) + g.POST("/application", handleApplication) + + g.GET("/reboot", handleReboot) + g.GET("/restore", handleRestore) + + g.Run(":8988") +} + +func handleAddress(c *gin.Context) { + mu.Lock() + defer mu.Unlock() + + addr := c.PostForm("address") + addr2 := c.PostForm("address2") + + if err := setIpAddress(addr, addr2); err != nil { + c.String(http.StatusBadRequest, "address: setIpAddress: %s", err.Error()) + return + } + + c.HTML(http.StatusOK, "reboot.html", gin.H{"Message": "IP address is updated."}) +} + +func handleSystem(c *gin.Context) { + mu.Lock() + defer mu.Unlock() + + if err := saveFormFile(c, "image", "/tmp/system.zip"); err != nil { + c.String(http.StatusBadRequest, "system: saveFormFile: %s", err.Error()) + return + } + + if err := updateSystem(); err != nil { + c.String(http.StatusBadRequest, "system: updateSystem: %s", err.Error()) + return + } + + c.HTML(http.StatusOK, "reboot.html", gin.H{"Message": "System is updated."}) +} + +func handleApplication(c *gin.Context) { + mu.Lock() + defer mu.Unlock() + + if err := saveFormFile(c, "image", "/tmp/application.zip"); err != nil { + c.String(http.StatusBadRequest, "application: saveFormFile: %s", err.Error()) + return + } + + if err := updateApp(); err != nil { + c.String(http.StatusBadRequest, "application: updateApplication: %s", err.Error()) + return + } + + c.HTML(http.StatusOK, "reboot.html", gin.H{"Message": "Application is updated."}) +} + +func handleReboot(c *gin.Context) { + reboot() + + c.String(http.StatusOK, "OK") +} + +func handleRestore(c *gin.Context) { + mu.Lock() + defer mu.Unlock() + + restore() + + c.HTML(http.StatusOK, "reboot.html", gin.H{"Message": "Restoration is done."}) +} + +func renderIndex(c *gin.Context) { + device := "System" + if len(os.Args) > 1 { + device = os.Args[1] + } + + c.HTML(http.StatusOK, "index.html", gin.H{ + "Device": device, + "IP": getIpAddress(), + "IP2": getIpAddress2(), + "Version": getVersion(), + }) +} + +func saveFormFile(c *gin.Context, name string, dst string) error { + file, err := c.FormFile(name) + if err != nil { + return err + } + + return c.SaveUploadedFile(file, dst) +} diff --git a/go/src/themaru/ip.go b/go/src/themaru/ip.go new file mode 100644 index 0000000..a3f09bd --- /dev/null +++ b/go/src/themaru/ip.go @@ -0,0 +1,77 @@ +package main + +import ( + "errors" + "regexp" + "strconv" +) + +func getIpAddress() string { + env, err := getEnv(0) + if err != nil { + return "" + } + + return env["ipaddr"] +} + +func getIpAddress2() string { + env, err := getEnv(0) + if err != nil { + return "" + } + + return env["ipaddr2"] +} + +func setIpAddress(address, address2 string) error { + address = extractIpAddress(address) + if address == "" { + return errors.New("invalid IP address") + } + + address2 = extractIpAddress(address2) + if address2 == "" { + return errors.New("invalid IP address2") + } + + env, err := getEnv(0) + if err != nil { + return err + } + + env["ipaddr"] = address + env["ipaddr2"] = address2 + + err = setEnv(0, env) + if err != nil { + return err + } + + return nil +} + +func extractIpAddress(address string) string { + r := regexp.MustCompile(`([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)`) + s := r.FindStringSubmatch(address) + if len(s) != 5 { + return "" + } + + for i, v := range s { + if i == 0 { + continue + } + + u, err := strconv.ParseUint(v, 10, 8) + if err != nil { + return "" + } + + if u > 255 { + return "" + } + } + + return s[0] +} diff --git a/go/src/themaru/main.go b/go/src/themaru/main.go new file mode 100644 index 0000000..241ff1a --- /dev/null +++ b/go/src/themaru/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + runHttp() +} diff --git a/go/src/themaru/system.go b/go/src/themaru/system.go new file mode 100644 index 0000000..abdc75c --- /dev/null +++ b/go/src/themaru/system.go @@ -0,0 +1,114 @@ +package main + +import ( + "io/ioutil" + "os/exec" +) + +func getVersion() string { + env, err := getEnv(1) + if err != nil { + return "" + } + + version, exist := env["falinux_version"] + if !exist { + return "" + } + + return version +} + +func updateSystem() error { + env, err := getEnv(1) + if err != nil { + return err + } + + bootpart := env["bootpart"] + + var dir string + var partname string + switch bootpart { + case "1": + dir = "/boot1" + partname = "/dev/mmcblk3p2" + env["bootpart"] = "2" + case "2": + dir = "/boot0" + partname = "/dev/mmcblk3p1" + env["bootpart"] = "1" + default: + dir = "/boot0" + partname = "/dev/mmcblk3p1" + env["bootpart"] = "1" + } + + if !partitionIsExists() { + makePartition() + } else { + formatPartition(partname) + } + + if err := exec.Command("mount", "-o", "rw", dir).Run(); err != nil { + return err + } + defer exec.Command("umount", dir).Run() + + if err := exec.Command("unzip", "-o", "/tmp/system.zip", "-d", dir).Run(); err != nil { + return err + } + + exec.Command("sync").Run() + + if ver, err := ioutil.ReadFile(dir + "/version"); err != nil { + env["falinux_version"] = "" + } else { + env["falinux_version"] = string(ver) + } + + return setEnv(1, env) +} + +func updateApp() error { + const cmdline = `\ + rm -rf /app/bin.old /app/bin.new; \ + mkdir /app/bin.new && \ + unzip -o /tmp/application.zip -d /app/bin.new && \ + sync && \ + mv /app/bin /app/bin.old; \ + mv /app/bin.new /app/bin; \ + sync` + + return exec.Command("/bin/sh", "-c", cmdline).Run() +} + +func partitionIsExists() bool { + err := exec.Command("test", "-e", "/dev/mmcblk3p1", "-a", "-e", "/dev/mmcblk3p2").Run() + return err == nil +} + +func makePartition() { + exec.Command("umount", "/app").Run() + exec.Command("/bin/sh", "-c", "/root/.falinux/mk-mmc-part.sh").Run() +} + +func formatPartition(partname string) { + exec.Command("mkfs.fat", partname).Run() +} + +func reboot() { + exec.Command("killall", "-19", "watchdog").Run() + exec.Command("reboot").Run() +} + +func restore() { + m := make(map[string]string) + + setEnv(0, m) + setEnv(1, m) + setEnv(2, m) + setEnv(3, m) + + exec.Command("/bin/sh", "-c", "/root/.falinux/mk-mmc-part.sh").Run() +} diff --git a/go/src/themaru/upx b/go/src/themaru/upx new file mode 100755 index 0000000000000000000000000000000000000000..1c53e841ff1ca756edab1220104ecf98c65682b3 GIT binary patch literal 422160 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 $oZM0 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 pBEc7#3+7?N_RO|jxK*X;SQQ$;#=yJ>y0Aw6 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%0D-kie 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

?MWka=vH64j33WIF;Tk8@48YZ8BqA@*Mp&M zZi~>hc*qeCyOIzJc2X%Gyll?sT?}8j9?QN0O};GgQ#|gT$y*}}VKJ^ArWjm^%LLDI zN9Aesaw(pto+P-jRSxih2tCbMyWAZ|()dmd_WUtgX(NQ7OY<2+R$}|Ltn=mEN_X>z)K=J9Xmt!{>Zae=Lt()19DsNrz93$n2X&8=tFydk43ZoR{q)yCr-C%rqIzWL=G8Ff z8q0Lw!JZtQ5XrKH{v{GcGVAxlYEO4jUon-zyM}3GF1mOd{#_K84oYp1sV?VH4}(01YGxyx7glxmb6+0y_4Oou z6VcRq#TgNMFS(T?k~23eO|s#fR0gv1eTgXXSq8(GA5(+!0J)stA;jtKgEduu4qT)I z&^59US4zUYDU*L#5j1Pps*%~8FYxy*DQjG3#ot~Bf}XcsU95IediAg@}d z!|ZOvBlk(!X3iH)FR?aTGdnxKZYqZ!IqW72wmyxp{Ld1y>>uMD(EHX zJCwj!KB)rJV5bz)UB3Jm8L}O_NtnL5*Y4g�};W5!pN~ZO>+ev7UAjPgirRIdfh+ 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 /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + go get -u github.com/campoy/embedmd; \ + fi + +embedmd: + embedmd -d *.md + +.PHONY: lint +lint: + @hash golint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + go get -u golang.org/x/lint/golint; \ + fi + for PKG in $(PACKAGES); do golint -set_exit_status $$PKG || exit 1; done; + +.PHONY: misspell-check +misspell-check: + @hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + go get -u github.com/client9/misspell/cmd/misspell; \ + fi + misspell -error $(GOFILES) + +.PHONY: misspell +misspell: + @hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + go get -u github.com/client9/misspell/cmd/misspell; \ + fi + misspell -w $(GOFILES) diff --git a/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/README.md b/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/README.md new file mode 100644 index 0000000..6c1d555 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/README.md @@ -0,0 +1,119 @@ +# Multitemplate + +[![Build Status](https://travis-ci.org/gin-contrib/multitemplate.svg)](https://travis-ci.org/gin-contrib/multitemplate) +[![codecov](https://codecov.io/gh/gin-contrib/multitemplate/branch/master/graph/badge.svg)](https://codecov.io/gh/gin-contrib/multitemplate) +[![Go Report Card](https://goreportcard.com/badge/github.com/gin-contrib/multitemplate)](https://goreportcard.com/report/github.com/gin-contrib/multitemplate) +[![GoDoc](https://godoc.org/github.com/gin-contrib/multitemplate?status.svg)](https://godoc.org/github.com/gin-contrib/multitemplate) + +This is a custom HTML render to support multi templates, ie. more than one `*template.Template`. + +## Usage + +### Start using it + +Download and install it: + +```sh +$ go get github.com/gin-contrib/multitemplate +``` + +Import it in your code: + +```go +import "github.com/gin-contrib/multitemplate" +``` + +### Simple example + +See [example/simple/example.go](example/simple/example.go) + +[embedmd]:# (example/simple/example.go go) +```go +package main + +import ( + "github.com/gin-contrib/multitemplate" + "github.com/gin-gonic/gin" +) + +func createMyRender() multitemplate.Renderer { + r := multitemplate.NewRenderer() + r.AddFromFiles("index", "templates/base.html", "templates/index.html") + r.AddFromFiles("article", "templates/base.html", "templates/index.html", "templates/article.html") + return r +} + +func main() { + router := gin.Default() + router.HTMLRender = createMyRender() + router.GET("/", func(c *gin.Context) { + c.HTML(200, "index", gin.H{ + "title": "Html5 Template Engine", + }) + }) + router.GET("/article", func(c *gin.Context) { + c.HTML(200, "article", gin.H{ + "title": "Html5 Article Engine", + }) + }) + router.Run(":8080") +} +``` + +### Advanced example + +[Approximating html/template Inheritance](https://elithrar.github.io/article/approximating-html-template-inheritance/) + +See [example/advanced/example.go](example/advanced/example.go) + +[embedmd]:# (example/advanced/example.go go) +```go +package main + +import ( + "path/filepath" + + "github.com/gin-contrib/multitemplate" + "github.com/gin-gonic/gin" +) + +func main() { + router := gin.Default() + router.HTMLRender = loadTemplates("./templates") + router.GET("/", func(c *gin.Context) { + c.HTML(200, "index.html", gin.H{ + "title": "Welcome!", + }) + }) + router.GET("/article", func(c *gin.Context) { + c.HTML(200, "article.html", gin.H{ + "title": "Html5 Article Engine", + }) + }) + + router.Run(":8080") +} + +func loadTemplates(templatesDir string) multitemplate.Renderer { + r := multitemplate.NewRenderer() + + layouts, err := filepath.Glob(templatesDir + "/layouts/*.html") + if err != nil { + panic(err.Error()) + } + + includes, err := filepath.Glob(templatesDir + "/includes/*.html") + if err != nil { + panic(err.Error()) + } + + // Generate our templates map from our layouts/ and includes/ directories + for _, include := range includes { + layoutCopy := make([]string, len(layouts)) + copy(layoutCopy, layouts) + files := append(layoutCopy, include) + r.AddFromFiles(filepath.Base(include), files...) + } + return r +} +``` diff --git a/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/dynamic.go b/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/dynamic.go new file mode 100644 index 0000000..8d56bad --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/dynamic.go @@ -0,0 +1,147 @@ +package multitemplate + +import ( + "fmt" + "html/template" + "path/filepath" + + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/render" +) + +// DynamicRender type +type DynamicRender map[string]*templateBuilder + +var ( + _ render.HTMLRender = DynamicRender{} + _ Renderer = DynamicRender{} +) + +// NewDynamic is the constructor for Dynamic templates +func NewDynamic() DynamicRender { + return make(DynamicRender) +} + +// NewRenderer allows create an agnostic multitemplate renderer +// depending on enabled gin mode +func NewRenderer() Renderer { + if gin.IsDebugging() { + return NewDynamic() + } + return New() +} + +// Type of dynamic builder +type builderType int + +// Types of dynamic builders +const ( + templateType builderType = iota + filesTemplateType + globTemplateType + stringTemplateType + stringFuncTemplateType + filesFuncTemplateType +) + +// Builder for dynamic templates +type templateBuilder struct { + buildType builderType + tmpl *template.Template + templateName string + files []string + glob string + templateString string + funcMap template.FuncMap + templateStrings []string +} + +func (tb templateBuilder) buildTemplate() *template.Template { + switch tb.buildType { + case templateType: + return tb.tmpl + case filesTemplateType: + return template.Must(template.ParseFiles(tb.files...)) + case globTemplateType: + return template.Must(template.ParseGlob(tb.glob)) + case stringTemplateType: + return template.Must(template.New(tb.templateName).Parse(tb.templateString)) + case stringFuncTemplateType: + tmpl := template.New(tb.templateName).Funcs(tb.funcMap) + for _, ts := range tb.templateStrings { + tmpl = template.Must(tmpl.Parse(ts)) + } + return tmpl + case filesFuncTemplateType: + return template.Must(template.New(tb.templateName).Funcs(tb.funcMap).ParseFiles(tb.files...)) + default: + panic("Invalid builder type for dynamic template") + } +} + +// Add new template +func (r DynamicRender) Add(name string, tmpl *template.Template) { + if tmpl == nil { + panic("template cannot be nil") + } + if len(name) == 0 { + panic("template name cannot be empty") + } + builder := &templateBuilder{templateName: name, tmpl: tmpl} + builder.buildType = templateType + r[name] = builder +} + +// AddFromFiles supply add template from files +func (r DynamicRender) AddFromFiles(name string, files ...string) *template.Template { + builder := &templateBuilder{templateName: name, files: files} + builder.buildType = filesTemplateType + r[name] = builder + return builder.buildTemplate() +} + +// AddFromGlob supply add template from global path +func (r DynamicRender) AddFromGlob(name, glob string) *template.Template { + builder := &templateBuilder{templateName: name, glob: glob} + builder.buildType = globTemplateType + r[name] = builder + return builder.buildTemplate() +} + +// AddFromString supply add template from strings +func (r DynamicRender) AddFromString(name, templateString string) *template.Template { + builder := &templateBuilder{templateName: name, templateString: templateString} + builder.buildType = stringTemplateType + r[name] = builder + return builder.buildTemplate() +} + +// AddFromStringsFuncs supply add template from strings +func (r DynamicRender) AddFromStringsFuncs(name string, funcMap template.FuncMap, templateStrings ...string) *template.Template { + builder := &templateBuilder{templateName: name, funcMap: funcMap, + templateStrings: templateStrings} + builder.buildType = stringFuncTemplateType + r[name] = builder + return builder.buildTemplate() +} + +// AddFromFilesFuncs supply add template from file callback func +func (r DynamicRender) AddFromFilesFuncs(name string, funcMap template.FuncMap, files ...string) *template.Template { + tname := filepath.Base(files[0]) + builder := &templateBuilder{templateName: tname, funcMap: funcMap, files: files} + builder.buildType = filesFuncTemplateType + r[name] = builder + return builder.buildTemplate() +} + +// Instance supply render string +func (r DynamicRender) Instance(name string, data interface{}) render.Render { + builder, ok := r[name] + if !ok { + panic(fmt.Sprintf("Dynamic template with name %s not found", name)) + } + return render.HTML{ + Template: builder.buildTemplate(), + Data: data, + } +} diff --git a/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/go.mod b/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/go.mod new file mode 100644 index 0000000..89fe1f6 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/go.mod @@ -0,0 +1,21 @@ +module github.com/gin-contrib/multitemplate + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7 // indirect + github.com/gin-gonic/gin v1.3.0 + github.com/golang/protobuf v1.2.0 // indirect + github.com/json-iterator/go v1.1.5 // indirect + github.com/mattn/go-isatty v0.0.4 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.2.2 + github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2 // indirect + golang.org/x/net v0.0.0-20181220203305-927f97764cc3 // indirect + golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect + golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb // indirect + gopkg.in/go-playground/assert.v1 v1.2.1 // indirect + gopkg.in/go-playground/validator.v8 v8.18.2 // indirect + gopkg.in/yaml.v2 v2.2.2 // indirect +) diff --git a/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/go.sum b/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/go.sum new file mode 100644 index 0000000..5ae9bd9 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/go.sum @@ -0,0 +1,36 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7 h1:AzN37oI0cOS+cougNAV9szl6CVoj2RYwzS3DpUQNtlY= +github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/gin-gonic/gin v1.3.0 h1:kCmZyPklC0gVdL728E6Aj20uYBJV93nj/TkwBTKhFbs= +github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE= +github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2 h1:EICbibRW4JNKMcY+LsWmuwob+CRS1BmdRdjphAm9mH4= +github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb h1:pf3XwC90UUdNPYWZdFjhGBE7DUFuK3Ct1zWmZ65QN30= +golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/multitemplate.go b/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/multitemplate.go new file mode 100644 index 0000000..0940aa8 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/multitemplate.go @@ -0,0 +1,85 @@ +package multitemplate + +import ( + "fmt" + "html/template" + "path/filepath" + + "github.com/gin-gonic/gin/render" +) + +// Render type +type Render map[string]*template.Template + +var ( + _ render.HTMLRender = Render{} + _ Renderer = Render{} +) + +// New instance +func New() Render { + return make(Render) +} + +// Add new template +func (r Render) Add(name string, tmpl *template.Template) { + if tmpl == nil { + panic("template can not be nil") + } + if len(name) == 0 { + panic("template name cannot be empty") + } + if _, ok := r[name]; ok { + panic(fmt.Sprintf("template %s already exists", name)) + } + r[name] = tmpl +} + +// AddFromFiles supply add template from files +func (r Render) AddFromFiles(name string, files ...string) *template.Template { + tmpl := template.Must(template.ParseFiles(files...)) + r.Add(name, tmpl) + return tmpl +} + +// AddFromGlob supply add template from global path +func (r Render) AddFromGlob(name, glob string) *template.Template { + tmpl := template.Must(template.ParseGlob(glob)) + r.Add(name, tmpl) + return tmpl +} + +// AddFromString supply add template from strings +func (r Render) AddFromString(name, templateString string) *template.Template { + tmpl := template.Must(template.New(name).Parse(templateString)) + r.Add(name, tmpl) + return tmpl +} + +// AddFromStringsFuncs supply add template from strings +func (r Render) AddFromStringsFuncs(name string, funcMap template.FuncMap, templateStrings ...string) *template.Template { + tmpl := template.New(name).Funcs(funcMap) + + for _, ts := range templateStrings { + tmpl = template.Must(tmpl.Parse(ts)) + } + + r.Add(name, tmpl) + return tmpl +} + +// AddFromFilesFuncs supply add template from file callback func +func (r Render) AddFromFilesFuncs(name string, funcMap template.FuncMap, files ...string) *template.Template { + tname := filepath.Base(files[0]) + tmpl := template.Must(template.New(tname).Funcs(funcMap).ParseFiles(files...)) + r.Add(name, tmpl) + return tmpl +} + +// Instance supply render string +func (r Render) Instance(name string, data interface{}) render.Render { + return render.HTML{ + Template: r[name], + Data: data, + } +} diff --git a/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/renderer.go b/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/renderer.go new file mode 100644 index 0000000..4e643e7 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-contrib/multitemplate/renderer.go @@ -0,0 +1,18 @@ +package multitemplate + +import "html/template" +import "github.com/gin-gonic/gin/render" + +// Renderer type is the Agnostic Renderer for multitemplates. +// When gin is in debug mode then all multitemplates works with +// hot reloading allowing you modify file templates and seeing changes instantly. +// Renderer should be created using multitemplate.NewRenderer() constructor. +type Renderer interface { + render.HTMLRender + Add(name string, tmpl *template.Template) + AddFromFiles(name string, files ...string) *template.Template + AddFromGlob(name, glob string) *template.Template + AddFromString(name, templateString string) *template.Template + AddFromStringsFuncs(name string, funcMap template.FuncMap, templateStrings ...string) *template.Template + AddFromFilesFuncs(name string, funcMap template.FuncMap, files ...string) *template.Template +} diff --git a/go/src/themaru/vendor/github.com/gin-contrib/sse/.travis.yml b/go/src/themaru/vendor/github.com/gin-contrib/sse/.travis.yml new file mode 100644 index 0000000..d0e8fcf --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-contrib/sse/.travis.yml @@ -0,0 +1,26 @@ +language: go +sudo: false +go: + - 1.8.x + - 1.9.x + - 1.10.x + - 1.11.x + - 1.12.x + - master + +git: + depth: 10 + +matrix: + fast_finish: true + include: + - go: 1.11.x + env: GO111MODULE=on + - go: 1.12.x + env: GO111MODULE=on + +script: + - go test -v -covermode=count -coverprofile=coverage.out + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/go/src/themaru/vendor/github.com/gin-contrib/sse/LICENSE b/go/src/themaru/vendor/github.com/gin-contrib/sse/LICENSE new file mode 100644 index 0000000..1ff7f37 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-contrib/sse/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Manuel Martínez-Almeida + +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. diff --git a/go/src/themaru/vendor/github.com/gin-contrib/sse/README.md b/go/src/themaru/vendor/github.com/gin-contrib/sse/README.md new file mode 100644 index 0000000..c9c49cf --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-contrib/sse/README.md @@ -0,0 +1,58 @@ +# Server-Sent Events + +[![GoDoc](https://godoc.org/github.com/gin-contrib/sse?status.svg)](https://godoc.org/github.com/gin-contrib/sse) +[![Build Status](https://travis-ci.org/gin-contrib/sse.svg)](https://travis-ci.org/gin-contrib/sse) +[![codecov](https://codecov.io/gh/gin-contrib/sse/branch/master/graph/badge.svg)](https://codecov.io/gh/gin-contrib/sse) +[![Go Report Card](https://goreportcard.com/badge/github.com/gin-contrib/sse)](https://goreportcard.com/report/github.com/gin-contrib/sse) + +Server-sent events (SSE) is a technology where a browser receives automatic updates from a server via HTTP connection. The Server-Sent Events EventSource API is [standardized as part of HTML5[1] by the W3C](http://www.w3.org/TR/2009/WD-eventsource-20091029/). + +- [Read this great SSE introduction by the HTML5Rocks guys](http://www.html5rocks.com/en/tutorials/eventsource/basics/) +- [Browser support](http://caniuse.com/#feat=eventsource) + +## Sample code + +```go +import "github.com/gin-contrib/sse" + +func httpHandler(w http.ResponseWriter, req *http.Request) { + // data can be a primitive like a string, an integer or a float + sse.Encode(w, sse.Event{ + Event: "message", + Data: "some data\nmore data", + }) + + // also a complex type, like a map, a struct or a slice + sse.Encode(w, sse.Event{ + Id: "124", + Event: "message", + Data: map[string]interface{}{ + "user": "manu", + "date": time.Now().Unix(), + "content": "hi!", + }, + }) +} +``` +``` +event: message +data: some data\\nmore data + +id: 124 +event: message +data: {"content":"hi!","date":1431540810,"user":"manu"} + +``` + +## Content-Type + +```go +fmt.Println(sse.ContentType) +``` +``` +text/event-stream +``` + +## Decoding support + +There is a client-side implementation of SSE coming soon. diff --git a/go/src/themaru/vendor/github.com/gin-contrib/sse/sse-decoder.go b/go/src/themaru/vendor/github.com/gin-contrib/sse/sse-decoder.go new file mode 100644 index 0000000..fd49b9c --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-contrib/sse/sse-decoder.go @@ -0,0 +1,116 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package sse + +import ( + "bytes" + "io" + "io/ioutil" +) + +type decoder struct { + events []Event +} + +func Decode(r io.Reader) ([]Event, error) { + var dec decoder + return dec.decode(r) +} + +func (d *decoder) dispatchEvent(event Event, data string) { + dataLength := len(data) + if dataLength > 0 { + //If the data buffer's last character is a U+000A LINE FEED (LF) character, then remove the last character from the data buffer. + data = data[:dataLength-1] + dataLength-- + } + if dataLength == 0 && event.Event == "" { + return + } + if event.Event == "" { + event.Event = "message" + } + event.Data = data + d.events = append(d.events, event) +} + +func (d *decoder) decode(r io.Reader) ([]Event, error) { + buf, err := ioutil.ReadAll(r) + if err != nil { + return nil, err + } + + var currentEvent Event + var dataBuffer *bytes.Buffer = new(bytes.Buffer) + // TODO (and unit tests) + // Lines must be separated by either a U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF) character pair, + // a single U+000A LINE FEED (LF) character, + // or a single U+000D CARRIAGE RETURN (CR) character. + lines := bytes.Split(buf, []byte{'\n'}) + for _, line := range lines { + if len(line) == 0 { + // If the line is empty (a blank line). Dispatch the event. + d.dispatchEvent(currentEvent, dataBuffer.String()) + + // reset current event and data buffer + currentEvent = Event{} + dataBuffer.Reset() + continue + } + if line[0] == byte(':') { + // If the line starts with a U+003A COLON character (:), ignore the line. + continue + } + + var field, value []byte + colonIndex := bytes.IndexRune(line, ':') + if colonIndex != -1 { + // If the line contains a U+003A COLON character character (:) + // Collect the characters on the line before the first U+003A COLON character (:), + // and let field be that string. + field = line[:colonIndex] + // Collect the characters on the line after the first U+003A COLON character (:), + // and let value be that string. + value = line[colonIndex+1:] + // If value starts with a single U+0020 SPACE character, remove it from value. + if len(value) > 0 && value[0] == ' ' { + value = value[1:] + } + } else { + // Otherwise, the string is not empty but does not contain a U+003A COLON character character (:) + // Use the whole line as the field name, and the empty string as the field value. + field = line + value = []byte{} + } + // The steps to process the field given a field name and a field value depend on the field name, + // as given in the following list. Field names must be compared literally, + // with no case folding performed. + switch string(field) { + case "event": + // Set the event name buffer to field value. + currentEvent.Event = string(value) + case "id": + // Set the event stream's last event ID to the field value. + currentEvent.Id = string(value) + case "retry": + // If the field value consists of only characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), + // then interpret the field value as an integer in base ten, and set the event stream's reconnection time to that integer. + // Otherwise, ignore the field. + currentEvent.Id = string(value) + case "data": + // Append the field value to the data buffer, + dataBuffer.Write(value) + // then append a single U+000A LINE FEED (LF) character to the data buffer. + dataBuffer.WriteString("\n") + default: + //Otherwise. The field is ignored. + continue + } + } + // Once the end of the file is reached, the user agent must dispatch the event one final time. + d.dispatchEvent(currentEvent, dataBuffer.String()) + + return d.events, nil +} diff --git a/go/src/themaru/vendor/github.com/gin-contrib/sse/sse-encoder.go b/go/src/themaru/vendor/github.com/gin-contrib/sse/sse-encoder.go new file mode 100644 index 0000000..f9c8087 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-contrib/sse/sse-encoder.go @@ -0,0 +1,110 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package sse + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "reflect" + "strconv" + "strings" +) + +// Server-Sent Events +// W3C Working Draft 29 October 2009 +// http://www.w3.org/TR/2009/WD-eventsource-20091029/ + +const ContentType = "text/event-stream" + +var contentType = []string{ContentType} +var noCache = []string{"no-cache"} + +var fieldReplacer = strings.NewReplacer( + "\n", "\\n", + "\r", "\\r") + +var dataReplacer = strings.NewReplacer( + "\n", "\ndata:", + "\r", "\\r") + +type Event struct { + Event string + Id string + Retry uint + Data interface{} +} + +func Encode(writer io.Writer, event Event) error { + w := checkWriter(writer) + writeId(w, event.Id) + writeEvent(w, event.Event) + writeRetry(w, event.Retry) + return writeData(w, event.Data) +} + +func writeId(w stringWriter, id string) { + if len(id) > 0 { + w.WriteString("id:") + fieldReplacer.WriteString(w, id) + w.WriteString("\n") + } +} + +func writeEvent(w stringWriter, event string) { + if len(event) > 0 { + w.WriteString("event:") + fieldReplacer.WriteString(w, event) + w.WriteString("\n") + } +} + +func writeRetry(w stringWriter, retry uint) { + if retry > 0 { + w.WriteString("retry:") + w.WriteString(strconv.FormatUint(uint64(retry), 10)) + w.WriteString("\n") + } +} + +func writeData(w stringWriter, data interface{}) error { + w.WriteString("data:") + switch kindOfData(data) { + case reflect.Struct, reflect.Slice, reflect.Map: + err := json.NewEncoder(w).Encode(data) + if err != nil { + return err + } + w.WriteString("\n") + default: + dataReplacer.WriteString(w, fmt.Sprint(data)) + w.WriteString("\n\n") + } + return nil +} + +func (r Event) Render(w http.ResponseWriter) error { + r.WriteContentType(w) + return Encode(w, r) +} + +func (r Event) WriteContentType(w http.ResponseWriter) { + header := w.Header() + header["Content-Type"] = contentType + + if _, exist := header["Cache-Control"]; !exist { + header["Cache-Control"] = noCache + } +} + +func kindOfData(data interface{}) reflect.Kind { + value := reflect.ValueOf(data) + valueType := value.Kind() + if valueType == reflect.Ptr { + valueType = value.Elem().Kind() + } + return valueType +} diff --git a/go/src/themaru/vendor/github.com/gin-contrib/sse/writer.go b/go/src/themaru/vendor/github.com/gin-contrib/sse/writer.go new file mode 100644 index 0000000..6f9806c --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-contrib/sse/writer.go @@ -0,0 +1,24 @@ +package sse + +import "io" + +type stringWriter interface { + io.Writer + WriteString(string) (int, error) +} + +type stringWrapper struct { + io.Writer +} + +func (w stringWrapper) WriteString(str string) (int, error) { + return w.Writer.Write([]byte(str)) +} + +func checkWriter(writer io.Writer) stringWriter { + if w, ok := writer.(stringWriter); ok { + return w + } else { + return stringWrapper{writer} + } +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/.gitignore b/go/src/themaru/vendor/github.com/gin-gonic/gin/.gitignore new file mode 100644 index 0000000..bdd50c9 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/.gitignore @@ -0,0 +1,7 @@ +vendor/* +!vendor/vendor.json +coverage.out +count.out +test +profile.out +tmp.out diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/.travis.yml b/go/src/themaru/vendor/github.com/gin-gonic/gin/.travis.yml new file mode 100644 index 0000000..f6ec8a8 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/.travis.yml @@ -0,0 +1,44 @@ +language: go + +matrix: + fast_finish: true + include: + - go: 1.8.x + - go: 1.9.x + - go: 1.10.x + - go: 1.11.x + env: GO111MODULE=on + - go: 1.12.x + env: GO111MODULE=on + - go: master + env: GO111MODULE=on + +git: + depth: 10 + +before_install: + - if [[ "${GO111MODULE}" = "on" ]]; then mkdir "${HOME}/go"; export GOPATH="${HOME}/go"; fi + +install: + - if [[ "${GO111MODULE}" = "on" ]]; then go mod download; else make install; fi + - if [[ "${GO111MODULE}" = "on" ]]; then export PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}"; fi + - if [[ "${GO111MODULE}" = "on" ]]; then make tools; fi + +go_import_path: github.com/gin-gonic/gin + +script: + - make vet + - make fmt-check + - make misspell-check + - make test + +after_success: + - bash <(curl -s https://codecov.io/bash) + +notifications: + webhooks: + urls: + - https://webhooks.gitter.im/e/7f95bf605c4d356372f4 + on_success: change # options: [always|never|change] default: always + on_failure: always # options: [always|never|change] default: always + on_start: false # default: false diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/AUTHORS.md b/go/src/themaru/vendor/github.com/gin-gonic/gin/AUTHORS.md new file mode 100644 index 0000000..dda19bc --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/AUTHORS.md @@ -0,0 +1,231 @@ +List of all the awesome people working to make Gin the best Web Framework in Go. + +## gin 1.x series authors + +**Gin Core Team:** Bo-Yi Wu (@appleboy), 田欧 (@thinkerou), Javier Provecho (@javierprovecho) + +## gin 0.x series authors + +**Maintainers:** Manu Martinez-Almeida (@manucorporat), Javier Provecho (@javierprovecho) + +People and companies, who have contributed, in alphabetical order. + +**@858806258 (杰哥)** +- Fix typo in example + + +**@achedeuzot (Klemen Sever)** +- Fix newline debug printing + + +**@adammck (Adam Mckaig)** +- Add MIT license + + +**@AlexanderChen1989 (Alexander)** +- Typos in README + + +**@alexanderdidenko (Aleksandr Didenko)** +- Add support multipart/form-data + + +**@alexandernyquist (Alexander Nyquist)** +- Using template.Must to fix multiple return issue +- ★ Added support for OPTIONS verb +- ★ Setting response headers before calling WriteHeader +- Improved documentation for model binding +- ★ Added Content.Redirect() +- ★ Added tons of Unit tests + + +**@austinheap (Austin Heap)** +- Added travis CI integration + + +**@andredublin (Andre Dublin)** +- Fix typo in comment + + +**@bredov (Ludwig Valda Vasquez)** +- Fix html templating in debug mode + + +**@bluele (Jun Kimura)** +- Fixes code examples in README + + +**@chad-russell** +- ★ Support for serializing gin.H into XML + + +**@dickeyxxx (Jeff Dickey)** +- Typos in README +- Add example about serving static files + + +**@donileo (Adonis)** +- Add NoMethod handler + + +**@dutchcoders (DutchCoders)** +- ★ Fix security bug that allows client to spoof ip +- Fix typo. r.HTMLTemplates -> SetHTMLTemplate + + +**@el3ctro- (Joshua Loper)** +- Fix typo in example + + +**@ethankan (Ethan Kan)** +- Unsigned integers in binding + + +**(Evgeny Persienko)** +- Validate sub structures + + +**@frankbille (Frank Bille)** +- Add support for HTTP Realm Auth + + +**@fmd (Fareed Dudhia)** +- Fix typo. SetHTTPTemplate -> SetHTMLTemplate + + +**@ironiridis (Christopher Harrington)** +- Remove old reference + + +**@jammie-stackhouse (Jamie Stackhouse)** +- Add more shortcuts for router methods + + +**@jasonrhansen** +- Fix spelling and grammar errors in documentation + + +**@JasonSoft (Jason Lee)** +- Fix typo in comment + + +**@joiggama (Ignacio Galindo)** +- Add utf-8 charset header on renders + + +**@julienschmidt (Julien Schmidt)** +- gofmt the code examples + + +**@kelcecil (Kel Cecil)** +- Fix readme typo + + +**@kyledinh (Kyle Dinh)** +- Adds RunTLS() + + +**@LinusU (Linus Unnebäck)** +- Small fixes in README + + +**@loongmxbt (Saint Asky)** +- Fix typo in example + + +**@lucas-clemente (Lucas Clemente)** +- ★ work around path.Join removing trailing slashes from routes + + +**@mattn (Yasuhiro Matsumoto)** +- Improve color logger + + +**@mdigger (Dmitry Sedykh)** +- Fixes Form binding when content-type is x-www-form-urlencoded +- No repeat call c.Writer.Status() in gin.Logger +- Fixes Content-Type for json render + + +**@mirzac (Mirza Ceric)** +- Fix debug printing + + +**@mopemope (Yutaka Matsubara)** +- ★ Adds Godep support (Dependencies Manager) +- Fix variadic parameter in the flexible render API +- Fix Corrupted plain render +- Add Pluggable View Renderer Example + + +**@msemenistyi (Mykyta Semenistyi)** +- update Readme.md. Add code to String method + + +**@msoedov (Sasha Myasoedov)** +- ★ Adds tons of unit tests. + + +**@ngerakines (Nick Gerakines)** +- ★ Improves API, c.GET() doesn't panic +- Adds MustGet() method + + +**@r8k (Rajiv Kilaparti)** +- Fix Port usage in README. + + +**@rayrod2030 (Ray Rodriguez)** +- Fix typo in example + + +**@rns** +- Fix typo in example + + +**@RobAWilkinson (Robert Wilkinson)** +- Add example of forms and params + + +**@rogierlommers (Rogier Lommers)** +- Add updated static serve example + + +**@se77en (Damon Zhao)** +- Improve color logging + + +**@silasb (Silas Baronda)** +- Fixing quotes in README + + +**@SkuliOskarsson (Skuli Oskarsson)** +- Fixes some texts in README II + + +**@slimmy (Jimmy Pettersson)** +- Added messages for required bindings + + +**@smira (Andrey Smirnov)** +- Add support for ignored/unexported fields in binding + + +**@superalsrk (SRK.Lyu)** +- Update httprouter godeps + + +**@tebeka (Miki Tebeka)** +- Use net/http constants instead of numeric values + + +**@techjanitor** +- Update context.go reserved IPs + + +**@yosssi (Keiji Yoshida)** +- Fix link in README + + +**@yuyabee** +- Fixed README diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/BENCHMARKS.md b/go/src/themaru/vendor/github.com/gin-gonic/gin/BENCHMARKS.md new file mode 100644 index 0000000..9a7df86 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/BENCHMARKS.md @@ -0,0 +1,604 @@ + +## Benchmark System + +**VM HOST:** DigitalOcean +**Machine:** 4 CPU, 8 GB RAM. Ubuntu 16.04.2 x64 +**Date:** July 19th, 2017 +**Go Version:** 1.8.3 linux/amd64 +**Source:** [Go HTTP Router Benchmark](https://github.com/julienschmidt/go-http-routing-benchmark) + +## Static Routes: 157 + +``` +Gin: 30512 Bytes + +HttpServeMux: 17344 Bytes +Ace: 30080 Bytes +Bear: 30472 Bytes +Beego: 96408 Bytes +Bone: 37904 Bytes +Denco: 10464 Bytes +Echo: 73680 Bytes +GocraftWeb: 55720 Bytes +Goji: 27200 Bytes +Gojiv2: 104464 Bytes +GoJsonRest: 136472 Bytes +GoRestful: 914904 Bytes +GorillaMux: 675568 Bytes +HttpRouter: 21128 Bytes +HttpTreeMux: 73448 Bytes +Kocha: 115072 Bytes +LARS: 30120 Bytes +Macaron: 37984 Bytes +Martini: 310832 Bytes +Pat: 20464 Bytes +Possum: 91328 Bytes +R2router: 23712 Bytes +Rivet: 23880 Bytes +Tango: 28008 Bytes +TigerTonic: 80368 Bytes +Traffic: 626480 Bytes +Vulcan: 369064 Bytes +``` + +## GithubAPI Routes: 203 + +``` +Gin: 52672 Bytes + +Ace: 48992 Bytes +Bear: 161592 Bytes +Beego: 147992 Bytes +Bone: 97728 Bytes +Denco: 36440 Bytes +Echo: 95672 Bytes +GocraftWeb: 95640 Bytes +Goji: 86088 Bytes +Gojiv2: 144392 Bytes +GoJsonRest: 134648 Bytes +GoRestful: 1410760 Bytes +GorillaMux: 1509488 Bytes +HttpRouter: 37464 Bytes +HttpTreeMux: 78800 Bytes +Kocha: 785408 Bytes +LARS: 49032 Bytes +Macaron: 132712 Bytes +Martini: 564352 Bytes +Pat: 21200 Bytes +Possum: 83888 Bytes +R2router: 47104 Bytes +Rivet: 42840 Bytes +Tango: 54584 Bytes +TigerTonic: 96384 Bytes +Traffic: 1061920 Bytes +Vulcan: 465296 Bytes +``` + +## GPlusAPI Routes: 13 + +``` +Gin: 3968 Bytes + +Ace: 3600 Bytes +Bear: 7112 Bytes +Beego: 10048 Bytes +Bone: 6480 Bytes +Denco: 3256 Bytes +Echo: 9000 Bytes +GocraftWeb: 7496 Bytes +Goji: 2912 Bytes +Gojiv2: 7376 Bytes +GoJsonRest: 11544 Bytes +GoRestful: 88776 Bytes +GorillaMux: 71488 Bytes +HttpRouter: 2712 Bytes +HttpTreeMux: 7440 Bytes +Kocha: 128880 Bytes +LARS: 3640 Bytes +Macaron: 8656 Bytes +Martini: 23936 Bytes +Pat: 1856 Bytes +Possum: 7248 Bytes +R2router: 3928 Bytes +Rivet: 3064 Bytes +Tango: 4912 Bytes +TigerTonic: 9408 Bytes +Traffic: 49472 Bytes +Vulcan: 25496 Bytes +``` + +## ParseAPI Routes: 26 + +``` +Gin: 6928 Bytes + +Ace: 6592 Bytes +Bear: 12320 Bytes +Beego: 18960 Bytes +Bone: 11024 Bytes +Denco: 4184 Bytes +Echo: 11168 Bytes +GocraftWeb: 12800 Bytes +Goji: 5232 Bytes +Gojiv2: 14464 Bytes +GoJsonRest: 14216 Bytes +GoRestful: 127368 Bytes +GorillaMux: 123016 Bytes +HttpRouter: 4976 Bytes +HttpTreeMux: 7848 Bytes +Kocha: 181712 Bytes +LARS: 6632 Bytes +Macaron: 13648 Bytes +Martini: 45952 Bytes +Pat: 2560 Bytes +Possum: 9200 Bytes +R2router: 7056 Bytes +Rivet: 5680 Bytes +Tango: 8664 Bytes +TigerTonic: 9840 Bytes +Traffic: 93480 Bytes +Vulcan: 44504 Bytes +``` + +## Static Routes + +``` +BenchmarkGin_StaticAll 50000 34506 ns/op 0 B/op 0 allocs/op + +BenchmarkAce_StaticAll 30000 49657 ns/op 0 B/op 0 allocs/op +BenchmarkHttpServeMux_StaticAll 2000 1183737 ns/op 96 B/op 8 allocs/op +BenchmarkBeego_StaticAll 5000 412621 ns/op 57776 B/op 628 allocs/op +BenchmarkBear_StaticAll 10000 149242 ns/op 20336 B/op 461 allocs/op +BenchmarkBone_StaticAll 10000 118583 ns/op 0 B/op 0 allocs/op +BenchmarkDenco_StaticAll 100000 13247 ns/op 0 B/op 0 allocs/op +BenchmarkEcho_StaticAll 20000 79914 ns/op 5024 B/op 157 allocs/op +BenchmarkGocraftWeb_StaticAll 10000 211823 ns/op 46440 B/op 785 allocs/op +BenchmarkGoji_StaticAll 10000 109390 ns/op 0 B/op 0 allocs/op +BenchmarkGojiv2_StaticAll 3000 415533 ns/op 145696 B/op 1099 allocs/op +BenchmarkGoJsonRest_StaticAll 5000 364403 ns/op 51653 B/op 1727 allocs/op +BenchmarkGoRestful_StaticAll 500 2578579 ns/op 314936 B/op 3144 allocs/op +BenchmarkGorillaMux_StaticAll 500 2704856 ns/op 115648 B/op 1578 allocs/op +BenchmarkHttpRouter_StaticAll 100000 18541 ns/op 0 B/op 0 allocs/op +BenchmarkHttpTreeMux_StaticAll 100000 22332 ns/op 0 B/op 0 allocs/op +BenchmarkKocha_StaticAll 50000 31176 ns/op 0 B/op 0 allocs/op +BenchmarkLARS_StaticAll 50000 40840 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_StaticAll 5000 517656 ns/op 120576 B/op 1413 allocs/op +BenchmarkMartini_StaticAll 300 4462289 ns/op 125442 B/op 1717 allocs/op +BenchmarkPat_StaticAll 500 2157275 ns/op 533904 B/op 11123 allocs/op +BenchmarkPossum_StaticAll 10000 254701 ns/op 65312 B/op 471 allocs/op +BenchmarkR2router_StaticAll 10000 133956 ns/op 22608 B/op 628 allocs/op +BenchmarkRivet_StaticAll 30000 46812 ns/op 0 B/op 0 allocs/op +BenchmarkTango_StaticAll 5000 390613 ns/op 39225 B/op 1256 allocs/op +BenchmarkTigerTonic_StaticAll 20000 88060 ns/op 7504 B/op 157 allocs/op +BenchmarkTraffic_StaticAll 500 2910236 ns/op 729736 B/op 14287 allocs/op +BenchmarkVulcan_StaticAll 5000 277366 ns/op 15386 B/op 471 allocs/op +``` + +## Micro Benchmarks + +``` +BenchmarkGin_Param 20000000 113 ns/op 0 B/op 0 allocs/op + +BenchmarkAce_Param 5000000 375 ns/op 32 B/op 1 allocs/op +BenchmarkBear_Param 1000000 1709 ns/op 456 B/op 5 allocs/op +BenchmarkBeego_Param 1000000 2484 ns/op 368 B/op 4 allocs/op +BenchmarkBone_Param 1000000 2391 ns/op 688 B/op 5 allocs/op +BenchmarkDenco_Param 10000000 240 ns/op 32 B/op 1 allocs/op +BenchmarkEcho_Param 5000000 366 ns/op 32 B/op 1 allocs/op +BenchmarkGocraftWeb_Param 1000000 2343 ns/op 648 B/op 8 allocs/op +BenchmarkGoji_Param 1000000 1197 ns/op 336 B/op 2 allocs/op +BenchmarkGojiv2_Param 1000000 2771 ns/op 944 B/op 8 allocs/op +BenchmarkGoJsonRest_Param 1000000 2993 ns/op 649 B/op 13 allocs/op +BenchmarkGoRestful_Param 200000 8860 ns/op 2296 B/op 21 allocs/op +BenchmarkGorillaMux_Param 500000 4461 ns/op 1056 B/op 11 allocs/op +BenchmarkHttpRouter_Param 10000000 175 ns/op 32 B/op 1 allocs/op +BenchmarkHttpTreeMux_Param 1000000 1167 ns/op 352 B/op 3 allocs/op +BenchmarkKocha_Param 3000000 429 ns/op 56 B/op 3 allocs/op +BenchmarkLARS_Param 10000000 134 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_Param 500000 4635 ns/op 1056 B/op 10 allocs/op +BenchmarkMartini_Param 200000 9933 ns/op 1072 B/op 10 allocs/op +BenchmarkPat_Param 1000000 2929 ns/op 648 B/op 12 allocs/op +BenchmarkPossum_Param 1000000 2503 ns/op 560 B/op 6 allocs/op +BenchmarkR2router_Param 1000000 1507 ns/op 432 B/op 5 allocs/op +BenchmarkRivet_Param 5000000 297 ns/op 48 B/op 1 allocs/op +BenchmarkTango_Param 1000000 1862 ns/op 248 B/op 8 allocs/op +BenchmarkTigerTonic_Param 500000 5660 ns/op 992 B/op 17 allocs/op +BenchmarkTraffic_Param 200000 8408 ns/op 1960 B/op 21 allocs/op +BenchmarkVulcan_Param 2000000 963 ns/op 98 B/op 3 allocs/op +BenchmarkAce_Param5 2000000 740 ns/op 160 B/op 1 allocs/op +BenchmarkBear_Param5 1000000 2777 ns/op 501 B/op 5 allocs/op +BenchmarkBeego_Param5 1000000 3740 ns/op 368 B/op 4 allocs/op +BenchmarkBone_Param5 1000000 2950 ns/op 736 B/op 5 allocs/op +BenchmarkDenco_Param5 2000000 644 ns/op 160 B/op 1 allocs/op +BenchmarkEcho_Param5 3000000 558 ns/op 32 B/op 1 allocs/op +BenchmarkGin_Param5 10000000 198 ns/op 0 B/op 0 allocs/op +BenchmarkGocraftWeb_Param5 500000 3870 ns/op 920 B/op 11 allocs/op +BenchmarkGoji_Param5 1000000 1746 ns/op 336 B/op 2 allocs/op +BenchmarkGojiv2_Param5 1000000 3214 ns/op 1008 B/op 8 allocs/op +BenchmarkGoJsonRest_Param5 500000 5509 ns/op 1097 B/op 16 allocs/op +BenchmarkGoRestful_Param5 200000 11232 ns/op 2392 B/op 21 allocs/op +BenchmarkGorillaMux_Param5 300000 7777 ns/op 1184 B/op 11 allocs/op +BenchmarkHttpRouter_Param5 3000000 631 ns/op 160 B/op 1 allocs/op +BenchmarkHttpTreeMux_Param5 1000000 2800 ns/op 576 B/op 6 allocs/op +BenchmarkKocha_Param5 1000000 2053 ns/op 440 B/op 10 allocs/op +BenchmarkLARS_Param5 10000000 232 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_Param5 500000 5888 ns/op 1056 B/op 10 allocs/op +BenchmarkMartini_Param5 200000 12807 ns/op 1232 B/op 11 allocs/op +BenchmarkPat_Param5 300000 7320 ns/op 964 B/op 32 allocs/op +BenchmarkPossum_Param5 1000000 2495 ns/op 560 B/op 6 allocs/op +BenchmarkR2router_Param5 1000000 1844 ns/op 432 B/op 5 allocs/op +BenchmarkRivet_Param5 2000000 935 ns/op 240 B/op 1 allocs/op +BenchmarkTango_Param5 1000000 2327 ns/op 360 B/op 8 allocs/op +BenchmarkTigerTonic_Param5 100000 18514 ns/op 2551 B/op 43 allocs/op +BenchmarkTraffic_Param5 200000 11997 ns/op 2248 B/op 25 allocs/op +BenchmarkVulcan_Param5 1000000 1333 ns/op 98 B/op 3 allocs/op +BenchmarkAce_Param20 1000000 2031 ns/op 640 B/op 1 allocs/op +BenchmarkBear_Param20 200000 7285 ns/op 1664 B/op 5 allocs/op +BenchmarkBeego_Param20 300000 6224 ns/op 368 B/op 4 allocs/op +BenchmarkBone_Param20 200000 8023 ns/op 1903 B/op 5 allocs/op +BenchmarkDenco_Param20 1000000 2262 ns/op 640 B/op 1 allocs/op +BenchmarkEcho_Param20 1000000 1387 ns/op 32 B/op 1 allocs/op +BenchmarkGin_Param20 3000000 503 ns/op 0 B/op 0 allocs/op +BenchmarkGocraftWeb_Param20 100000 14408 ns/op 3795 B/op 15 allocs/op +BenchmarkGoji_Param20 500000 5272 ns/op 1247 B/op 2 allocs/op +BenchmarkGojiv2_Param20 1000000 4163 ns/op 1248 B/op 8 allocs/op +BenchmarkGoJsonRest_Param20 100000 17866 ns/op 4485 B/op 20 allocs/op +BenchmarkGoRestful_Param20 100000 21022 ns/op 4724 B/op 23 allocs/op +BenchmarkGorillaMux_Param20 100000 17055 ns/op 3547 B/op 13 allocs/op +BenchmarkHttpRouter_Param20 1000000 1748 ns/op 640 B/op 1 allocs/op +BenchmarkHttpTreeMux_Param20 200000 12246 ns/op 3196 B/op 10 allocs/op +BenchmarkKocha_Param20 300000 6861 ns/op 1808 B/op 27 allocs/op +BenchmarkLARS_Param20 3000000 526 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_Param20 100000 13069 ns/op 2906 B/op 12 allocs/op +BenchmarkMartini_Param20 100000 23602 ns/op 3597 B/op 13 allocs/op +BenchmarkPat_Param20 50000 32143 ns/op 4688 B/op 111 allocs/op +BenchmarkPossum_Param20 1000000 2396 ns/op 560 B/op 6 allocs/op +BenchmarkR2router_Param20 200000 8907 ns/op 2283 B/op 7 allocs/op +BenchmarkRivet_Param20 1000000 3280 ns/op 1024 B/op 1 allocs/op +BenchmarkTango_Param20 500000 4640 ns/op 856 B/op 8 allocs/op +BenchmarkTigerTonic_Param20 20000 67581 ns/op 10532 B/op 138 allocs/op +BenchmarkTraffic_Param20 50000 40313 ns/op 7941 B/op 45 allocs/op +BenchmarkVulcan_Param20 1000000 2264 ns/op 98 B/op 3 allocs/op +BenchmarkAce_ParamWrite 3000000 532 ns/op 40 B/op 2 allocs/op +BenchmarkBear_ParamWrite 1000000 1778 ns/op 456 B/op 5 allocs/op +BenchmarkBeego_ParamWrite 1000000 2596 ns/op 376 B/op 5 allocs/op +BenchmarkBone_ParamWrite 1000000 2519 ns/op 688 B/op 5 allocs/op +BenchmarkDenco_ParamWrite 5000000 411 ns/op 32 B/op 1 allocs/op +BenchmarkEcho_ParamWrite 2000000 718 ns/op 40 B/op 2 allocs/op +BenchmarkGin_ParamWrite 5000000 283 ns/op 0 B/op 0 allocs/op +BenchmarkGocraftWeb_ParamWrite 1000000 2561 ns/op 656 B/op 9 allocs/op +BenchmarkGoji_ParamWrite 1000000 1378 ns/op 336 B/op 2 allocs/op +BenchmarkGojiv2_ParamWrite 1000000 3128 ns/op 976 B/op 10 allocs/op +BenchmarkGoJsonRest_ParamWrite 500000 4446 ns/op 1128 B/op 18 allocs/op +BenchmarkGoRestful_ParamWrite 200000 10291 ns/op 2304 B/op 22 allocs/op +BenchmarkGorillaMux_ParamWrite 500000 5153 ns/op 1064 B/op 12 allocs/op +BenchmarkHttpRouter_ParamWrite 5000000 263 ns/op 32 B/op 1 allocs/op +BenchmarkHttpTreeMux_ParamWrite 1000000 1351 ns/op 352 B/op 3 allocs/op +BenchmarkKocha_ParamWrite 3000000 538 ns/op 56 B/op 3 allocs/op +BenchmarkLARS_ParamWrite 5000000 316 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_ParamWrite 500000 5756 ns/op 1160 B/op 14 allocs/op +BenchmarkMartini_ParamWrite 200000 13097 ns/op 1176 B/op 14 allocs/op +BenchmarkPat_ParamWrite 500000 4954 ns/op 1072 B/op 17 allocs/op +BenchmarkPossum_ParamWrite 1000000 2499 ns/op 560 B/op 6 allocs/op +BenchmarkR2router_ParamWrite 1000000 1531 ns/op 432 B/op 5 allocs/op +BenchmarkRivet_ParamWrite 3000000 570 ns/op 112 B/op 2 allocs/op +BenchmarkTango_ParamWrite 2000000 957 ns/op 136 B/op 4 allocs/op +BenchmarkTigerTonic_ParamWrite 200000 7025 ns/op 1424 B/op 23 allocs/op +BenchmarkTraffic_ParamWrite 200000 10112 ns/op 2384 B/op 25 allocs/op +BenchmarkVulcan_ParamWrite 1000000 1006 ns/op 98 B/op 3 allocs/op +``` + +## GitHub + +``` +BenchmarkGin_GithubStatic 10000000 156 ns/op 0 B/op 0 allocs/op + +BenchmarkAce_GithubStatic 5000000 294 ns/op 0 B/op 0 allocs/op +BenchmarkBear_GithubStatic 2000000 893 ns/op 120 B/op 3 allocs/op +BenchmarkBeego_GithubStatic 1000000 2491 ns/op 368 B/op 4 allocs/op +BenchmarkBone_GithubStatic 50000 25300 ns/op 2880 B/op 60 allocs/op +BenchmarkDenco_GithubStatic 20000000 76.0 ns/op 0 B/op 0 allocs/op +BenchmarkEcho_GithubStatic 2000000 516 ns/op 32 B/op 1 allocs/op +BenchmarkGocraftWeb_GithubStatic 1000000 1448 ns/op 296 B/op 5 allocs/op +BenchmarkGoji_GithubStatic 3000000 496 ns/op 0 B/op 0 allocs/op +BenchmarkGojiv2_GithubStatic 1000000 2941 ns/op 928 B/op 7 allocs/op +BenchmarkGoRestful_GithubStatic 100000 27256 ns/op 3224 B/op 22 allocs/op +BenchmarkGoJsonRest_GithubStatic 1000000 2196 ns/op 329 B/op 11 allocs/op +BenchmarkGorillaMux_GithubStatic 50000 31617 ns/op 736 B/op 10 allocs/op +BenchmarkHttpRouter_GithubStatic 20000000 88.4 ns/op 0 B/op 0 allocs/op +BenchmarkHttpTreeMux_GithubStatic 10000000 134 ns/op 0 B/op 0 allocs/op +BenchmarkKocha_GithubStatic 20000000 113 ns/op 0 B/op 0 allocs/op +BenchmarkLARS_GithubStatic 10000000 195 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_GithubStatic 500000 3740 ns/op 768 B/op 9 allocs/op +BenchmarkMartini_GithubStatic 50000 27673 ns/op 768 B/op 9 allocs/op +BenchmarkPat_GithubStatic 100000 19470 ns/op 3648 B/op 76 allocs/op +BenchmarkPossum_GithubStatic 1000000 1729 ns/op 416 B/op 3 allocs/op +BenchmarkR2router_GithubStatic 2000000 879 ns/op 144 B/op 4 allocs/op +BenchmarkRivet_GithubStatic 10000000 231 ns/op 0 B/op 0 allocs/op +BenchmarkTango_GithubStatic 1000000 2325 ns/op 248 B/op 8 allocs/op +BenchmarkTigerTonic_GithubStatic 3000000 610 ns/op 48 B/op 1 allocs/op +BenchmarkTraffic_GithubStatic 20000 62973 ns/op 18904 B/op 148 allocs/op +BenchmarkVulcan_GithubStatic 1000000 1447 ns/op 98 B/op 3 allocs/op +BenchmarkAce_GithubParam 2000000 686 ns/op 96 B/op 1 allocs/op +BenchmarkBear_GithubParam 1000000 2155 ns/op 496 B/op 5 allocs/op +BenchmarkBeego_GithubParam 1000000 2713 ns/op 368 B/op 4 allocs/op +BenchmarkBone_GithubParam 100000 15088 ns/op 1760 B/op 18 allocs/op +BenchmarkDenco_GithubParam 2000000 629 ns/op 128 B/op 1 allocs/op +BenchmarkEcho_GithubParam 2000000 653 ns/op 32 B/op 1 allocs/op +BenchmarkGin_GithubParam 5000000 255 ns/op 0 B/op 0 allocs/op +BenchmarkGocraftWeb_GithubParam 1000000 3145 ns/op 712 B/op 9 allocs/op +BenchmarkGoji_GithubParam 1000000 1916 ns/op 336 B/op 2 allocs/op +BenchmarkGojiv2_GithubParam 1000000 3975 ns/op 1024 B/op 10 allocs/op +BenchmarkGoJsonRest_GithubParam 300000 4134 ns/op 713 B/op 14 allocs/op +BenchmarkGoRestful_GithubParam 50000 30782 ns/op 2360 B/op 21 allocs/op +BenchmarkGorillaMux_GithubParam 100000 17148 ns/op 1088 B/op 11 allocs/op +BenchmarkHttpRouter_GithubParam 3000000 523 ns/op 96 B/op 1 allocs/op +BenchmarkHttpTreeMux_GithubParam 1000000 1671 ns/op 384 B/op 4 allocs/op +BenchmarkKocha_GithubParam 1000000 1021 ns/op 128 B/op 5 allocs/op +BenchmarkLARS_GithubParam 5000000 283 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_GithubParam 500000 4270 ns/op 1056 B/op 10 allocs/op +BenchmarkMartini_GithubParam 100000 21728 ns/op 1152 B/op 11 allocs/op +BenchmarkPat_GithubParam 200000 11208 ns/op 2464 B/op 48 allocs/op +BenchmarkPossum_GithubParam 1000000 2334 ns/op 560 B/op 6 allocs/op +BenchmarkR2router_GithubParam 1000000 1487 ns/op 432 B/op 5 allocs/op +BenchmarkRivet_GithubParam 2000000 782 ns/op 96 B/op 1 allocs/op +BenchmarkTango_GithubParam 1000000 2653 ns/op 344 B/op 8 allocs/op +BenchmarkTigerTonic_GithubParam 300000 14073 ns/op 1440 B/op 24 allocs/op +BenchmarkTraffic_GithubParam 50000 29164 ns/op 5992 B/op 52 allocs/op +BenchmarkVulcan_GithubParam 1000000 2529 ns/op 98 B/op 3 allocs/op +BenchmarkAce_GithubAll 10000 134059 ns/op 13792 B/op 167 allocs/op +BenchmarkBear_GithubAll 5000 534445 ns/op 86448 B/op 943 allocs/op +BenchmarkBeego_GithubAll 3000 592444 ns/op 74705 B/op 812 allocs/op +BenchmarkBone_GithubAll 200 6957308 ns/op 698784 B/op 8453 allocs/op +BenchmarkDenco_GithubAll 10000 158819 ns/op 20224 B/op 167 allocs/op +BenchmarkEcho_GithubAll 10000 154700 ns/op 6496 B/op 203 allocs/op +BenchmarkGin_GithubAll 30000 48375 ns/op 0 B/op 0 allocs/op +BenchmarkGocraftWeb_GithubAll 3000 570806 ns/op 131656 B/op 1686 allocs/op +BenchmarkGoji_GithubAll 2000 818034 ns/op 56112 B/op 334 allocs/op +BenchmarkGojiv2_GithubAll 2000 1213973 ns/op 274768 B/op 3712 allocs/op +BenchmarkGoJsonRest_GithubAll 2000 785796 ns/op 134371 B/op 2737 allocs/op +BenchmarkGoRestful_GithubAll 300 5238188 ns/op 689672 B/op 4519 allocs/op +BenchmarkGorillaMux_GithubAll 100 10257726 ns/op 211840 B/op 2272 allocs/op +BenchmarkHttpRouter_GithubAll 20000 105414 ns/op 13792 B/op 167 allocs/op +BenchmarkHttpTreeMux_GithubAll 10000 319934 ns/op 65856 B/op 671 allocs/op +BenchmarkKocha_GithubAll 10000 209442 ns/op 23304 B/op 843 allocs/op +BenchmarkLARS_GithubAll 20000 62565 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_GithubAll 2000 1161270 ns/op 204194 B/op 2000 allocs/op +BenchmarkMartini_GithubAll 200 9991713 ns/op 226549 B/op 2325 allocs/op +BenchmarkPat_GithubAll 200 5590793 ns/op 1499568 B/op 27435 allocs/op +BenchmarkPossum_GithubAll 10000 319768 ns/op 84448 B/op 609 allocs/op +BenchmarkR2router_GithubAll 10000 305134 ns/op 77328 B/op 979 allocs/op +BenchmarkRivet_GithubAll 10000 132134 ns/op 16272 B/op 167 allocs/op +BenchmarkTango_GithubAll 3000 552754 ns/op 63826 B/op 1618 allocs/op +BenchmarkTigerTonic_GithubAll 1000 1439483 ns/op 239104 B/op 5374 allocs/op +BenchmarkTraffic_GithubAll 100 11383067 ns/op 2659329 B/op 21848 allocs/op +BenchmarkVulcan_GithubAll 5000 394253 ns/op 19894 B/op 609 allocs/op +``` + +## Google+ + +``` +BenchmarkGin_GPlusStatic 10000000 183 ns/op 0 B/op 0 allocs/op + +BenchmarkAce_GPlusStatic 5000000 276 ns/op 0 B/op 0 allocs/op +BenchmarkBear_GPlusStatic 2000000 652 ns/op 104 B/op 3 allocs/op +BenchmarkBeego_GPlusStatic 1000000 2239 ns/op 368 B/op 4 allocs/op +BenchmarkBone_GPlusStatic 5000000 380 ns/op 32 B/op 1 allocs/op +BenchmarkDenco_GPlusStatic 30000000 45.8 ns/op 0 B/op 0 allocs/op +BenchmarkEcho_GPlusStatic 5000000 338 ns/op 32 B/op 1 allocs/op +BenchmarkGocraftWeb_GPlusStatic 1000000 1158 ns/op 280 B/op 5 allocs/op +BenchmarkGoji_GPlusStatic 5000000 331 ns/op 0 B/op 0 allocs/op +BenchmarkGojiv2_GPlusStatic 1000000 2106 ns/op 928 B/op 7 allocs/op +BenchmarkGoJsonRest_GPlusStatic 1000000 1626 ns/op 329 B/op 11 allocs/op +BenchmarkGoRestful_GPlusStatic 300000 7598 ns/op 1976 B/op 20 allocs/op +BenchmarkGorillaMux_GPlusStatic 1000000 2629 ns/op 736 B/op 10 allocs/op +BenchmarkHttpRouter_GPlusStatic 30000000 52.5 ns/op 0 B/op 0 allocs/op +BenchmarkHttpTreeMux_GPlusStatic 20000000 85.8 ns/op 0 B/op 0 allocs/op +BenchmarkKocha_GPlusStatic 20000000 89.2 ns/op 0 B/op 0 allocs/op +BenchmarkLARS_GPlusStatic 10000000 162 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_GPlusStatic 500000 3479 ns/op 768 B/op 9 allocs/op +BenchmarkMartini_GPlusStatic 200000 9092 ns/op 768 B/op 9 allocs/op +BenchmarkPat_GPlusStatic 3000000 493 ns/op 96 B/op 2 allocs/op +BenchmarkPossum_GPlusStatic 1000000 1467 ns/op 416 B/op 3 allocs/op +BenchmarkR2router_GPlusStatic 2000000 788 ns/op 144 B/op 4 allocs/op +BenchmarkRivet_GPlusStatic 20000000 114 ns/op 0 B/op 0 allocs/op +BenchmarkTango_GPlusStatic 1000000 1534 ns/op 200 B/op 8 allocs/op +BenchmarkTigerTonic_GPlusStatic 5000000 282 ns/op 32 B/op 1 allocs/op +BenchmarkTraffic_GPlusStatic 500000 3798 ns/op 1192 B/op 15 allocs/op +BenchmarkVulcan_GPlusStatic 2000000 1125 ns/op 98 B/op 3 allocs/op +BenchmarkAce_GPlusParam 3000000 528 ns/op 64 B/op 1 allocs/op +BenchmarkBear_GPlusParam 1000000 1570 ns/op 480 B/op 5 allocs/op +BenchmarkBeego_GPlusParam 1000000 2369 ns/op 368 B/op 4 allocs/op +BenchmarkBone_GPlusParam 1000000 2028 ns/op 688 B/op 5 allocs/op +BenchmarkDenco_GPlusParam 5000000 385 ns/op 64 B/op 1 allocs/op +BenchmarkEcho_GPlusParam 3000000 441 ns/op 32 B/op 1 allocs/op +BenchmarkGin_GPlusParam 10000000 174 ns/op 0 B/op 0 allocs/op +BenchmarkGocraftWeb_GPlusParam 1000000 2033 ns/op 648 B/op 8 allocs/op +BenchmarkGoji_GPlusParam 1000000 1399 ns/op 336 B/op 2 allocs/op +BenchmarkGojiv2_GPlusParam 1000000 2641 ns/op 944 B/op 8 allocs/op +BenchmarkGoJsonRest_GPlusParam 1000000 2824 ns/op 649 B/op 13 allocs/op +BenchmarkGoRestful_GPlusParam 200000 8875 ns/op 2296 B/op 21 allocs/op +BenchmarkGorillaMux_GPlusParam 200000 6291 ns/op 1056 B/op 11 allocs/op +BenchmarkHttpRouter_GPlusParam 5000000 316 ns/op 64 B/op 1 allocs/op +BenchmarkHttpTreeMux_GPlusParam 1000000 1129 ns/op 352 B/op 3 allocs/op +BenchmarkKocha_GPlusParam 3000000 538 ns/op 56 B/op 3 allocs/op +BenchmarkLARS_GPlusParam 10000000 198 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_GPlusParam 500000 3554 ns/op 1056 B/op 10 allocs/op +BenchmarkMartini_GPlusParam 200000 9831 ns/op 1072 B/op 10 allocs/op +BenchmarkPat_GPlusParam 1000000 2706 ns/op 688 B/op 12 allocs/op +BenchmarkPossum_GPlusParam 1000000 2297 ns/op 560 B/op 6 allocs/op +BenchmarkR2router_GPlusParam 1000000 1318 ns/op 432 B/op 5 allocs/op +BenchmarkRivet_GPlusParam 5000000 399 ns/op 48 B/op 1 allocs/op +BenchmarkTango_GPlusParam 1000000 2070 ns/op 264 B/op 8 allocs/op +BenchmarkTigerTonic_GPlusParam 500000 4853 ns/op 1056 B/op 17 allocs/op +BenchmarkTraffic_GPlusParam 200000 8278 ns/op 1976 B/op 21 allocs/op +BenchmarkVulcan_GPlusParam 1000000 1243 ns/op 98 B/op 3 allocs/op +BenchmarkAce_GPlus2Params 3000000 549 ns/op 64 B/op 1 allocs/op +BenchmarkBear_GPlus2Params 1000000 2112 ns/op 496 B/op 5 allocs/op +BenchmarkBeego_GPlus2Params 500000 2750 ns/op 368 B/op 4 allocs/op +BenchmarkBone_GPlus2Params 300000 7032 ns/op 1040 B/op 9 allocs/op +BenchmarkDenco_GPlus2Params 3000000 502 ns/op 64 B/op 1 allocs/op +BenchmarkEcho_GPlus2Params 3000000 641 ns/op 32 B/op 1 allocs/op +BenchmarkGin_GPlus2Params 5000000 250 ns/op 0 B/op 0 allocs/op +BenchmarkGocraftWeb_GPlus2Params 1000000 2681 ns/op 712 B/op 9 allocs/op +BenchmarkGoji_GPlus2Params 1000000 1926 ns/op 336 B/op 2 allocs/op +BenchmarkGojiv2_GPlus2Params 500000 3996 ns/op 1024 B/op 11 allocs/op +BenchmarkGoJsonRest_GPlus2Params 500000 3886 ns/op 713 B/op 14 allocs/op +BenchmarkGoRestful_GPlus2Params 200000 10376 ns/op 2360 B/op 21 allocs/op +BenchmarkGorillaMux_GPlus2Params 100000 14162 ns/op 1088 B/op 11 allocs/op +BenchmarkHttpRouter_GPlus2Params 5000000 336 ns/op 64 B/op 1 allocs/op +BenchmarkHttpTreeMux_GPlus2Params 1000000 1523 ns/op 384 B/op 4 allocs/op +BenchmarkKocha_GPlus2Params 2000000 970 ns/op 128 B/op 5 allocs/op +BenchmarkLARS_GPlus2Params 5000000 238 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_GPlus2Params 500000 4016 ns/op 1056 B/op 10 allocs/op +BenchmarkMartini_GPlus2Params 100000 21253 ns/op 1200 B/op 13 allocs/op +BenchmarkPat_GPlus2Params 200000 8632 ns/op 2256 B/op 34 allocs/op +BenchmarkPossum_GPlus2Params 1000000 2171 ns/op 560 B/op 6 allocs/op +BenchmarkR2router_GPlus2Params 1000000 1340 ns/op 432 B/op 5 allocs/op +BenchmarkRivet_GPlus2Params 3000000 557 ns/op 96 B/op 1 allocs/op +BenchmarkTango_GPlus2Params 1000000 2186 ns/op 344 B/op 8 allocs/op +BenchmarkTigerTonic_GPlus2Params 200000 9060 ns/op 1488 B/op 24 allocs/op +BenchmarkTraffic_GPlus2Params 100000 20324 ns/op 3272 B/op 31 allocs/op +BenchmarkVulcan_GPlus2Params 1000000 2039 ns/op 98 B/op 3 allocs/op +BenchmarkAce_GPlusAll 300000 6603 ns/op 640 B/op 11 allocs/op +BenchmarkBear_GPlusAll 100000 22363 ns/op 5488 B/op 61 allocs/op +BenchmarkBeego_GPlusAll 50000 38757 ns/op 4784 B/op 52 allocs/op +BenchmarkBone_GPlusAll 20000 54916 ns/op 10336 B/op 98 allocs/op +BenchmarkDenco_GPlusAll 300000 4959 ns/op 672 B/op 11 allocs/op +BenchmarkEcho_GPlusAll 200000 6558 ns/op 416 B/op 13 allocs/op +BenchmarkGin_GPlusAll 500000 2757 ns/op 0 B/op 0 allocs/op +BenchmarkGocraftWeb_GPlusAll 50000 34615 ns/op 8040 B/op 103 allocs/op +BenchmarkGoji_GPlusAll 100000 16002 ns/op 3696 B/op 22 allocs/op +BenchmarkGojiv2_GPlusAll 50000 35060 ns/op 12624 B/op 115 allocs/op +BenchmarkGoJsonRest_GPlusAll 50000 41479 ns/op 8117 B/op 170 allocs/op +BenchmarkGoRestful_GPlusAll 10000 131653 ns/op 32024 B/op 275 allocs/op +BenchmarkGorillaMux_GPlusAll 10000 101380 ns/op 13296 B/op 142 allocs/op +BenchmarkHttpRouter_GPlusAll 500000 3711 ns/op 640 B/op 11 allocs/op +BenchmarkHttpTreeMux_GPlusAll 100000 14438 ns/op 4032 B/op 38 allocs/op +BenchmarkKocha_GPlusAll 200000 8039 ns/op 976 B/op 43 allocs/op +BenchmarkLARS_GPlusAll 500000 2630 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_GPlusAll 30000 51123 ns/op 13152 B/op 128 allocs/op +BenchmarkMartini_GPlusAll 10000 176157 ns/op 14016 B/op 145 allocs/op +BenchmarkPat_GPlusAll 20000 69911 ns/op 16576 B/op 298 allocs/op +BenchmarkPossum_GPlusAll 100000 20716 ns/op 5408 B/op 39 allocs/op +BenchmarkR2router_GPlusAll 100000 17463 ns/op 5040 B/op 63 allocs/op +BenchmarkRivet_GPlusAll 300000 5142 ns/op 768 B/op 11 allocs/op +BenchmarkTango_GPlusAll 50000 27321 ns/op 3656 B/op 104 allocs/op +BenchmarkTigerTonic_GPlusAll 20000 77597 ns/op 14512 B/op 288 allocs/op +BenchmarkTraffic_GPlusAll 10000 151406 ns/op 37360 B/op 392 allocs/op +BenchmarkVulcan_GPlusAll 100000 18555 ns/op 1274 B/op 39 allocs/op +``` + +## Parse.com + +``` +BenchmarkGin_ParseStatic 10000000 133 ns/op 0 B/op 0 allocs/op + +BenchmarkAce_ParseStatic 5000000 241 ns/op 0 B/op 0 allocs/op +BenchmarkBear_ParseStatic 2000000 728 ns/op 120 B/op 3 allocs/op +BenchmarkBeego_ParseStatic 1000000 2623 ns/op 368 B/op 4 allocs/op +BenchmarkBone_ParseStatic 1000000 1285 ns/op 144 B/op 3 allocs/op +BenchmarkDenco_ParseStatic 30000000 57.8 ns/op 0 B/op 0 allocs/op +BenchmarkEcho_ParseStatic 5000000 342 ns/op 32 B/op 1 allocs/op +BenchmarkGocraftWeb_ParseStatic 1000000 1478 ns/op 296 B/op 5 allocs/op +BenchmarkGoji_ParseStatic 3000000 415 ns/op 0 B/op 0 allocs/op +BenchmarkGojiv2_ParseStatic 1000000 2087 ns/op 928 B/op 7 allocs/op +BenchmarkGoJsonRest_ParseStatic 1000000 1712 ns/op 329 B/op 11 allocs/op +BenchmarkGoRestful_ParseStatic 200000 11072 ns/op 3224 B/op 22 allocs/op +BenchmarkGorillaMux_ParseStatic 500000 4129 ns/op 752 B/op 11 allocs/op +BenchmarkHttpRouter_ParseStatic 30000000 52.4 ns/op 0 B/op 0 allocs/op +BenchmarkHttpTreeMux_ParseStatic 20000000 109 ns/op 0 B/op 0 allocs/op +BenchmarkKocha_ParseStatic 20000000 81.8 ns/op 0 B/op 0 allocs/op +BenchmarkLARS_ParseStatic 10000000 150 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_ParseStatic 1000000 3288 ns/op 768 B/op 9 allocs/op +BenchmarkMartini_ParseStatic 200000 9110 ns/op 768 B/op 9 allocs/op +BenchmarkPat_ParseStatic 1000000 1135 ns/op 240 B/op 5 allocs/op +BenchmarkPossum_ParseStatic 1000000 1557 ns/op 416 B/op 3 allocs/op +BenchmarkR2router_ParseStatic 2000000 730 ns/op 144 B/op 4 allocs/op +BenchmarkRivet_ParseStatic 10000000 121 ns/op 0 B/op 0 allocs/op +BenchmarkTango_ParseStatic 1000000 1688 ns/op 248 B/op 8 allocs/op +BenchmarkTigerTonic_ParseStatic 3000000 427 ns/op 48 B/op 1 allocs/op +BenchmarkTraffic_ParseStatic 500000 5962 ns/op 1816 B/op 20 allocs/op +BenchmarkVulcan_ParseStatic 2000000 969 ns/op 98 B/op 3 allocs/op +BenchmarkAce_ParseParam 3000000 497 ns/op 64 B/op 1 allocs/op +BenchmarkBear_ParseParam 1000000 1473 ns/op 467 B/op 5 allocs/op +BenchmarkBeego_ParseParam 1000000 2384 ns/op 368 B/op 4 allocs/op +BenchmarkBone_ParseParam 1000000 2513 ns/op 768 B/op 6 allocs/op +BenchmarkDenco_ParseParam 5000000 364 ns/op 64 B/op 1 allocs/op +BenchmarkEcho_ParseParam 5000000 418 ns/op 32 B/op 1 allocs/op +BenchmarkGin_ParseParam 10000000 163 ns/op 0 B/op 0 allocs/op +BenchmarkGocraftWeb_ParseParam 1000000 2361 ns/op 664 B/op 8 allocs/op +BenchmarkGoji_ParseParam 1000000 1590 ns/op 336 B/op 2 allocs/op +BenchmarkGojiv2_ParseParam 1000000 2851 ns/op 976 B/op 9 allocs/op +BenchmarkGoJsonRest_ParseParam 1000000 2965 ns/op 649 B/op 13 allocs/op +BenchmarkGoRestful_ParseParam 200000 12207 ns/op 3544 B/op 23 allocs/op +BenchmarkGorillaMux_ParseParam 500000 5187 ns/op 1088 B/op 12 allocs/op +BenchmarkHttpRouter_ParseParam 5000000 275 ns/op 64 B/op 1 allocs/op +BenchmarkHttpTreeMux_ParseParam 1000000 1108 ns/op 352 B/op 3 allocs/op +BenchmarkKocha_ParseParam 3000000 495 ns/op 56 B/op 3 allocs/op +BenchmarkLARS_ParseParam 10000000 192 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_ParseParam 500000 4103 ns/op 1056 B/op 10 allocs/op +BenchmarkMartini_ParseParam 200000 9878 ns/op 1072 B/op 10 allocs/op +BenchmarkPat_ParseParam 500000 3657 ns/op 1120 B/op 17 allocs/op +BenchmarkPossum_ParseParam 1000000 2084 ns/op 560 B/op 6 allocs/op +BenchmarkR2router_ParseParam 1000000 1251 ns/op 432 B/op 5 allocs/op +BenchmarkRivet_ParseParam 5000000 335 ns/op 48 B/op 1 allocs/op +BenchmarkTango_ParseParam 1000000 1854 ns/op 280 B/op 8 allocs/op +BenchmarkTigerTonic_ParseParam 500000 4582 ns/op 1008 B/op 17 allocs/op +BenchmarkTraffic_ParseParam 200000 8125 ns/op 2248 B/op 23 allocs/op +BenchmarkVulcan_ParseParam 1000000 1148 ns/op 98 B/op 3 allocs/op +BenchmarkAce_Parse2Params 3000000 539 ns/op 64 B/op 1 allocs/op +BenchmarkBear_Parse2Params 1000000 1778 ns/op 496 B/op 5 allocs/op +BenchmarkBeego_Parse2Params 1000000 2519 ns/op 368 B/op 4 allocs/op +BenchmarkBone_Parse2Params 1000000 2596 ns/op 720 B/op 5 allocs/op +BenchmarkDenco_Parse2Params 3000000 492 ns/op 64 B/op 1 allocs/op +BenchmarkEcho_Parse2Params 3000000 484 ns/op 32 B/op 1 allocs/op +BenchmarkGin_Parse2Params 10000000 193 ns/op 0 B/op 0 allocs/op +BenchmarkGocraftWeb_Parse2Params 1000000 2575 ns/op 712 B/op 9 allocs/op +BenchmarkGoji_Parse2Params 1000000 1373 ns/op 336 B/op 2 allocs/op +BenchmarkGojiv2_Parse2Params 500000 2416 ns/op 960 B/op 8 allocs/op +BenchmarkGoJsonRest_Parse2Params 300000 3452 ns/op 713 B/op 14 allocs/op +BenchmarkGoRestful_Parse2Params 100000 17719 ns/op 6008 B/op 25 allocs/op +BenchmarkGorillaMux_Parse2Params 300000 5102 ns/op 1088 B/op 11 allocs/op +BenchmarkHttpRouter_Parse2Params 5000000 303 ns/op 64 B/op 1 allocs/op +BenchmarkHttpTreeMux_Parse2Params 1000000 1372 ns/op 384 B/op 4 allocs/op +BenchmarkKocha_Parse2Params 2000000 874 ns/op 128 B/op 5 allocs/op +BenchmarkLARS_Parse2Params 10000000 192 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_Parse2Params 500000 3871 ns/op 1056 B/op 10 allocs/op +BenchmarkMartini_Parse2Params 200000 9954 ns/op 1152 B/op 11 allocs/op +BenchmarkPat_Parse2Params 500000 4194 ns/op 832 B/op 17 allocs/op +BenchmarkPossum_Parse2Params 1000000 2121 ns/op 560 B/op 6 allocs/op +BenchmarkR2router_Parse2Params 1000000 1415 ns/op 432 B/op 5 allocs/op +BenchmarkRivet_Parse2Params 3000000 457 ns/op 96 B/op 1 allocs/op +BenchmarkTango_Parse2Params 1000000 1914 ns/op 312 B/op 8 allocs/op +BenchmarkTigerTonic_Parse2Params 300000 6895 ns/op 1408 B/op 24 allocs/op +BenchmarkTraffic_Parse2Params 200000 8317 ns/op 2040 B/op 22 allocs/op +BenchmarkVulcan_Parse2Params 1000000 1274 ns/op 98 B/op 3 allocs/op +BenchmarkAce_ParseAll 200000 10401 ns/op 640 B/op 16 allocs/op +BenchmarkBear_ParseAll 50000 37743 ns/op 8928 B/op 110 allocs/op +BenchmarkBeego_ParseAll 20000 63193 ns/op 9568 B/op 104 allocs/op +BenchmarkBone_ParseAll 20000 61767 ns/op 14160 B/op 131 allocs/op +BenchmarkDenco_ParseAll 300000 7036 ns/op 928 B/op 16 allocs/op +BenchmarkEcho_ParseAll 200000 11824 ns/op 832 B/op 26 allocs/op +BenchmarkGin_ParseAll 300000 4199 ns/op 0 B/op 0 allocs/op +BenchmarkGocraftWeb_ParseAll 30000 51758 ns/op 13728 B/op 181 allocs/op +BenchmarkGoji_ParseAll 50000 29614 ns/op 5376 B/op 32 allocs/op +BenchmarkGojiv2_ParseAll 20000 68676 ns/op 24464 B/op 199 allocs/op +BenchmarkGoJsonRest_ParseAll 20000 76135 ns/op 13866 B/op 321 allocs/op +BenchmarkGoRestful_ParseAll 5000 389487 ns/op 110928 B/op 600 allocs/op +BenchmarkGorillaMux_ParseAll 10000 221250 ns/op 24864 B/op 292 allocs/op +BenchmarkHttpRouter_ParseAll 200000 6444 ns/op 640 B/op 16 allocs/op +BenchmarkHttpTreeMux_ParseAll 50000 30702 ns/op 5728 B/op 51 allocs/op +BenchmarkKocha_ParseAll 200000 13712 ns/op 1112 B/op 54 allocs/op +BenchmarkLARS_ParseAll 300000 6925 ns/op 0 B/op 0 allocs/op +BenchmarkMacaron_ParseAll 20000 96278 ns/op 24576 B/op 250 allocs/op +BenchmarkMartini_ParseAll 5000 271352 ns/op 25072 B/op 253 allocs/op +BenchmarkPat_ParseAll 20000 74941 ns/op 17264 B/op 343 allocs/op +BenchmarkPossum_ParseAll 50000 39947 ns/op 10816 B/op 78 allocs/op +BenchmarkR2router_ParseAll 50000 42479 ns/op 8352 B/op 120 allocs/op +BenchmarkRivet_ParseAll 200000 7726 ns/op 912 B/op 16 allocs/op +BenchmarkTango_ParseAll 30000 50014 ns/op 7168 B/op 208 allocs/op +BenchmarkTigerTonic_ParseAll 10000 106550 ns/op 19728 B/op 379 allocs/op +BenchmarkTraffic_ParseAll 10000 216037 ns/op 57776 B/op 642 allocs/op +BenchmarkVulcan_ParseAll 50000 34379 ns/op 2548 B/op 78 allocs/op +``` diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/CHANGELOG.md b/go/src/themaru/vendor/github.com/gin-gonic/gin/CHANGELOG.md new file mode 100644 index 0000000..8ea2495 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/CHANGELOG.md @@ -0,0 +1,269 @@ + +### Gin 1.4.0 + +- [NEW] Support for [Go Modules](https://github.com/golang/go/wiki/Modules) [#1569](https://github.com/gin-gonic/gin/pull/1569) +- [NEW] Refactor of form mapping multipart requesta [#1829](https://github.com/gin-gonic/gin/pull/1829) +- [FIX] Truncate Latency precision in long running request [#1830](https://github.com/gin-gonic/gin/pull/1830) +- [FIX] IsTerm flag should not be affected by DisableConsoleColor method. [#1802](https://github.com/gin-gonic/gin/pull/1802) +- [NEW] Supporting file binding [#1264](https://github.com/gin-gonic/gin/pull/1264) +- [NEW] Add support for mapping arrays [#1797](https://github.com/gin-gonic/gin/pull/1797) +- [FIX] Readme updates [#1793](https://github.com/gin-gonic/gin/pull/1793) [#1788](https://github.com/gin-gonic/gin/pull/1788) [1789](https://github.com/gin-gonic/gin/pull/1789) +- [FIX] StaticFS: Fixed Logging two log lines on 404. [#1805](https://github.com/gin-gonic/gin/pull/1805), [#1804](https://github.com/gin-gonic/gin/pull/1804) +- [NEW] Make context.Keys available as LogFormatterParams [#1779](https://github.com/gin-gonic/gin/pull/1779) +- [NEW] Use internal/json for Marshal/Unmarshal [#1791](https://github.com/gin-gonic/gin/pull/1791) +- [NEW] Support mapping time.Duration [#1794](https://github.com/gin-gonic/gin/pull/1794) +- [NEW] Refactor form mappings [#1749](https://github.com/gin-gonic/gin/pull/1749) +- [NEW] Added flag to context.Stream indicates if client disconnected in middle of stream [#1252](https://github.com/gin-gonic/gin/pull/1252) +- [FIX] Moved [examples](https://github.com/gin-gonic/examples) to stand alone Repo [#1775](https://github.com/gin-gonic/gin/pull/1775) +- [NEW] Extend context.File to allow for the content-dispositon attachments via a new method context.Attachment [#1260](https://github.com/gin-gonic/gin/pull/1260) +- [FIX] Support HTTP content negotiation wildcards [#1112](https://github.com/gin-gonic/gin/pull/1112) +- [NEW] Add prefix from X-Forwarded-Prefix in redirectTrailingSlash [#1238](https://github.com/gin-gonic/gin/pull/1238) +- [FIX] context.Copy() race condition [#1020](https://github.com/gin-gonic/gin/pull/1020) +- [NEW] Add context.HandlerNames() [#1729](https://github.com/gin-gonic/gin/pull/1729) +- [FIX] Change color methods to public in the defaultLogger. [#1771](https://github.com/gin-gonic/gin/pull/1771) +- [FIX] Update writeHeaders method to use http.Header.Set [#1722](https://github.com/gin-gonic/gin/pull/1722) +- [NEW] Add response size to LogFormatterParams [#1752](https://github.com/gin-gonic/gin/pull/1752) +- [NEW] Allow ignoring field on form mapping [#1733](https://github.com/gin-gonic/gin/pull/1733) +- [NEW] Add a function to force color in console output. [#1724](https://github.com/gin-gonic/gin/pull/1724) +- [FIX] Context.Next() - recheck len of handlers on every iteration. [#1745](https://github.com/gin-gonic/gin/pull/1745) +- [FIX] Fix all errcheck warnings [#1739](https://github.com/gin-gonic/gin/pull/1739) [#1653](https://github.com/gin-gonic/gin/pull/1653) +- [NEW] context: inherits context cancellation and deadline from http.Request context for Go>=1.7 [#1690](https://github.com/gin-gonic/gin/pull/1690) +- [NEW] Binding for URL Params [#1694](https://github.com/gin-gonic/gin/pull/1694) +- [NEW] Add LoggerWithFormatter method [#1677](https://github.com/gin-gonic/gin/pull/1677) +- [FIX] CI testing updates [#1671](https://github.com/gin-gonic/gin/pull/1671) [#1670](https://github.com/gin-gonic/gin/pull/1670) [#1682](https://github.com/gin-gonic/gin/pull/1682) [#1669](https://github.com/gin-gonic/gin/pull/1669) +- [FIX] StaticFS(): Send 404 when path does not exist [#1663](https://github.com/gin-gonic/gin/pull/1663) +- [FIX] Handle nil body for JSON binding [#1638](https://github.com/gin-gonic/gin/pull/1638) +- [FIX] Support bind uri param [#1612](https://github.com/gin-gonic/gin/pull/1612) +- [FIX] recovery: fix issue with syscall import on google app engine [#1640](https://github.com/gin-gonic/gin/pull/1640) +- [FIX] Make sure the debug log contains line breaks [#1650](https://github.com/gin-gonic/gin/pull/1650) +- [FIX] Panic stack trace being printed during recovery of broken pipe [#1089](https://github.com/gin-gonic/gin/pull/1089) [#1259](https://github.com/gin-gonic/gin/pull/1259) +- [NEW] RunFd method to run http.Server through a file descriptor [#1609](https://github.com/gin-gonic/gin/pull/1609) +- [NEW] Yaml binding support [#1618](https://github.com/gin-gonic/gin/pull/1618) +- [FIX] Pass MaxMultipartMemory when FormFile is called [#1600](https://github.com/gin-gonic/gin/pull/1600) +- [FIX] LoadHTML* tests [#1559](https://github.com/gin-gonic/gin/pull/1559) +- [FIX] Removed use of sync.pool from HandleContext [#1565](https://github.com/gin-gonic/gin/pull/1565) +- [FIX] Format output log to os.Stderr [#1571](https://github.com/gin-gonic/gin/pull/1571) +- [FIX] Make logger use a yellow background and a darkgray text for legibility [#1570](https://github.com/gin-gonic/gin/pull/1570) +- [FIX] Remove sensitive request information from panic log. [#1370](https://github.com/gin-gonic/gin/pull/1370) +- [FIX] log.Println() does not print timestamp [#829](https://github.com/gin-gonic/gin/pull/829) [#1560](https://github.com/gin-gonic/gin/pull/1560) +- [NEW] Add PureJSON renderer [#694](https://github.com/gin-gonic/gin/pull/694) +- [FIX] Add missing copyright and update if/else [#1497](https://github.com/gin-gonic/gin/pull/1497) +- [FIX] Update msgpack usage [#1498](https://github.com/gin-gonic/gin/pull/1498) +- [FIX] Use protobuf on render [#1496](https://github.com/gin-gonic/gin/pull/1496) +- [FIX] Add support for Protobuf format response [#1479](https://github.com/gin-gonic/gin/pull/1479) +- [NEW] Set default time format in form binding [#1487](https://github.com/gin-gonic/gin/pull/1487) +- [FIX] Add BindXML and ShouldBindXML [#1485](https://github.com/gin-gonic/gin/pull/1485) +- [NEW] Upgrade dependency libraries [#1491](https://github.com/gin-gonic/gin/pull/1491) + + +### Gin 1.3.0 + +- [NEW] Add [`func (*Context) QueryMap`](https://godoc.org/github.com/gin-gonic/gin#Context.QueryMap), [`func (*Context) GetQueryMap`](https://godoc.org/github.com/gin-gonic/gin#Context.GetQueryMap), [`func (*Context) PostFormMap`](https://godoc.org/github.com/gin-gonic/gin#Context.PostFormMap) and [`func (*Context) GetPostFormMap`](https://godoc.org/github.com/gin-gonic/gin#Context.GetPostFormMap) to support `type map[string]string` as query string or form parameters, see [#1383](https://github.com/gin-gonic/gin/pull/1383) +- [NEW] Add [`func (*Context) AsciiJSON`](https://godoc.org/github.com/gin-gonic/gin#Context.AsciiJSON), see [#1358](https://github.com/gin-gonic/gin/pull/1358) +- [NEW] Add `Pusher()` in [`type ResponseWriter`](https://godoc.org/github.com/gin-gonic/gin#ResponseWriter) for supporting http2 push, see [#1273](https://github.com/gin-gonic/gin/pull/1273) +- [NEW] Add [`func (*Context) DataFromReader`](https://godoc.org/github.com/gin-gonic/gin#Context.DataFromReader) for serving dynamic data, see [#1304](https://github.com/gin-gonic/gin/pull/1304) +- [NEW] Add [`func (*Context) ShouldBindBodyWith`](https://godoc.org/github.com/gin-gonic/gin#Context.ShouldBindBodyWith) allowing to call binding multiple times, see [#1341](https://github.com/gin-gonic/gin/pull/1341) +- [NEW] Support pointers in form binding, see [#1336](https://github.com/gin-gonic/gin/pull/1336) +- [NEW] Add [`func (*Context) JSONP`](https://godoc.org/github.com/gin-gonic/gin#Context.JSONP), see [#1333](https://github.com/gin-gonic/gin/pull/1333) +- [NEW] Support default value in form binding, see [#1138](https://github.com/gin-gonic/gin/pull/1138) +- [NEW] Expose validator engine in [`type StructValidator`](https://godoc.org/github.com/gin-gonic/gin/binding#StructValidator), see [#1277](https://github.com/gin-gonic/gin/pull/1277) +- [NEW] Add [`func (*Context) ShouldBind`](https://godoc.org/github.com/gin-gonic/gin#Context.ShouldBind), [`func (*Context) ShouldBindQuery`](https://godoc.org/github.com/gin-gonic/gin#Context.ShouldBindQuery) and [`func (*Context) ShouldBindJSON`](https://godoc.org/github.com/gin-gonic/gin#Context.ShouldBindJSON), see [#1047](https://github.com/gin-gonic/gin/pull/1047) +- [NEW] Add support for `time.Time` location in form binding, see [#1117](https://github.com/gin-gonic/gin/pull/1117) +- [NEW] Add [`func (*Context) BindQuery`](https://godoc.org/github.com/gin-gonic/gin#Context.BindQuery), see [#1029](https://github.com/gin-gonic/gin/pull/1029) +- [NEW] Make [jsonite](https://github.com/json-iterator/go) optional with build tags, see [#1026](https://github.com/gin-gonic/gin/pull/1026) +- [NEW] Show query string in logger, see [#999](https://github.com/gin-gonic/gin/pull/999) +- [NEW] Add [`func (*Context) SecureJSON`](https://godoc.org/github.com/gin-gonic/gin#Context.SecureJSON), see [#987](https://github.com/gin-gonic/gin/pull/987) and [#993](https://github.com/gin-gonic/gin/pull/993) +- [DEPRECATE] `func (*Context) GetCookie` for [`func (*Context) Cookie`](https://godoc.org/github.com/gin-gonic/gin#Context.Cookie) +- [FIX] Don't display color tags if [`func DisableConsoleColor`](https://godoc.org/github.com/gin-gonic/gin#DisableConsoleColor) called, see [#1072](https://github.com/gin-gonic/gin/pull/1072) +- [FIX] Gin Mode `""` when calling [`func Mode`](https://godoc.org/github.com/gin-gonic/gin#Mode) now returns `const DebugMode`, see [#1250](https://github.com/gin-gonic/gin/pull/1250) +- [FIX] `Flush()` now doesn't overwrite `responseWriter` status code, see [#1460](https://github.com/gin-gonic/gin/pull/1460) + +### Gin 1.2.0 + +- [NEW] Switch from godeps to govendor +- [NEW] Add support for Let's Encrypt via gin-gonic/autotls +- [NEW] Improve README examples and add extra at examples folder +- [NEW] Improved support with App Engine +- [NEW] Add custom template delimiters, see #860 +- [NEW] Add Template Func Maps, see #962 +- [NEW] Add \*context.Handler(), see #928 +- [NEW] Add \*context.GetRawData() +- [NEW] Add \*context.GetHeader() (request) +- [NEW] Add \*context.AbortWithStatusJSON() (JSON content type) +- [NEW] Add \*context.Keys type cast helpers +- [NEW] Add \*context.ShouldBindWith() +- [NEW] Add \*context.MustBindWith() +- [NEW] Add \*engine.SetFuncMap() +- [DEPRECATE] On next release: \*context.BindWith(), see #855 +- [FIX] Refactor render +- [FIX] Reworked tests +- [FIX] logger now supports cygwin +- [FIX] Use X-Forwarded-For before X-Real-Ip +- [FIX] time.Time binding (#904) + +### Gin 1.1.4 + +- [NEW] Support google appengine for IsTerminal func + +### Gin 1.1.3 + +- [FIX] Reverted Logger: skip ANSI color commands + +### Gin 1.1 + +- [NEW] Implement QueryArray and PostArray methods +- [NEW] Refactor GetQuery and GetPostForm +- [NEW] Add contribution guide +- [FIX] Corrected typos in README +- [FIX] Removed additional Iota +- [FIX] Changed imports to gopkg instead of github in README (#733) +- [FIX] Logger: skip ANSI color commands if output is not a tty + +### Gin 1.0rc2 (...) + +- [PERFORMANCE] Fast path for writing Content-Type. +- [PERFORMANCE] Much faster 404 routing +- [PERFORMANCE] Allocation optimizations +- [PERFORMANCE] Faster root tree lookup +- [PERFORMANCE] Zero overhead, String() and JSON() rendering. +- [PERFORMANCE] Faster ClientIP parsing +- [PERFORMANCE] Much faster SSE implementation +- [NEW] Benchmarks suite +- [NEW] Bind validation can be disabled and replaced with custom validators. +- [NEW] More flexible HTML render +- [NEW] Multipart and PostForm bindings +- [NEW] Adds method to return all the registered routes +- [NEW] Context.HandlerName() returns the main handler's name +- [NEW] Adds Error.IsType() helper +- [FIX] Binding multipart form +- [FIX] Integration tests +- [FIX] Crash when binding non struct object in Context. +- [FIX] RunTLS() implementation +- [FIX] Logger() unit tests +- [FIX] Adds SetHTMLTemplate() warning +- [FIX] Context.IsAborted() +- [FIX] More unit tests +- [FIX] JSON, XML, HTML renders accept custom content-types +- [FIX] gin.AbortIndex is unexported +- [FIX] Better approach to avoid directory listing in StaticFS() +- [FIX] Context.ClientIP() always returns the IP with trimmed spaces. +- [FIX] Better warning when running in debug mode. +- [FIX] Google App Engine integration. debugPrint does not use os.Stdout +- [FIX] Fixes integer overflow in error type +- [FIX] Error implements the json.Marshaller interface +- [FIX] MIT license in every file + + +### Gin 1.0rc1 (May 22, 2015) + +- [PERFORMANCE] Zero allocation router +- [PERFORMANCE] Faster JSON, XML and text rendering +- [PERFORMANCE] Custom hand optimized HttpRouter for Gin +- [PERFORMANCE] Misc code optimizations. Inlining, tail call optimizations +- [NEW] Built-in support for golang.org/x/net/context +- [NEW] Any(path, handler). Create a route that matches any path +- [NEW] Refactored rendering pipeline (faster and static typeded) +- [NEW] Refactored errors API +- [NEW] IndentedJSON() prints pretty JSON +- [NEW] Added gin.DefaultWriter +- [NEW] UNIX socket support +- [NEW] RouterGroup.BasePath is exposed +- [NEW] JSON validation using go-validate-yourself (very powerful options) +- [NEW] Completed suite of unit tests +- [NEW] HTTP streaming with c.Stream() +- [NEW] StaticFile() creates a router for serving just one file. +- [NEW] StaticFS() has an option to disable directory listing. +- [NEW] StaticFS() for serving static files through virtual filesystems +- [NEW] Server-Sent Events native support +- [NEW] WrapF() and WrapH() helpers for wrapping http.HandlerFunc and http.Handler +- [NEW] Added LoggerWithWriter() middleware +- [NEW] Added RecoveryWithWriter() middleware +- [NEW] Added DefaultPostFormValue() +- [NEW] Added DefaultFormValue() +- [NEW] Added DefaultParamValue() +- [FIX] BasicAuth() when using custom realm +- [FIX] Bug when serving static files in nested routing group +- [FIX] Redirect using built-in http.Redirect() +- [FIX] Logger when printing the requested path +- [FIX] Documentation typos +- [FIX] Context.Engine renamed to Context.engine +- [FIX] Better debugging messages +- [FIX] ErrorLogger +- [FIX] Debug HTTP render +- [FIX] Refactored binding and render modules +- [FIX] Refactored Context initialization +- [FIX] Refactored BasicAuth() +- [FIX] NoMethod/NoRoute handlers +- [FIX] Hijacking http +- [FIX] Better support for Google App Engine (using log instead of fmt) + + +### Gin 0.6 (Mar 9, 2015) + +- [NEW] Support multipart/form-data +- [NEW] NoMethod handler +- [NEW] Validate sub structures +- [NEW] Support for HTTP Realm Auth +- [FIX] Unsigned integers in binding +- [FIX] Improve color logger + + +### Gin 0.5 (Feb 7, 2015) + +- [NEW] Content Negotiation +- [FIX] Solved security bug that allow a client to spoof ip +- [FIX] Fix unexported/ignored fields in binding + + +### Gin 0.4 (Aug 21, 2014) + +- [NEW] Development mode +- [NEW] Unit tests +- [NEW] Add Content.Redirect() +- [FIX] Deferring WriteHeader() +- [FIX] Improved documentation for model binding + + +### Gin 0.3 (Jul 18, 2014) + +- [PERFORMANCE] Normal log and error log are printed in the same call. +- [PERFORMANCE] Improve performance of NoRouter() +- [PERFORMANCE] Improve context's memory locality, reduce CPU cache faults. +- [NEW] Flexible rendering API +- [NEW] Add Context.File() +- [NEW] Add shorcut RunTLS() for http.ListenAndServeTLS +- [FIX] Rename NotFound404() to NoRoute() +- [FIX] Errors in context are purged +- [FIX] Adds HEAD method in Static file serving +- [FIX] Refactors Static() file serving +- [FIX] Using keyed initialization to fix app-engine integration +- [FIX] Can't unmarshal JSON array, #63 +- [FIX] Renaming Context.Req to Context.Request +- [FIX] Check application/x-www-form-urlencoded when parsing form + + +### Gin 0.2b (Jul 08, 2014) +- [PERFORMANCE] Using sync.Pool to allocatio/gc overhead +- [NEW] Travis CI integration +- [NEW] Completely new logger +- [NEW] New API for serving static files. gin.Static() +- [NEW] gin.H() can be serialized into XML +- [NEW] Typed errors. Errors can be typed. Internet/external/custom. +- [NEW] Support for Godeps +- [NEW] Travis/Godocs badges in README +- [NEW] New Bind() and BindWith() methods for parsing request body. +- [NEW] Add Content.Copy() +- [NEW] Add context.LastError() +- [NEW] Add shorcut for OPTIONS HTTP method +- [FIX] Tons of README fixes +- [FIX] Header is written before body +- [FIX] BasicAuth() and changes API a little bit +- [FIX] Recovery() middleware only prints panics +- [FIX] Context.Get() does not panic anymore. Use MustGet() instead. +- [FIX] Multiple http.WriteHeader() in NotFound handlers +- [FIX] Engine.Run() panics if http server can't be setted up +- [FIX] Crash when route path doesn't start with '/' +- [FIX] Do not update header when status code is negative +- [FIX] Setting response headers before calling WriteHeader in context.String() +- [FIX] Add MIT license +- [FIX] Changes behaviour of ErrorLogger() and Logger() diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/CODE_OF_CONDUCT.md b/go/src/themaru/vendor/github.com/gin-gonic/gin/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..4ea14f3 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at teamgingonic@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/CONTRIBUTING.md b/go/src/themaru/vendor/github.com/gin-gonic/gin/CONTRIBUTING.md new file mode 100644 index 0000000..547b777 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/CONTRIBUTING.md @@ -0,0 +1,13 @@ +## Contributing + +- With issues: + - Use the search tool before opening a new issue. + - Please provide source code and commit sha if you found a bug. + - Review existing issues and provide feedback or react to them. + +- With pull requests: + - Open your pull request against `master` + - Your pull request should have no more than two commits, if not you should squash them. + - It should pass all tests in the available continuous integrations systems such as TravisCI. + - You should add/modify tests to cover your proposed code changes. + - If your pull request contains a new feature, please document it on the README. diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/LICENSE b/go/src/themaru/vendor/github.com/gin-gonic/gin/LICENSE new file mode 100644 index 0000000..1ff7f37 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Manuel Martínez-Almeida + +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. diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/Makefile b/go/src/themaru/vendor/github.com/gin-gonic/gin/Makefile new file mode 100644 index 0000000..51a6b91 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/Makefile @@ -0,0 +1,80 @@ +GO ?= go +GOFMT ?= gofmt "-s" +PACKAGES ?= $(shell $(GO) list ./... | grep -v /vendor/) +VETPACKAGES ?= $(shell $(GO) list ./... | grep -v /vendor/ | grep -v /examples/) +GOFILES := $(shell find . -name "*.go" -type f -not -path "./vendor/*") +TESTFOLDER := $(shell $(GO) list ./... | grep -E 'gin$$|binding$$|render$$' | grep -v examples) + +all: install + +install: deps + govendor sync + +.PHONY: test +test: + echo "mode: count" > coverage.out + for d in $(TESTFOLDER); do \ + $(GO) test -v -covermode=count -coverprofile=profile.out $$d > tmp.out; \ + cat tmp.out; \ + if grep -q "^--- FAIL" tmp.out; then \ + rm tmp.out; \ + exit 1; \ + elif grep -q "build failed" tmp.out; then \ + rm tmp.out; \ + exit 1; \ + elif grep -q "setup failed" tmp.out; then \ + rm tmp.out; \ + exit 1; \ + fi; \ + if [ -f profile.out ]; then \ + cat profile.out | grep -v "mode:" >> coverage.out; \ + rm profile.out; \ + fi; \ + done + +.PHONY: fmt +fmt: + $(GOFMT) -w $(GOFILES) + +.PHONY: fmt-check +fmt-check: + @diff=$$($(GOFMT) -d $(GOFILES)); \ + if [ -n "$$diff" ]; then \ + echo "Please run 'make fmt' and commit the result:"; \ + echo "$${diff}"; \ + exit 1; \ + fi; + +vet: + $(GO) vet $(VETPACKAGES) + +deps: + @hash govendor > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + $(GO) get -u github.com/kardianos/govendor; \ + fi + +.PHONY: lint +lint: + @hash golint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + $(GO) get -u golang.org/x/lint/golint; \ + fi + for PKG in $(PACKAGES); do golint -set_exit_status $$PKG || exit 1; done; + +.PHONY: misspell-check +misspell-check: + @hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + $(GO) get -u github.com/client9/misspell/cmd/misspell; \ + fi + misspell -error $(GOFILES) + +.PHONY: misspell +misspell: + @hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + $(GO) get -u github.com/client9/misspell/cmd/misspell; \ + fi + misspell -w $(GOFILES) + +.PHONY: tools +tools: + go install golang.org/x/lint/golint; \ + go install github.com/client9/misspell/cmd/misspell; diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/README.md b/go/src/themaru/vendor/github.com/gin-gonic/gin/README.md new file mode 100644 index 0000000..3e817a7 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/README.md @@ -0,0 +1,2070 @@ +# Gin Web Framework + + + +[![Build Status](https://travis-ci.org/gin-gonic/gin.svg)](https://travis-ci.org/gin-gonic/gin) +[![codecov](https://codecov.io/gh/gin-gonic/gin/branch/master/graph/badge.svg)](https://codecov.io/gh/gin-gonic/gin) +[![Go Report Card](https://goreportcard.com/badge/github.com/gin-gonic/gin)](https://goreportcard.com/report/github.com/gin-gonic/gin) +[![GoDoc](https://godoc.org/github.com/gin-gonic/gin?status.svg)](https://godoc.org/github.com/gin-gonic/gin) +[![Join the chat at https://gitter.im/gin-gonic/gin](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/gin-gonic/gin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Sourcegraph](https://sourcegraph.com/github.com/gin-gonic/gin/-/badge.svg)](https://sourcegraph.com/github.com/gin-gonic/gin?badge) +[![Open Source Helpers](https://www.codetriage.com/gin-gonic/gin/badges/users.svg)](https://www.codetriage.com/gin-gonic/gin) +[![Release](https://img.shields.io/github/release/gin-gonic/gin.svg?style=flat-square)](https://github.com/gin-gonic/gin/releases) + +Gin is a web framework written in Go (Golang). It features a martini-like API with much better performance, up to 40 times faster thanks to [httprouter](https://github.com/julienschmidt/httprouter). If you need performance and good productivity, you will love Gin. + + +## Contents + +- [Installation](#installation) +- [Prerequisite](#prerequisite) +- [Quick start](#quick-start) +- [Benchmarks](#benchmarks) +- [Gin v1.stable](#gin-v1-stable) +- [Build with jsoniter](#build-with-jsoniter) +- [API Examples](#api-examples) + - [Using GET,POST,PUT,PATCH,DELETE and OPTIONS](#using-get-post-put-patch-delete-and-options) + - [Parameters in path](#parameters-in-path) + - [Querystring parameters](#querystring-parameters) + - [Multipart/Urlencoded Form](#multiparturlencoded-form) + - [Another example: query + post form](#another-example-query--post-form) + - [Map as querystring or postform parameters](#map-as-querystring-or-postform-parameters) + - [Upload files](#upload-files) + - [Grouping routes](#grouping-routes) + - [Blank Gin without middleware by default](#blank-gin-without-middleware-by-default) + - [Using middleware](#using-middleware) + - [How to write log file](#how-to-write-log-file) + - [Custom Log Format](#custom-log-format) + - [Model binding and validation](#model-binding-and-validation) + - [Custom Validators](#custom-validators) + - [Only Bind Query String](#only-bind-query-string) + - [Bind Query String or Post Data](#bind-query-string-or-post-data) + - [Bind Uri](#bind-uri) + - [Bind HTML checkboxes](#bind-html-checkboxes) + - [Multipart/Urlencoded binding](#multiparturlencoded-binding) + - [XML, JSON, YAML and ProtoBuf rendering](#xml-json-yaml-and-protobuf-rendering) + - [JSONP rendering](#jsonp) + - [Serving static files](#serving-static-files) + - [Serving data from reader](#serving-data-from-reader) + - [HTML rendering](#html-rendering) + - [Multitemplate](#multitemplate) + - [Redirects](#redirects) + - [Custom Middleware](#custom-middleware) + - [Using BasicAuth() middleware](#using-basicauth-middleware) + - [Goroutines inside a middleware](#goroutines-inside-a-middleware) + - [Custom HTTP configuration](#custom-http-configuration) + - [Support Let's Encrypt](#support-lets-encrypt) + - [Run multiple service using Gin](#run-multiple-service-using-gin) + - [Graceful restart or stop](#graceful-restart-or-stop) + - [Build a single binary with templates](#build-a-single-binary-with-templates) + - [Bind form-data request with custom struct](#bind-form-data-request-with-custom-struct) + - [Try to bind body into different structs](#try-to-bind-body-into-different-structs) + - [http2 server push](#http2-server-push) + - [Define format for the log of routes](#define-format-for-the-log-of-routes) + - [Set and get a cookie](#set-and-get-a-cookie) +- [Testing](#testing) +- [Users](#users) + +## Installation + +To install Gin package, you need to install Go and set your Go workspace first. + +1. The first need [Go](https://golang.org/) installed (**version 1.8+ is required**), then you can use the below Go command to install Gin. + +```sh +$ go get -u github.com/gin-gonic/gin +``` + +2. Import it in your code: + +```go +import "github.com/gin-gonic/gin" +``` + +3. (Optional) Import `net/http`. This is required for example if using constants such as `http.StatusOK`. + +```go +import "net/http" +``` + +### Use a vendor tool like [Govendor](https://github.com/kardianos/govendor) + +1. `go get` govendor + +```sh +$ go get github.com/kardianos/govendor +``` +2. Create your project folder and `cd` inside + +```sh +$ mkdir -p $GOPATH/src/github.com/myusername/project && cd "$_" +``` + +3. Vendor init your project and add gin + +```sh +$ govendor init +$ govendor fetch github.com/gin-gonic/gin@v1.3 +``` + +4. Copy a starting template inside your project + +```sh +$ curl https://raw.githubusercontent.com/gin-gonic/examples/master/basic/main.go > main.go +``` + +5. Run your project + +```sh +$ go run main.go +``` + +## Prerequisite + +Now Gin requires Go 1.6 or later and Go 1.7 will be required soon. + +## Quick start + +```sh +# assume the following codes in example.go file +$ cat example.go +``` + +```go +package main + +import "github.com/gin-gonic/gin" + +func main() { + r := gin.Default() + r.GET("/ping", func(c *gin.Context) { + c.JSON(200, gin.H{ + "message": "pong", + }) + }) + r.Run() // listen and serve on 0.0.0.0:8080 +} +``` + +``` +# run example.go and visit 0.0.0.0:8080/ping on browser +$ go run example.go +``` + +## Benchmarks + +Gin uses a custom version of [HttpRouter](https://github.com/julienschmidt/httprouter) + +[See all benchmarks](/BENCHMARKS.md) + +Benchmark name | (1) | (2) | (3) | (4) +--------------------------------------------|-----------:|------------:|-----------:|---------: +**BenchmarkGin_GithubAll** | **30000** | **48375** | **0** | **0** +BenchmarkAce_GithubAll | 10000 | 134059 | 13792 | 167 +BenchmarkBear_GithubAll | 5000 | 534445 | 86448 | 943 +BenchmarkBeego_GithubAll | 3000 | 592444 | 74705 | 812 +BenchmarkBone_GithubAll | 200 | 6957308 | 698784 | 8453 +BenchmarkDenco_GithubAll | 10000 | 158819 | 20224 | 167 +BenchmarkEcho_GithubAll | 10000 | 154700 | 6496 | 203 +BenchmarkGocraftWeb_GithubAll | 3000 | 570806 | 131656 | 1686 +BenchmarkGoji_GithubAll | 2000 | 818034 | 56112 | 334 +BenchmarkGojiv2_GithubAll | 2000 | 1213973 | 274768 | 3712 +BenchmarkGoJsonRest_GithubAll | 2000 | 785796 | 134371 | 2737 +BenchmarkGoRestful_GithubAll | 300 | 5238188 | 689672 | 4519 +BenchmarkGorillaMux_GithubAll | 100 | 10257726 | 211840 | 2272 +BenchmarkHttpRouter_GithubAll | 20000 | 105414 | 13792 | 167 +BenchmarkHttpTreeMux_GithubAll | 10000 | 319934 | 65856 | 671 +BenchmarkKocha_GithubAll | 10000 | 209442 | 23304 | 843 +BenchmarkLARS_GithubAll | 20000 | 62565 | 0 | 0 +BenchmarkMacaron_GithubAll | 2000 | 1161270 | 204194 | 2000 +BenchmarkMartini_GithubAll | 200 | 9991713 | 226549 | 2325 +BenchmarkPat_GithubAll | 200 | 5590793 | 1499568 | 27435 +BenchmarkPossum_GithubAll | 10000 | 319768 | 84448 | 609 +BenchmarkR2router_GithubAll | 10000 | 305134 | 77328 | 979 +BenchmarkRivet_GithubAll | 10000 | 132134 | 16272 | 167 +BenchmarkTango_GithubAll | 3000 | 552754 | 63826 | 1618 +BenchmarkTigerTonic_GithubAll | 1000 | 1439483 | 239104 | 5374 +BenchmarkTraffic_GithubAll | 100 | 11383067 | 2659329 | 21848 +BenchmarkVulcan_GithubAll | 5000 | 394253 | 19894 | 609 + +- (1): Total Repetitions achieved in constant time, higher means more confident result +- (2): Single Repetition Duration (ns/op), lower is better +- (3): Heap Memory (B/op), lower is better +- (4): Average Allocations per Repetition (allocs/op), lower is better + +## Gin v1. stable + +- [x] Zero allocation router. +- [x] Still the fastest http router and framework. From routing to writing. +- [x] Complete suite of unit tests +- [x] Battle tested +- [x] API frozen, new releases will not break your code. + +## Build with [jsoniter](https://github.com/json-iterator/go) + +Gin uses `encoding/json` as default json package but you can change to [jsoniter](https://github.com/json-iterator/go) by build from other tags. + +```sh +$ go build -tags=jsoniter . +``` + +## API Examples + +You can find a number of ready-to-run examples at [Gin examples repository](https://github.com/gin-gonic/examples). + +### Using GET, POST, PUT, PATCH, DELETE and OPTIONS + +```go +func main() { + // Creates a gin router with default middleware: + // logger and recovery (crash-free) middleware + router := gin.Default() + + router.GET("/someGet", getting) + router.POST("/somePost", posting) + router.PUT("/somePut", putting) + router.DELETE("/someDelete", deleting) + router.PATCH("/somePatch", patching) + router.HEAD("/someHead", head) + router.OPTIONS("/someOptions", options) + + // By default it serves on :8080 unless a + // PORT environment variable was defined. + router.Run() + // router.Run(":3000") for a hard coded port +} +``` + +### Parameters in path + +```go +func main() { + router := gin.Default() + + // This handler will match /user/john but will not match /user/ or /user + router.GET("/user/:name", func(c *gin.Context) { + name := c.Param("name") + c.String(http.StatusOK, "Hello %s", name) + }) + + // However, this one will match /user/john/ and also /user/john/send + // If no other routers match /user/john, it will redirect to /user/john/ + router.GET("/user/:name/*action", func(c *gin.Context) { + name := c.Param("name") + action := c.Param("action") + message := name + " is " + action + c.String(http.StatusOK, message) + }) + + router.Run(":8080") +} +``` + +### Querystring parameters + +```go +func main() { + router := gin.Default() + + // Query string parameters are parsed using the existing underlying request object. + // The request responds to a url matching: /welcome?firstname=Jane&lastname=Doe + router.GET("/welcome", func(c *gin.Context) { + firstname := c.DefaultQuery("firstname", "Guest") + lastname := c.Query("lastname") // shortcut for c.Request.URL.Query().Get("lastname") + + c.String(http.StatusOK, "Hello %s %s", firstname, lastname) + }) + router.Run(":8080") +} +``` + +### Multipart/Urlencoded Form + +```go +func main() { + router := gin.Default() + + router.POST("/form_post", func(c *gin.Context) { + message := c.PostForm("message") + nick := c.DefaultPostForm("nick", "anonymous") + + c.JSON(200, gin.H{ + "status": "posted", + "message": message, + "nick": nick, + }) + }) + router.Run(":8080") +} +``` + +### Another example: query + post form + +``` +POST /post?id=1234&page=1 HTTP/1.1 +Content-Type: application/x-www-form-urlencoded + +name=manu&message=this_is_great +``` + +```go +func main() { + router := gin.Default() + + router.POST("/post", func(c *gin.Context) { + + id := c.Query("id") + page := c.DefaultQuery("page", "0") + name := c.PostForm("name") + message := c.PostForm("message") + + fmt.Printf("id: %s; page: %s; name: %s; message: %s", id, page, name, message) + }) + router.Run(":8080") +} +``` + +``` +id: 1234; page: 1; name: manu; message: this_is_great +``` + +### Map as querystring or postform parameters + +``` +POST /post?ids[a]=1234&ids[b]=hello HTTP/1.1 +Content-Type: application/x-www-form-urlencoded + +names[first]=thinkerou&names[second]=tianou +``` + +```go +func main() { + router := gin.Default() + + router.POST("/post", func(c *gin.Context) { + + ids := c.QueryMap("ids") + names := c.PostFormMap("names") + + fmt.Printf("ids: %v; names: %v", ids, names) + }) + router.Run(":8080") +} +``` + +``` +ids: map[b:hello a:1234], names: map[second:tianou first:thinkerou] +``` + +### Upload files + +#### Single file + +References issue [#774](https://github.com/gin-gonic/gin/issues/774) and detail [example code](https://github.com/gin-gonic/examples/tree/master/upload-file/single). + +`file.Filename` **SHOULD NOT** be trusted. See [`Content-Disposition` on MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#Directives) and [#1693](https://github.com/gin-gonic/gin/issues/1693) + +> The filename is always optional and must not be used blindly by the application: path information should be stripped, and conversion to the server file system rules should be done. + +```go +func main() { + router := gin.Default() + // Set a lower memory limit for multipart forms (default is 32 MiB) + // router.MaxMultipartMemory = 8 << 20 // 8 MiB + router.POST("/upload", func(c *gin.Context) { + // single file + file, _ := c.FormFile("file") + log.Println(file.Filename) + + // Upload the file to specific dst. + // c.SaveUploadedFile(file, dst) + + c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename)) + }) + router.Run(":8080") +} +``` + +How to `curl`: + +```bash +curl -X POST http://localhost:8080/upload \ + -F "file=@/Users/appleboy/test.zip" \ + -H "Content-Type: multipart/form-data" +``` + +#### Multiple files + +See the detail [example code](https://github.com/gin-gonic/examples/tree/master/upload-file/multiple). + +```go +func main() { + router := gin.Default() + // Set a lower memory limit for multipart forms (default is 32 MiB) + // router.MaxMultipartMemory = 8 << 20 // 8 MiB + router.POST("/upload", func(c *gin.Context) { + // Multipart form + form, _ := c.MultipartForm() + files := form.File["upload[]"] + + for _, file := range files { + log.Println(file.Filename) + + // Upload the file to specific dst. + // c.SaveUploadedFile(file, dst) + } + c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files))) + }) + router.Run(":8080") +} +``` + +How to `curl`: + +```bash +curl -X POST http://localhost:8080/upload \ + -F "upload[]=@/Users/appleboy/test1.zip" \ + -F "upload[]=@/Users/appleboy/test2.zip" \ + -H "Content-Type: multipart/form-data" +``` + +### Grouping routes + +```go +func main() { + router := gin.Default() + + // Simple group: v1 + v1 := router.Group("/v1") + { + v1.POST("/login", loginEndpoint) + v1.POST("/submit", submitEndpoint) + v1.POST("/read", readEndpoint) + } + + // Simple group: v2 + v2 := router.Group("/v2") + { + v2.POST("/login", loginEndpoint) + v2.POST("/submit", submitEndpoint) + v2.POST("/read", readEndpoint) + } + + router.Run(":8080") +} +``` + +### Blank Gin without middleware by default + +Use + +```go +r := gin.New() +``` + +instead of + +```go +// Default With the Logger and Recovery middleware already attached +r := gin.Default() +``` + + +### Using middleware +```go +func main() { + // Creates a router without any middleware by default + r := gin.New() + + // Global middleware + // Logger middleware will write the logs to gin.DefaultWriter even if you set with GIN_MODE=release. + // By default gin.DefaultWriter = os.Stdout + r.Use(gin.Logger()) + + // Recovery middleware recovers from any panics and writes a 500 if there was one. + r.Use(gin.Recovery()) + + // Per route middleware, you can add as many as you desire. + r.GET("/benchmark", MyBenchLogger(), benchEndpoint) + + // Authorization group + // authorized := r.Group("/", AuthRequired()) + // exactly the same as: + authorized := r.Group("/") + // per group middleware! in this case we use the custom created + // AuthRequired() middleware just in the "authorized" group. + authorized.Use(AuthRequired()) + { + authorized.POST("/login", loginEndpoint) + authorized.POST("/submit", submitEndpoint) + authorized.POST("/read", readEndpoint) + + // nested group + testing := authorized.Group("testing") + testing.GET("/analytics", analyticsEndpoint) + } + + // Listen and serve on 0.0.0.0:8080 + r.Run(":8080") +} +``` + +### How to write log file +```go +func main() { + // Disable Console Color, you don't need console color when writing the logs to file. + gin.DisableConsoleColor() + + // Logging to a file. + f, _ := os.Create("gin.log") + gin.DefaultWriter = io.MultiWriter(f) + + // Use the following code if you need to write the logs to file and console at the same time. + // gin.DefaultWriter = io.MultiWriter(f, os.Stdout) + + router := gin.Default() + router.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + +    router.Run(":8080") +} +``` + +### Custom Log Format +```go +func main() { + router := gin.New() + + // LoggerWithFormatter middleware will write the logs to gin.DefaultWriter + // By default gin.DefaultWriter = os.Stdout + router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string { + + // your custom format + return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n", + param.ClientIP, + param.TimeStamp.Format(time.RFC1123), + param.Method, + param.Path, + param.Request.Proto, + param.StatusCode, + param.Latency, + param.Request.UserAgent(), + param.ErrorMessage, + ) + })) + router.Use(gin.Recovery()) + + router.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + + router.Run(":8080") +} +``` + +**Sample Output** +``` +::1 - [Fri, 07 Dec 2018 17:04:38 JST] "GET /ping HTTP/1.1 200 122.767µs "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36" " +``` + +### Controlling Log output coloring + +By default, logs output on console should be colorized depending on the detected TTY. + +Never colorize logs: + +```go +func main() { + // Disable log's color + gin.DisableConsoleColor() + + // Creates a gin router with default middleware: + // logger and recovery (crash-free) middleware + router := gin.Default() + + router.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + + router.Run(":8080") +} +``` + +Always colorize logs: + +```go +func main() { + // Force log's color + gin.ForceConsoleColor() + + // Creates a gin router with default middleware: + // logger and recovery (crash-free) middleware + router := gin.Default() + + router.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + + router.Run(":8080") +} +``` + +### Model binding and validation + +To bind a request body into a type, use model binding. We currently support binding of JSON, XML, YAML and standard form values (foo=bar&boo=baz). + +Gin uses [**go-playground/validator.v8**](https://github.com/go-playground/validator) for validation. Check the full docs on tags usage [here](http://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Baked_In_Validators_and_Tags). + +Note that you need to set the corresponding binding tag on all fields you want to bind. For example, when binding from JSON, set `json:"fieldname"`. + +Also, Gin provides two sets of methods for binding: +- **Type** - Must bind + - **Methods** - `Bind`, `BindJSON`, `BindXML`, `BindQuery`, `BindYAML` + - **Behavior** - These methods use `MustBindWith` under the hood. If there is a binding error, the request is aborted with `c.AbortWithError(400, err).SetType(ErrorTypeBind)`. This sets the response status code to 400 and the `Content-Type` header is set to `text/plain; charset=utf-8`. Note that if you try to set the response code after this, it will result in a warning `[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422`. If you wish to have greater control over the behavior, consider using the `ShouldBind` equivalent method. +- **Type** - Should bind + - **Methods** - `ShouldBind`, `ShouldBindJSON`, `ShouldBindXML`, `ShouldBindQuery`, `ShouldBindYAML` + - **Behavior** - These methods use `ShouldBindWith` under the hood. If there is a binding error, the error is returned and it is the developer's responsibility to handle the request and error appropriately. + +When using the Bind-method, Gin tries to infer the binder depending on the Content-Type header. If you are sure what you are binding, you can use `MustBindWith` or `ShouldBindWith`. + +You can also specify that specific fields are required. If a field is decorated with `binding:"required"` and has a empty value when binding, an error will be returned. + +```go +// Binding from JSON +type Login struct { + User string `form:"user" json:"user" xml:"user" binding:"required"` + Password string `form:"password" json:"password" xml:"password" binding:"required"` +} + +func main() { + router := gin.Default() + + // Example for binding JSON ({"user": "manu", "password": "123"}) + router.POST("/loginJSON", func(c *gin.Context) { + var json Login + if err := c.ShouldBindJSON(&json); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + if json.User != "manu" || json.Password != "123" { + c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"}) + return + } + + c.JSON(http.StatusOK, gin.H{"status": "you are logged in"}) + }) + + // Example for binding XML ( + // + // + // user + // 123 + // ) + router.POST("/loginXML", func(c *gin.Context) { + var xml Login + if err := c.ShouldBindXML(&xml); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + if xml.User != "manu" || xml.Password != "123" { + c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"}) + return + } + + c.JSON(http.StatusOK, gin.H{"status": "you are logged in"}) + }) + + // Example for binding a HTML form (user=manu&password=123) + router.POST("/loginForm", func(c *gin.Context) { + var form Login + // This will infer what binder to use depending on the content-type header. + if err := c.ShouldBind(&form); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + if form.User != "manu" || form.Password != "123" { + c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"}) + return + } + + c.JSON(http.StatusOK, gin.H{"status": "you are logged in"}) + }) + + // Listen and serve on 0.0.0.0:8080 + router.Run(":8080") +} +``` + +**Sample request** +```shell +$ curl -v -X POST \ + http://localhost:8080/loginJSON \ + -H 'content-type: application/json' \ + -d '{ "user": "manu" }' +> POST /loginJSON HTTP/1.1 +> Host: localhost:8080 +> User-Agent: curl/7.51.0 +> Accept: */* +> content-type: application/json +> Content-Length: 18 +> +* upload completely sent off: 18 out of 18 bytes +< HTTP/1.1 400 Bad Request +< Content-Type: application/json; charset=utf-8 +< Date: Fri, 04 Aug 2017 03:51:31 GMT +< Content-Length: 100 +< +{"error":"Key: 'Login.Password' Error:Field validation for 'Password' failed on the 'required' tag"} +``` + +**Skip validate** + +When running the above example using the above the `curl` command, it returns error. Because the example use `binding:"required"` for `Password`. If use `binding:"-"` for `Password`, then it will not return error when running the above example again. + +### Custom Validators + +It is also possible to register custom validators. See the [example code](https://github.com/gin-gonic/examples/tree/master/custom-validation/server.go). + +```go +package main + +import ( + "net/http" + "reflect" + "time" + + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "gopkg.in/go-playground/validator.v8" +) + +// Booking contains binded and validated data. +type Booking struct { + CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"` + CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"` +} + +func bookableDate( + v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value, + field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string, +) bool { + if date, ok := field.Interface().(time.Time); ok { + today := time.Now() + if today.Year() > date.Year() || today.YearDay() > date.YearDay() { + return false + } + } + return true +} + +func main() { + route := gin.Default() + + if v, ok := binding.Validator.Engine().(*validator.Validate); ok { + v.RegisterValidation("bookabledate", bookableDate) + } + + route.GET("/bookable", getBookable) + route.Run(":8085") +} + +func getBookable(c *gin.Context) { + var b Booking + if err := c.ShouldBindWith(&b, binding.Query); err == nil { + c.JSON(http.StatusOK, gin.H{"message": "Booking dates are valid!"}) + } else { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + } +} +``` + +```console +$ curl "localhost:8085/bookable?check_in=2018-04-16&check_out=2018-04-17" +{"message":"Booking dates are valid!"} + +$ curl "localhost:8085/bookable?check_in=2018-03-08&check_out=2018-03-09" +{"error":"Key: 'Booking.CheckIn' Error:Field validation for 'CheckIn' failed on the 'bookabledate' tag"} +``` + +[Struct level validations](https://github.com/go-playground/validator/releases/tag/v8.7) can also be registered this way. +See the [struct-lvl-validation example](https://github.com/gin-gonic/examples/tree/master/struct-lvl-validations) to learn more. + +### Only Bind Query String + +`ShouldBindQuery` function only binds the query params and not the post data. See the [detail information](https://github.com/gin-gonic/gin/issues/742#issuecomment-315953017). + +```go +package main + +import ( + "log" + + "github.com/gin-gonic/gin" +) + +type Person struct { + Name string `form:"name"` + Address string `form:"address"` +} + +func main() { + route := gin.Default() + route.Any("/testing", startPage) + route.Run(":8085") +} + +func startPage(c *gin.Context) { + var person Person + if c.ShouldBindQuery(&person) == nil { + log.Println("====== Only Bind By Query String ======") + log.Println(person.Name) + log.Println(person.Address) + } + c.String(200, "Success") +} + +``` + +### Bind Query String or Post Data + +See the [detail information](https://github.com/gin-gonic/gin/issues/742#issuecomment-264681292). + +```go +package main + +import ( + "log" + "time" + + "github.com/gin-gonic/gin" +) + +type Person struct { + Name string `form:"name"` + Address string `form:"address"` + Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"` +} + +func main() { + route := gin.Default() + route.GET("/testing", startPage) + route.Run(":8085") +} + +func startPage(c *gin.Context) { + var person Person + // If `GET`, only `Form` binding engine (`query`) used. + // If `POST`, first checks the `content-type` for `JSON` or `XML`, then uses `Form` (`form-data`). + // See more at https://github.com/gin-gonic/gin/blob/master/binding/binding.go#L48 + if c.ShouldBind(&person) == nil { + log.Println(person.Name) + log.Println(person.Address) + log.Println(person.Birthday) + } + + c.String(200, "Success") +} +``` + +Test it with: +```sh +$ curl -X GET "localhost:8085/testing?name=appleboy&address=xyz&birthday=1992-03-15" +``` + +### Bind Uri + +See the [detail information](https://github.com/gin-gonic/gin/issues/846). + +```go +package main + +import "github.com/gin-gonic/gin" + +type Person struct { + ID string `uri:"id" binding:"required,uuid"` + Name string `uri:"name" binding:"required"` +} + +func main() { + route := gin.Default() + route.GET("/:name/:id", func(c *gin.Context) { + var person Person + if err := c.ShouldBindUri(&person); err != nil { + c.JSON(400, gin.H{"msg": err}) + return + } + c.JSON(200, gin.H{"name": person.Name, "uuid": person.ID}) + }) + route.Run(":8088") +} +``` + +Test it with: +```sh +$ curl -v localhost:8088/thinkerou/987fbc97-4bed-5078-9f07-9141ba07c9f3 +$ curl -v localhost:8088/thinkerou/not-uuid +``` + +### Bind HTML checkboxes + +See the [detail information](https://github.com/gin-gonic/gin/issues/129#issuecomment-124260092) + +main.go + +```go +... + +type myForm struct { + Colors []string `form:"colors[]"` +} + +... + +func formHandler(c *gin.Context) { + var fakeForm myForm + c.ShouldBind(&fakeForm) + c.JSON(200, gin.H{"color": fakeForm.Colors}) +} + +... + +``` + +form.html + +```html +

+

Check some colors

+ + + + + + + + +``` + +result: + +``` +{"color":["red","green","blue"]} +``` + +### Multipart/Urlencoded binding + +```go +package main + +import ( + "github.com/gin-gonic/gin" +) + +type LoginForm struct { + User string `form:"user" binding:"required"` + Password string `form:"password" binding:"required"` +} + +func main() { + router := gin.Default() + router.POST("/login", func(c *gin.Context) { + // you can bind multipart form with explicit binding declaration: + // c.ShouldBindWith(&form, binding.Form) + // or you can simply use autobinding with ShouldBind method: + var form LoginForm + // in this case proper binding will be automatically selected + if c.ShouldBind(&form) == nil { + if form.User == "user" && form.Password == "password" { + c.JSON(200, gin.H{"status": "you are logged in"}) + } else { + c.JSON(401, gin.H{"status": "unauthorized"}) + } + } + }) + router.Run(":8080") +} +``` + +Test it with: +```sh +$ curl -v --form user=user --form password=password http://localhost:8080/login +``` + +### XML, JSON, YAML and ProtoBuf rendering + +```go +func main() { + r := gin.Default() + + // gin.H is a shortcut for map[string]interface{} + r.GET("/someJSON", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK}) + }) + + r.GET("/moreJSON", func(c *gin.Context) { + // You also can use a struct + var msg struct { + Name string `json:"user"` + Message string + Number int + } + msg.Name = "Lena" + msg.Message = "hey" + msg.Number = 123 + // Note that msg.Name becomes "user" in the JSON + // Will output : {"user": "Lena", "Message": "hey", "Number": 123} + c.JSON(http.StatusOK, msg) + }) + + r.GET("/someXML", func(c *gin.Context) { + c.XML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK}) + }) + + r.GET("/someYAML", func(c *gin.Context) { + c.YAML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK}) + }) + + r.GET("/someProtoBuf", func(c *gin.Context) { + reps := []int64{int64(1), int64(2)} + label := "test" + // The specific definition of protobuf is written in the testdata/protoexample file. + data := &protoexample.Test{ + Label: &label, + Reps: reps, + } + // Note that data becomes binary data in the response + // Will output protoexample.Test protobuf serialized data + c.ProtoBuf(http.StatusOK, data) + }) + + // Listen and serve on 0.0.0.0:8080 + r.Run(":8080") +} +``` + +#### SecureJSON + +Using SecureJSON to prevent json hijacking. Default prepends `"while(1),"` to response body if the given struct is array values. + +```go +func main() { + r := gin.Default() + + // You can also use your own secure json prefix + // r.SecureJsonPrefix(")]}',\n") + + r.GET("/someJSON", func(c *gin.Context) { + names := []string{"lena", "austin", "foo"} + + // Will output : while(1);["lena","austin","foo"] + c.SecureJSON(http.StatusOK, names) + }) + + // Listen and serve on 0.0.0.0:8080 + r.Run(":8080") +} +``` +#### JSONP + +Using JSONP to request data from a server in a different domain. Add callback to response body if the query parameter callback exists. + +```go +func main() { + r := gin.Default() + + r.GET("/JSONP?callback=x", func(c *gin.Context) { + data := map[string]interface{}{ + "foo": "bar", + } + + //callback is x + // Will output : x({\"foo\":\"bar\"}) + c.JSONP(http.StatusOK, data) + }) + + // Listen and serve on 0.0.0.0:8080 + r.Run(":8080") +} +``` + +#### AsciiJSON + +Using AsciiJSON to Generates ASCII-only JSON with escaped non-ASCII chracters. + +```go +func main() { + r := gin.Default() + + r.GET("/someJSON", func(c *gin.Context) { + data := map[string]interface{}{ + "lang": "GO语言", + "tag": "
", + } + + // will output : {"lang":"GO\u8bed\u8a00","tag":"\u003cbr\u003e"} + c.AsciiJSON(http.StatusOK, data) + }) + + // Listen and serve on 0.0.0.0:8080 + r.Run(":8080") +} +``` + +#### PureJSON + +Normally, JSON replaces special HTML characters with their unicode entities, e.g. `<` becomes `\u003c`. If you want to encode such characters literally, you can use PureJSON instead. +This feature is unavailable in Go 1.6 and lower. + +```go +func main() { + r := gin.Default() + + // Serves unicode entities + r.GET("/json", func(c *gin.Context) { + c.JSON(200, gin.H{ + "html": "Hello, world!", + }) + }) + + // Serves literal characters + r.GET("/purejson", func(c *gin.Context) { + c.PureJSON(200, gin.H{ + "html": "Hello, world!", + }) + }) + + // listen and serve on 0.0.0.0:8080 + r.Run(":8080") +} +``` + +### Serving static files + +```go +func main() { + router := gin.Default() + router.Static("/assets", "./assets") + router.StaticFS("/more_static", http.Dir("my_file_system")) + router.StaticFile("/favicon.ico", "./resources/favicon.ico") + + // Listen and serve on 0.0.0.0:8080 + router.Run(":8080") +} +``` + +### Serving data from reader + +```go +func main() { + router := gin.Default() + router.GET("/someDataFromReader", func(c *gin.Context) { + response, err := http.Get("https://raw.githubusercontent.com/gin-gonic/logo/master/color.png") + if err != nil || response.StatusCode != http.StatusOK { + c.Status(http.StatusServiceUnavailable) + return + } + + reader := response.Body + contentLength := response.ContentLength + contentType := response.Header.Get("Content-Type") + + extraHeaders := map[string]string{ + "Content-Disposition": `attachment; filename="gopher.png"`, + } + + c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders) + }) + router.Run(":8080") +} +``` + +### HTML rendering + +Using LoadHTMLGlob() or LoadHTMLFiles() + +```go +func main() { + router := gin.Default() + router.LoadHTMLGlob("templates/*") + //router.LoadHTMLFiles("templates/template1.html", "templates/template2.html") + router.GET("/index", func(c *gin.Context) { + c.HTML(http.StatusOK, "index.tmpl", gin.H{ + "title": "Main website", + }) + }) + router.Run(":8080") +} +``` + +templates/index.tmpl + +```html + +

+ {{ .title }} +

+ +``` + +Using templates with same name in different directories + +```go +func main() { + router := gin.Default() + router.LoadHTMLGlob("templates/**/*") + router.GET("/posts/index", func(c *gin.Context) { + c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{ + "title": "Posts", + }) + }) + router.GET("/users/index", func(c *gin.Context) { + c.HTML(http.StatusOK, "users/index.tmpl", gin.H{ + "title": "Users", + }) + }) + router.Run(":8080") +} +``` + +templates/posts/index.tmpl + +```html +{{ define "posts/index.tmpl" }} +

+ {{ .title }} +

+

Using posts/index.tmpl

+ +{{ end }} +``` + +templates/users/index.tmpl + +```html +{{ define "users/index.tmpl" }} +

+ {{ .title }} +

+

Using users/index.tmpl

+ +{{ end }} +``` + +#### Custom Template renderer + +You can also use your own html template render + +```go +import "html/template" + +func main() { + router := gin.Default() + html := template.Must(template.ParseFiles("file1", "file2")) + router.SetHTMLTemplate(html) + router.Run(":8080") +} +``` + +#### Custom Delimiters + +You may use custom delims + +```go + r := gin.Default() + r.Delims("{[{", "}]}") + r.LoadHTMLGlob("/path/to/templates") +``` + +#### Custom Template Funcs + +See the detail [example code](https://github.com/gin-gonic/examples/tree/master/template). + +main.go + +```go +import ( + "fmt" + "html/template" + "net/http" + "time" + + "github.com/gin-gonic/gin" +) + +func formatAsDate(t time.Time) string { + year, month, day := t.Date() + return fmt.Sprintf("%d%02d/%02d", year, month, day) +} + +func main() { + router := gin.Default() + router.Delims("{[{", "}]}") + router.SetFuncMap(template.FuncMap{ + "formatAsDate": formatAsDate, + }) + router.LoadHTMLFiles("./testdata/template/raw.tmpl") + + router.GET("/raw", func(c *gin.Context) { + c.HTML(http.StatusOK, "raw.tmpl", map[string]interface{}{ + "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC), + }) + }) + + router.Run(":8080") +} + +``` + +raw.tmpl + +```html +Date: {[{.now | formatAsDate}]} +``` + +Result: +``` +Date: 2017/07/01 +``` + +### Multitemplate + +Gin allow by default use only one html.Template. Check [a multitemplate render](https://github.com/gin-contrib/multitemplate) for using features like go 1.6 `block template`. + +### Redirects + +Issuing a HTTP redirect is easy. Both internal and external locations are supported. + +```go +r.GET("/test", func(c *gin.Context) { + c.Redirect(http.StatusMovedPermanently, "http://www.google.com/") +}) +``` + + +Issuing a Router redirect, use `HandleContext` like below. + +``` go +r.GET("/test", func(c *gin.Context) { + c.Request.URL.Path = "/test2" + r.HandleContext(c) +}) +r.GET("/test2", func(c *gin.Context) { + c.JSON(200, gin.H{"hello": "world"}) +}) +``` + + +### Custom Middleware + +```go +func Logger() gin.HandlerFunc { + return func(c *gin.Context) { + t := time.Now() + + // Set example variable + c.Set("example", "12345") + + // before request + + c.Next() + + // after request + latency := time.Since(t) + log.Print(latency) + + // access the status we are sending + status := c.Writer.Status() + log.Println(status) + } +} + +func main() { + r := gin.New() + r.Use(Logger()) + + r.GET("/test", func(c *gin.Context) { + example := c.MustGet("example").(string) + + // it would print: "12345" + log.Println(example) + }) + + // Listen and serve on 0.0.0.0:8080 + r.Run(":8080") +} +``` + +### Using BasicAuth() middleware + +```go +// simulate some private data +var secrets = gin.H{ + "foo": gin.H{"email": "foo@bar.com", "phone": "123433"}, + "austin": gin.H{"email": "austin@example.com", "phone": "666"}, + "lena": gin.H{"email": "lena@guapa.com", "phone": "523443"}, +} + +func main() { + r := gin.Default() + + // Group using gin.BasicAuth() middleware + // gin.Accounts is a shortcut for map[string]string + authorized := r.Group("/admin", gin.BasicAuth(gin.Accounts{ + "foo": "bar", + "austin": "1234", + "lena": "hello2", + "manu": "4321", + })) + + // /admin/secrets endpoint + // hit "localhost:8080/admin/secrets + authorized.GET("/secrets", func(c *gin.Context) { + // get user, it was set by the BasicAuth middleware + user := c.MustGet(gin.AuthUserKey).(string) + if secret, ok := secrets[user]; ok { + c.JSON(http.StatusOK, gin.H{"user": user, "secret": secret}) + } else { + c.JSON(http.StatusOK, gin.H{"user": user, "secret": "NO SECRET :("}) + } + }) + + // Listen and serve on 0.0.0.0:8080 + r.Run(":8080") +} +``` + +### Goroutines inside a middleware + +When starting new Goroutines inside a middleware or handler, you **SHOULD NOT** use the original context inside it, you have to use a read-only copy. + +```go +func main() { + r := gin.Default() + + r.GET("/long_async", func(c *gin.Context) { + // create copy to be used inside the goroutine + cCp := c.Copy() + go func() { + // simulate a long task with time.Sleep(). 5 seconds + time.Sleep(5 * time.Second) + + // note that you are using the copied context "cCp", IMPORTANT + log.Println("Done! in path " + cCp.Request.URL.Path) + }() + }) + + r.GET("/long_sync", func(c *gin.Context) { + // simulate a long task with time.Sleep(). 5 seconds + time.Sleep(5 * time.Second) + + // since we are NOT using a goroutine, we do not have to copy the context + log.Println("Done! in path " + c.Request.URL.Path) + }) + + // Listen and serve on 0.0.0.0:8080 + r.Run(":8080") +} +``` + +### Custom HTTP configuration + +Use `http.ListenAndServe()` directly, like this: + +```go +func main() { + router := gin.Default() + http.ListenAndServe(":8080", router) +} +``` +or + +```go +func main() { + router := gin.Default() + + s := &http.Server{ + Addr: ":8080", + Handler: router, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + MaxHeaderBytes: 1 << 20, + } + s.ListenAndServe() +} +``` + +### Support Let's Encrypt + +example for 1-line LetsEncrypt HTTPS servers. + +```go +package main + +import ( + "log" + + "github.com/gin-gonic/autotls" + "github.com/gin-gonic/gin" +) + +func main() { + r := gin.Default() + + // Ping handler + r.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + + log.Fatal(autotls.Run(r, "example1.com", "example2.com")) +} +``` + +example for custom autocert manager. + +```go +package main + +import ( + "log" + + "github.com/gin-gonic/autotls" + "github.com/gin-gonic/gin" + "golang.org/x/crypto/acme/autocert" +) + +func main() { + r := gin.Default() + + // Ping handler + r.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + + m := autocert.Manager{ + Prompt: autocert.AcceptTOS, + HostPolicy: autocert.HostWhitelist("example1.com", "example2.com"), + Cache: autocert.DirCache("/var/www/.cache"), + } + + log.Fatal(autotls.RunWithManager(r, &m)) +} +``` + +### Run multiple service using Gin + +See the [question](https://github.com/gin-gonic/gin/issues/346) and try the following example: + +```go +package main + +import ( + "log" + "net/http" + "time" + + "github.com/gin-gonic/gin" + "golang.org/x/sync/errgroup" +) + +var ( + g errgroup.Group +) + +func router01() http.Handler { + e := gin.New() + e.Use(gin.Recovery()) + e.GET("/", func(c *gin.Context) { + c.JSON( + http.StatusOK, + gin.H{ + "code": http.StatusOK, + "error": "Welcome server 01", + }, + ) + }) + + return e +} + +func router02() http.Handler { + e := gin.New() + e.Use(gin.Recovery()) + e.GET("/", func(c *gin.Context) { + c.JSON( + http.StatusOK, + gin.H{ + "code": http.StatusOK, + "error": "Welcome server 02", + }, + ) + }) + + return e +} + +func main() { + server01 := &http.Server{ + Addr: ":8080", + Handler: router01(), + ReadTimeout: 5 * time.Second, + WriteTimeout: 10 * time.Second, + } + + server02 := &http.Server{ + Addr: ":8081", + Handler: router02(), + ReadTimeout: 5 * time.Second, + WriteTimeout: 10 * time.Second, + } + + g.Go(func() error { + return server01.ListenAndServe() + }) + + g.Go(func() error { + return server02.ListenAndServe() + }) + + if err := g.Wait(); err != nil { + log.Fatal(err) + } +} +``` + +### Graceful restart or stop + +Do you want to graceful restart or stop your web server? +There are some ways this can be done. + +We can use [fvbock/endless](https://github.com/fvbock/endless) to replace the default `ListenAndServe`. Refer issue [#296](https://github.com/gin-gonic/gin/issues/296) for more details. + +```go +router := gin.Default() +router.GET("/", handler) +// [...] +endless.ListenAndServe(":4242", router) +``` + +An alternative to endless: + +* [manners](https://github.com/braintree/manners): A polite Go HTTP server that shuts down gracefully. +* [graceful](https://github.com/tylerb/graceful): Graceful is a Go package enabling graceful shutdown of an http.Handler server. +* [grace](https://github.com/facebookgo/grace): Graceful restart & zero downtime deploy for Go servers. + +If you are using Go 1.8, you may not need to use this library! Consider using http.Server's built-in [Shutdown()](https://golang.org/pkg/net/http/#Server.Shutdown) method for graceful shutdowns. See the full [graceful-shutdown](https://github.com/gin-gonic/examples/tree/master/graceful-shutdown) example with gin. + +```go +// +build go1.8 + +package main + +import ( + "context" + "log" + "net/http" + "os" + "os/signal" + "syscall" + "time" + + "github.com/gin-gonic/gin" +) + +func main() { + router := gin.Default() + router.GET("/", func(c *gin.Context) { + time.Sleep(5 * time.Second) + c.String(http.StatusOK, "Welcome Gin Server") + }) + + srv := &http.Server{ + Addr: ":8080", + Handler: router, + } + + go func() { + // service connections + if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Fatalf("listen: %s\n", err) + } + }() + + // Wait for interrupt signal to gracefully shutdown the server with + // a timeout of 5 seconds. + quit := make(chan os.Signal) + // kill (no param) default send syscall.SIGTERM + // kill -2 is syscall.SIGINT + // kill -9 is syscall.SIGKILL but can"t be catch, so don't need add it + signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) + <-quit + log.Println("Shutdown Server ...") + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + if err := srv.Shutdown(ctx); err != nil { + log.Fatal("Server Shutdown:", err) + } + // catching ctx.Done(). timeout of 5 seconds. + select { + case <-ctx.Done(): + log.Println("timeout of 5 seconds.") + } + log.Println("Server exiting") +} +``` + +### Build a single binary with templates + +You can build a server into a single binary containing templates by using [go-assets][]. + +[go-assets]: https://github.com/jessevdk/go-assets + +```go +func main() { + r := gin.New() + + t, err := loadTemplate() + if err != nil { + panic(err) + } + r.SetHTMLTemplate(t) + + r.GET("/", func(c *gin.Context) { + c.HTML(http.StatusOK, "/html/index.tmpl",nil) + }) + r.Run(":8080") +} + +// loadTemplate loads templates embedded by go-assets-builder +func loadTemplate() (*template.Template, error) { + t := template.New("") + for name, file := range Assets.Files { + if file.IsDir() || !strings.HasSuffix(name, ".tmpl") { + continue + } + h, err := ioutil.ReadAll(file) + if err != nil { + return nil, err + } + t, err = t.New(name).Parse(string(h)) + if err != nil { + return nil, err + } + } + return t, nil +} +``` + +See a complete example in the `https://github.com/gin-gonic/examples/tree/master/assets-in-binary` directory. + +### Bind form-data request with custom struct + +The follow example using custom struct: + +```go +type StructA struct { + FieldA string `form:"field_a"` +} + +type StructB struct { + NestedStruct StructA + FieldB string `form:"field_b"` +} + +type StructC struct { + NestedStructPointer *StructA + FieldC string `form:"field_c"` +} + +type StructD struct { + NestedAnonyStruct struct { + FieldX string `form:"field_x"` + } + FieldD string `form:"field_d"` +} + +func GetDataB(c *gin.Context) { + var b StructB + c.Bind(&b) + c.JSON(200, gin.H{ + "a": b.NestedStruct, + "b": b.FieldB, + }) +} + +func GetDataC(c *gin.Context) { + var b StructC + c.Bind(&b) + c.JSON(200, gin.H{ + "a": b.NestedStructPointer, + "c": b.FieldC, + }) +} + +func GetDataD(c *gin.Context) { + var b StructD + c.Bind(&b) + c.JSON(200, gin.H{ + "x": b.NestedAnonyStruct, + "d": b.FieldD, + }) +} + +func main() { + r := gin.Default() + r.GET("/getb", GetDataB) + r.GET("/getc", GetDataC) + r.GET("/getd", GetDataD) + + r.Run() +} +``` + +Using the command `curl` command result: + +``` +$ curl "http://localhost:8080/getb?field_a=hello&field_b=world" +{"a":{"FieldA":"hello"},"b":"world"} +$ curl "http://localhost:8080/getc?field_a=hello&field_c=world" +{"a":{"FieldA":"hello"},"c":"world"} +$ curl "http://localhost:8080/getd?field_x=hello&field_d=world" +{"d":"world","x":{"FieldX":"hello"}} +``` + +### Try to bind body into different structs + +The normal methods for binding request body consumes `c.Request.Body` and they +cannot be called multiple times. + +```go +type formA struct { + Foo string `json:"foo" xml:"foo" binding:"required"` +} + +type formB struct { + Bar string `json:"bar" xml:"bar" binding:"required"` +} + +func SomeHandler(c *gin.Context) { + objA := formA{} + objB := formB{} + // This c.ShouldBind consumes c.Request.Body and it cannot be reused. + if errA := c.ShouldBind(&objA); errA == nil { + c.String(http.StatusOK, `the body should be formA`) + // Always an error is occurred by this because c.Request.Body is EOF now. + } else if errB := c.ShouldBind(&objB); errB == nil { + c.String(http.StatusOK, `the body should be formB`) + } else { + ... + } +} +``` + +For this, you can use `c.ShouldBindBodyWith`. + +```go +func SomeHandler(c *gin.Context) { + objA := formA{} + objB := formB{} + // This reads c.Request.Body and stores the result into the context. + if errA := c.ShouldBindBodyWith(&objA, binding.JSON); errA == nil { + c.String(http.StatusOK, `the body should be formA`) + // At this time, it reuses body stored in the context. + } else if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB == nil { + c.String(http.StatusOK, `the body should be formB JSON`) + // And it can accepts other formats + } else if errB2 := c.ShouldBindBodyWith(&objB, binding.XML); errB2 == nil { + c.String(http.StatusOK, `the body should be formB XML`) + } else { + ... + } +} +``` + +* `c.ShouldBindBodyWith` stores body into the context before binding. This has +a slight impact to performance, so you should not use this method if you are +enough to call binding at once. +* This feature is only needed for some formats -- `JSON`, `XML`, `MsgPack`, +`ProtoBuf`. For other formats, `Query`, `Form`, `FormPost`, `FormMultipart`, +can be called by `c.ShouldBind()` multiple times without any damage to +performance (See [#1341](https://github.com/gin-gonic/gin/pull/1341)). + +### http2 server push + +http.Pusher is supported only **go1.8+**. See the [golang blog](https://blog.golang.org/h2push) for detail information. + +```go +package main + +import ( + "html/template" + "log" + + "github.com/gin-gonic/gin" +) + +var html = template.Must(template.New("https").Parse(` + + + Https Test + + + +

Welcome, Ginner!

+ + +`)) + +func main() { + r := gin.Default() + r.Static("/assets", "./assets") + r.SetHTMLTemplate(html) + + r.GET("/", func(c *gin.Context) { + if pusher := c.Writer.Pusher(); pusher != nil { + // use pusher.Push() to do server push + if err := pusher.Push("/assets/app.js", nil); err != nil { + log.Printf("Failed to push: %v", err) + } + } + c.HTML(200, "https", gin.H{ + "status": "success", + }) + }) + + // Listen and Server in https://127.0.0.1:8080 + r.RunTLS(":8080", "./testdata/server.pem", "./testdata/server.key") +} +``` + +### Define format for the log of routes + +The default log of routes is: +``` +[GIN-debug] POST /foo --> main.main.func1 (3 handlers) +[GIN-debug] GET /bar --> main.main.func2 (3 handlers) +[GIN-debug] GET /status --> main.main.func3 (3 handlers) +``` + +If you want to log this information in given format (e.g. JSON, key values or something else), then you can define this format with `gin.DebugPrintRouteFunc`. +In the example below, we log all routes with standard log package but you can use another log tools that suits of your needs. +```go +import ( + "log" + "net/http" + + "github.com/gin-gonic/gin" +) + +func main() { + r := gin.Default() + gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) { + log.Printf("endpoint %v %v %v %v\n", httpMethod, absolutePath, handlerName, nuHandlers) + } + + r.POST("/foo", func(c *gin.Context) { + c.JSON(http.StatusOK, "foo") + }) + + r.GET("/bar", func(c *gin.Context) { + c.JSON(http.StatusOK, "bar") + }) + + r.GET("/status", func(c *gin.Context) { + c.JSON(http.StatusOK, "ok") + }) + + // Listen and Server in http://0.0.0.0:8080 + r.Run() +} +``` + +### Set and get a cookie + +```go +import ( + "fmt" + + "github.com/gin-gonic/gin" +) + +func main() { + + router := gin.Default() + + router.GET("/cookie", func(c *gin.Context) { + + cookie, err := c.Cookie("gin_cookie") + + if err != nil { + cookie = "NotSet" + c.SetCookie("gin_cookie", "test", 3600, "/", "localhost", false, true) + } + + fmt.Printf("Cookie value: %s \n", cookie) + }) + + router.Run() +} +``` + + +## Testing + +The `net/http/httptest` package is preferable way for HTTP testing. + +```go +package main + +func setupRouter() *gin.Engine { + r := gin.Default() + r.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + return r +} + +func main() { + r := setupRouter() + r.Run(":8080") +} +``` + +Test for code example above: + +```go +package main + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPingRoute(t *testing.T) { + router := setupRouter() + + w := httptest.NewRecorder() + req, _ := http.NewRequest("GET", "/ping", nil) + router.ServeHTTP(w, req) + + assert.Equal(t, 200, w.Code) + assert.Equal(t, "pong", w.Body.String()) +} +``` + +## Users + +Awesome project lists using [Gin](https://github.com/gin-gonic/gin) web framework. + +* [gorush](https://github.com/appleboy/gorush): A push notification server written in Go. +* [fnproject](https://github.com/fnproject/fn): The container native, cloud agnostic serverless platform. +* [photoprism](https://github.com/photoprism/photoprism): Personal photo management powered by Go and Google TensorFlow. +* [krakend](https://github.com/devopsfaith/krakend): Ultra performant API Gateway with middlewares. +* [picfit](https://github.com/thoas/picfit): An image resizing server written in Go. diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/auth.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/auth.go new file mode 100644 index 0000000..9ed81b5 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/auth.go @@ -0,0 +1,96 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import ( + "crypto/subtle" + "encoding/base64" + "net/http" + "strconv" +) + +// AuthUserKey is the cookie name for user credential in basic auth. +const AuthUserKey = "user" + +// Accounts defines a key/value for user/pass list of authorized logins. +type Accounts map[string]string + +type authPair struct { + value string + user string +} + +type authPairs []authPair + +func (a authPairs) searchCredential(authValue string) (string, bool) { + if authValue == "" { + return "", false + } + for _, pair := range a { + if pair.value == authValue { + return pair.user, true + } + } + return "", false +} + +// BasicAuthForRealm returns a Basic HTTP Authorization middleware. It takes as arguments a map[string]string where +// the key is the user name and the value is the password, as well as the name of the Realm. +// If the realm is empty, "Authorization Required" will be used by default. +// (see http://tools.ietf.org/html/rfc2617#section-1.2) +func BasicAuthForRealm(accounts Accounts, realm string) HandlerFunc { + if realm == "" { + realm = "Authorization Required" + } + realm = "Basic realm=" + strconv.Quote(realm) + pairs := processAccounts(accounts) + return func(c *Context) { + // Search user in the slice of allowed credentials + user, found := pairs.searchCredential(c.requestHeader("Authorization")) + if !found { + // Credentials doesn't match, we return 401 and abort handlers chain. + c.Header("WWW-Authenticate", realm) + c.AbortWithStatus(http.StatusUnauthorized) + return + } + + // The user credentials was found, set user's id to key AuthUserKey in this context, the user's id can be read later using + // c.MustGet(gin.AuthUserKey). + c.Set(AuthUserKey, user) + } +} + +// BasicAuth returns a Basic HTTP Authorization middleware. It takes as argument a map[string]string where +// the key is the user name and the value is the password. +func BasicAuth(accounts Accounts) HandlerFunc { + return BasicAuthForRealm(accounts, "") +} + +func processAccounts(accounts Accounts) authPairs { + assert1(len(accounts) > 0, "Empty list of authorized credentials") + pairs := make(authPairs, 0, len(accounts)) + for user, password := range accounts { + assert1(user != "", "User can not be empty") + value := authorizationHeader(user, password) + pairs = append(pairs, authPair{ + value: value, + user: user, + }) + } + return pairs +} + +func authorizationHeader(user, password string) string { + base := user + ":" + password + return "Basic " + base64.StdEncoding.EncodeToString([]byte(base)) +} + +func secureCompare(given, actual string) bool { + if subtle.ConstantTimeEq(int32(len(given)), int32(len(actual))) == 1 { + return subtle.ConstantTimeCompare([]byte(given), []byte(actual)) == 1 + } + // Securely compare actual to itself to keep constant time, but always return false. + return subtle.ConstantTimeCompare([]byte(actual), []byte(actual)) == 1 && false +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/binding.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/binding.go new file mode 100644 index 0000000..520c510 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/binding.go @@ -0,0 +1,113 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package binding + +import "net/http" + +// Content-Type MIME of the most common data formats. +const ( + MIMEJSON = "application/json" + MIMEHTML = "text/html" + MIMEXML = "application/xml" + MIMEXML2 = "text/xml" + MIMEPlain = "text/plain" + MIMEPOSTForm = "application/x-www-form-urlencoded" + MIMEMultipartPOSTForm = "multipart/form-data" + MIMEPROTOBUF = "application/x-protobuf" + MIMEMSGPACK = "application/x-msgpack" + MIMEMSGPACK2 = "application/msgpack" + MIMEYAML = "application/x-yaml" +) + +// Binding describes the interface which needs to be implemented for binding the +// data present in the request such as JSON request body, query parameters or +// the form POST. +type Binding interface { + Name() string + Bind(*http.Request, interface{}) error +} + +// BindingBody adds BindBody method to Binding. BindBody is similar with Bind, +// but it reads the body from supplied bytes instead of req.Body. +type BindingBody interface { + Binding + BindBody([]byte, interface{}) error +} + +// BindingUri adds BindUri method to Binding. BindUri is similar with Bind, +// but it read the Params. +type BindingUri interface { + Name() string + BindUri(map[string][]string, interface{}) error +} + +// StructValidator is the minimal interface which needs to be implemented in +// order for it to be used as the validator engine for ensuring the correctness +// of the request. Gin provides a default implementation for this using +// https://github.com/go-playground/validator/tree/v8.18.2. +type StructValidator interface { + // ValidateStruct can receive any kind of type and it should never panic, even if the configuration is not right. + // If the received type is not a struct, any validation should be skipped and nil must be returned. + // If the received type is a struct or pointer to a struct, the validation should be performed. + // If the struct is not valid or the validation itself fails, a descriptive error should be returned. + // Otherwise nil must be returned. + ValidateStruct(interface{}) error + + // Engine returns the underlying validator engine which powers the + // StructValidator implementation. + Engine() interface{} +} + +// Validator is the default validator which implements the StructValidator +// interface. It uses https://github.com/go-playground/validator/tree/v8.18.2 +// under the hood. +var Validator StructValidator = &defaultValidator{} + +// These implement the Binding interface and can be used to bind the data +// present in the request to struct instances. +var ( + JSON = jsonBinding{} + XML = xmlBinding{} + Form = formBinding{} + Query = queryBinding{} + FormPost = formPostBinding{} + FormMultipart = formMultipartBinding{} + ProtoBuf = protobufBinding{} + MsgPack = msgpackBinding{} + YAML = yamlBinding{} + Uri = uriBinding{} +) + +// Default returns the appropriate Binding instance based on the HTTP method +// and the content type. +func Default(method, contentType string) Binding { + if method == "GET" { + return Form + } + + switch contentType { + case MIMEJSON: + return JSON + case MIMEXML, MIMEXML2: + return XML + case MIMEPROTOBUF: + return ProtoBuf + case MIMEMSGPACK, MIMEMSGPACK2: + return MsgPack + case MIMEYAML: + return YAML + case MIMEMultipartPOSTForm: + return FormMultipart + default: // case MIMEPOSTForm: + return Form + } +} + +func validate(obj interface{}) error { + if Validator == nil { + return nil + } + return Validator.ValidateStruct(obj) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/default_validator.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/default_validator.go new file mode 100644 index 0000000..e7a302d --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/default_validator.go @@ -0,0 +1,51 @@ +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package binding + +import ( + "reflect" + "sync" + + "gopkg.in/go-playground/validator.v8" +) + +type defaultValidator struct { + once sync.Once + validate *validator.Validate +} + +var _ StructValidator = &defaultValidator{} + +// ValidateStruct receives any kind of type, but only performed struct or pointer to struct type. +func (v *defaultValidator) ValidateStruct(obj interface{}) error { + value := reflect.ValueOf(obj) + valueType := value.Kind() + if valueType == reflect.Ptr { + valueType = value.Elem().Kind() + } + if valueType == reflect.Struct { + v.lazyinit() + if err := v.validate.Struct(obj); err != nil { + return err + } + } + return nil +} + +// Engine returns the underlying validator engine which powers the default +// Validator instance. This is useful if you want to register custom validations +// or struct level validations. See validator GoDoc for more info - +// https://godoc.org/gopkg.in/go-playground/validator.v8 +func (v *defaultValidator) Engine() interface{} { + v.lazyinit() + return v.validate +} + +func (v *defaultValidator) lazyinit() { + v.once.Do(func() { + config := &validator.Config{TagName: "binding"} + v.validate = validator.New(config) + }) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/form.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/form.go new file mode 100644 index 0000000..0b28aa8 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/form.go @@ -0,0 +1,89 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package binding + +import ( + "mime/multipart" + "net/http" + "reflect" +) + +const defaultMemory = 32 * 1024 * 1024 + +type formBinding struct{} +type formPostBinding struct{} +type formMultipartBinding struct{} + +func (formBinding) Name() string { + return "form" +} + +func (formBinding) Bind(req *http.Request, obj interface{}) error { + if err := req.ParseForm(); err != nil { + return err + } + if err := req.ParseMultipartForm(defaultMemory); err != nil { + if err != http.ErrNotMultipart { + return err + } + } + if err := mapForm(obj, req.Form); err != nil { + return err + } + return validate(obj) +} + +func (formPostBinding) Name() string { + return "form-urlencoded" +} + +func (formPostBinding) Bind(req *http.Request, obj interface{}) error { + if err := req.ParseForm(); err != nil { + return err + } + if err := mapForm(obj, req.PostForm); err != nil { + return err + } + return validate(obj) +} + +func (formMultipartBinding) Name() string { + return "multipart/form-data" +} + +func (formMultipartBinding) Bind(req *http.Request, obj interface{}) error { + if err := req.ParseMultipartForm(defaultMemory); err != nil { + return err + } + if err := mappingByPtr(obj, (*multipartRequest)(req), "form"); err != nil { + return err + } + + return validate(obj) +} + +type multipartRequest http.Request + +var _ setter = (*multipartRequest)(nil) + +var ( + multipartFileHeaderStructType = reflect.TypeOf(multipart.FileHeader{}) +) + +// TrySet tries to set a value by the multipart request with the binding a form file +func (r *multipartRequest) TrySet(value reflect.Value, field reflect.StructField, key string, opt setOptions) (isSetted bool, err error) { + if value.Type() == multipartFileHeaderStructType { + _, file, err := (*http.Request)(r).FormFile(key) + if err != nil { + return false, err + } + if file != nil { + value.Set(reflect.ValueOf(*file)) + return true, nil + } + } + + return setByForm(value, field, r.MultipartForm.Value, key, opt) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/form_mapping.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/form_mapping.go new file mode 100644 index 0000000..aaacf6c --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/form_mapping.go @@ -0,0 +1,330 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package binding + +import ( + "errors" + "fmt" + "reflect" + "strconv" + "strings" + "time" + + "github.com/gin-gonic/gin/internal/json" +) + +var errUnknownType = errors.New("Unknown type") + +func mapUri(ptr interface{}, m map[string][]string) error { + return mapFormByTag(ptr, m, "uri") +} + +func mapForm(ptr interface{}, form map[string][]string) error { + return mapFormByTag(ptr, form, "form") +} + +var emptyField = reflect.StructField{} + +func mapFormByTag(ptr interface{}, form map[string][]string, tag string) error { + return mappingByPtr(ptr, formSource(form), tag) +} + +// setter tries to set value on a walking by fields of a struct +type setter interface { + TrySet(value reflect.Value, field reflect.StructField, key string, opt setOptions) (isSetted bool, err error) +} + +type formSource map[string][]string + +var _ setter = formSource(nil) + +// TrySet tries to set a value by request's form source (like map[string][]string) +func (form formSource) TrySet(value reflect.Value, field reflect.StructField, tagValue string, opt setOptions) (isSetted bool, err error) { + return setByForm(value, field, form, tagValue, opt) +} + +func mappingByPtr(ptr interface{}, setter setter, tag string) error { + _, err := mapping(reflect.ValueOf(ptr), emptyField, setter, tag) + return err +} + +func mapping(value reflect.Value, field reflect.StructField, setter setter, tag string) (bool, error) { + var vKind = value.Kind() + + if vKind == reflect.Ptr { + var isNew bool + vPtr := value + if value.IsNil() { + isNew = true + vPtr = reflect.New(value.Type().Elem()) + } + isSetted, err := mapping(vPtr.Elem(), field, setter, tag) + if err != nil { + return false, err + } + if isNew && isSetted { + value.Set(vPtr) + } + return isSetted, nil + } + + ok, err := tryToSetValue(value, field, setter, tag) + if err != nil { + return false, err + } + if ok { + return true, nil + } + + if vKind == reflect.Struct { + tValue := value.Type() + + var isSetted bool + for i := 0; i < value.NumField(); i++ { + if !value.Field(i).CanSet() { + continue + } + ok, err := mapping(value.Field(i), tValue.Field(i), setter, tag) + if err != nil { + return false, err + } + isSetted = isSetted || ok + } + return isSetted, nil + } + return false, nil +} + +type setOptions struct { + isDefaultExists bool + defaultValue string +} + +func tryToSetValue(value reflect.Value, field reflect.StructField, setter setter, tag string) (bool, error) { + var tagValue string + var setOpt setOptions + + tagValue = field.Tag.Get(tag) + tagValue, opts := head(tagValue, ",") + + if tagValue == "-" { // just ignoring this field + return false, nil + } + if tagValue == "" { // default value is FieldName + tagValue = field.Name + } + if tagValue == "" { // when field is "emptyField" variable + return false, nil + } + + var opt string + for len(opts) > 0 { + opt, opts = head(opts, ",") + + k, v := head(opt, "=") + switch k { + case "default": + setOpt.isDefaultExists = true + setOpt.defaultValue = v + } + } + + return setter.TrySet(value, field, tagValue, setOpt) +} + +func setByForm(value reflect.Value, field reflect.StructField, form map[string][]string, tagValue string, opt setOptions) (isSetted bool, err error) { + vs, ok := form[tagValue] + if !ok && !opt.isDefaultExists { + return false, nil + } + + switch value.Kind() { + case reflect.Slice: + if !ok { + vs = []string{opt.defaultValue} + } + return true, setSlice(vs, value, field) + case reflect.Array: + if !ok { + vs = []string{opt.defaultValue} + } + if len(vs) != value.Len() { + return false, fmt.Errorf("%q is not valid value for %s", vs, value.Type().String()) + } + return true, setArray(vs, value, field) + default: + var val string + if !ok { + val = opt.defaultValue + } + + if len(vs) > 0 { + val = vs[0] + } + return true, setWithProperType(val, value, field) + } +} + +func setWithProperType(val string, value reflect.Value, field reflect.StructField) error { + switch value.Kind() { + case reflect.Int: + return setIntField(val, 0, value) + case reflect.Int8: + return setIntField(val, 8, value) + case reflect.Int16: + return setIntField(val, 16, value) + case reflect.Int32: + return setIntField(val, 32, value) + case reflect.Int64: + switch value.Interface().(type) { + case time.Duration: + return setTimeDuration(val, value, field) + } + return setIntField(val, 64, value) + case reflect.Uint: + return setUintField(val, 0, value) + case reflect.Uint8: + return setUintField(val, 8, value) + case reflect.Uint16: + return setUintField(val, 16, value) + case reflect.Uint32: + return setUintField(val, 32, value) + case reflect.Uint64: + return setUintField(val, 64, value) + case reflect.Bool: + return setBoolField(val, value) + case reflect.Float32: + return setFloatField(val, 32, value) + case reflect.Float64: + return setFloatField(val, 64, value) + case reflect.String: + value.SetString(val) + case reflect.Struct: + switch value.Interface().(type) { + case time.Time: + return setTimeField(val, field, value) + } + return json.Unmarshal([]byte(val), value.Addr().Interface()) + case reflect.Map: + return json.Unmarshal([]byte(val), value.Addr().Interface()) + default: + return errUnknownType + } + return nil +} + +func setIntField(val string, bitSize int, field reflect.Value) error { + if val == "" { + val = "0" + } + intVal, err := strconv.ParseInt(val, 10, bitSize) + if err == nil { + field.SetInt(intVal) + } + return err +} + +func setUintField(val string, bitSize int, field reflect.Value) error { + if val == "" { + val = "0" + } + uintVal, err := strconv.ParseUint(val, 10, bitSize) + if err == nil { + field.SetUint(uintVal) + } + return err +} + +func setBoolField(val string, field reflect.Value) error { + if val == "" { + val = "false" + } + boolVal, err := strconv.ParseBool(val) + if err == nil { + field.SetBool(boolVal) + } + return err +} + +func setFloatField(val string, bitSize int, field reflect.Value) error { + if val == "" { + val = "0.0" + } + floatVal, err := strconv.ParseFloat(val, bitSize) + if err == nil { + field.SetFloat(floatVal) + } + return err +} + +func setTimeField(val string, structField reflect.StructField, value reflect.Value) error { + timeFormat := structField.Tag.Get("time_format") + if timeFormat == "" { + timeFormat = time.RFC3339 + } + + if val == "" { + value.Set(reflect.ValueOf(time.Time{})) + return nil + } + + l := time.Local + if isUTC, _ := strconv.ParseBool(structField.Tag.Get("time_utc")); isUTC { + l = time.UTC + } + + if locTag := structField.Tag.Get("time_location"); locTag != "" { + loc, err := time.LoadLocation(locTag) + if err != nil { + return err + } + l = loc + } + + t, err := time.ParseInLocation(timeFormat, val, l) + if err != nil { + return err + } + + value.Set(reflect.ValueOf(t)) + return nil +} + +func setArray(vals []string, value reflect.Value, field reflect.StructField) error { + for i, s := range vals { + err := setWithProperType(s, value.Index(i), field) + if err != nil { + return err + } + } + return nil +} + +func setSlice(vals []string, value reflect.Value, field reflect.StructField) error { + slice := reflect.MakeSlice(value.Type(), len(vals), len(vals)) + err := setArray(vals, slice, field) + if err != nil { + return err + } + value.Set(slice) + return nil +} + +func setTimeDuration(val string, value reflect.Value, field reflect.StructField) error { + d, err := time.ParseDuration(val) + if err != nil { + return err + } + value.Set(reflect.ValueOf(d)) + return nil +} + +func head(str, sep string) (head string, tail string) { + idx := strings.Index(str, sep) + if idx < 0 { + return str, "" + } + return str[:idx], str[idx+len(sep):] +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/json.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/json.go new file mode 100644 index 0000000..f968161 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/json.go @@ -0,0 +1,47 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package binding + +import ( + "bytes" + "fmt" + "io" + "net/http" + + "github.com/gin-gonic/gin/internal/json" +) + +// EnableDecoderUseNumber is used to call the UseNumber method on the JSON +// Decoder instance. UseNumber causes the Decoder to unmarshal a number into an +// interface{} as a Number instead of as a float64. +var EnableDecoderUseNumber = false + +type jsonBinding struct{} + +func (jsonBinding) Name() string { + return "json" +} + +func (jsonBinding) Bind(req *http.Request, obj interface{}) error { + if req == nil || req.Body == nil { + return fmt.Errorf("invalid request") + } + return decodeJSON(req.Body, obj) +} + +func (jsonBinding) BindBody(body []byte, obj interface{}) error { + return decodeJSON(bytes.NewReader(body), obj) +} + +func decodeJSON(r io.Reader, obj interface{}) error { + decoder := json.NewDecoder(r) + if EnableDecoderUseNumber { + decoder.UseNumber() + } + if err := decoder.Decode(obj); err != nil { + return err + } + return validate(obj) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/msgpack.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/msgpack.go new file mode 100644 index 0000000..b7f7319 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/msgpack.go @@ -0,0 +1,35 @@ +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package binding + +import ( + "bytes" + "io" + "net/http" + + "github.com/ugorji/go/codec" +) + +type msgpackBinding struct{} + +func (msgpackBinding) Name() string { + return "msgpack" +} + +func (msgpackBinding) Bind(req *http.Request, obj interface{}) error { + return decodeMsgPack(req.Body, obj) +} + +func (msgpackBinding) BindBody(body []byte, obj interface{}) error { + return decodeMsgPack(bytes.NewReader(body), obj) +} + +func decodeMsgPack(r io.Reader, obj interface{}) error { + cdc := new(codec.MsgpackHandle) + if err := codec.NewDecoder(r, cdc).Decode(&obj); err != nil { + return err + } + return validate(obj) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/protobuf.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/protobuf.go new file mode 100644 index 0000000..f9ece92 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/protobuf.go @@ -0,0 +1,36 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package binding + +import ( + "io/ioutil" + "net/http" + + "github.com/golang/protobuf/proto" +) + +type protobufBinding struct{} + +func (protobufBinding) Name() string { + return "protobuf" +} + +func (b protobufBinding) Bind(req *http.Request, obj interface{}) error { + buf, err := ioutil.ReadAll(req.Body) + if err != nil { + return err + } + return b.BindBody(buf, obj) +} + +func (protobufBinding) BindBody(body []byte, obj interface{}) error { + if err := proto.Unmarshal(body, obj.(proto.Message)); err != nil { + return err + } + // Here it's same to return validate(obj), but util now we can't add + // `binding:""` to the struct which automatically generate by gen-proto + return nil + // return validate(obj) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/query.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/query.go new file mode 100644 index 0000000..219743f --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/query.go @@ -0,0 +1,21 @@ +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package binding + +import "net/http" + +type queryBinding struct{} + +func (queryBinding) Name() string { + return "query" +} + +func (queryBinding) Bind(req *http.Request, obj interface{}) error { + values := req.URL.Query() + if err := mapForm(obj, values); err != nil { + return err + } + return validate(obj) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/uri.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/uri.go new file mode 100644 index 0000000..f91ec38 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/uri.go @@ -0,0 +1,18 @@ +// Copyright 2018 Gin Core Team. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package binding + +type uriBinding struct{} + +func (uriBinding) Name() string { + return "uri" +} + +func (uriBinding) BindUri(m map[string][]string, obj interface{}) error { + if err := mapUri(obj, m); err != nil { + return err + } + return validate(obj) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/xml.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/xml.go new file mode 100644 index 0000000..4e90114 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/xml.go @@ -0,0 +1,33 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package binding + +import ( + "bytes" + "encoding/xml" + "io" + "net/http" +) + +type xmlBinding struct{} + +func (xmlBinding) Name() string { + return "xml" +} + +func (xmlBinding) Bind(req *http.Request, obj interface{}) error { + return decodeXML(req.Body, obj) +} + +func (xmlBinding) BindBody(body []byte, obj interface{}) error { + return decodeXML(bytes.NewReader(body), obj) +} +func decodeXML(r io.Reader, obj interface{}) error { + decoder := xml.NewDecoder(r) + if err := decoder.Decode(obj); err != nil { + return err + } + return validate(obj) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/yaml.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/yaml.go new file mode 100644 index 0000000..a2d36d6 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/binding/yaml.go @@ -0,0 +1,35 @@ +// Copyright 2018 Gin Core Team. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package binding + +import ( + "bytes" + "io" + "net/http" + + "gopkg.in/yaml.v2" +) + +type yamlBinding struct{} + +func (yamlBinding) Name() string { + return "yaml" +} + +func (yamlBinding) Bind(req *http.Request, obj interface{}) error { + return decodeYAML(req.Body, obj) +} + +func (yamlBinding) BindBody(body []byte, obj interface{}) error { + return decodeYAML(bytes.NewReader(body), obj) +} + +func decodeYAML(r io.Reader, obj interface{}) error { + decoder := yaml.NewDecoder(r) + if err := decoder.Decode(obj); err != nil { + return err + } + return validate(obj) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/codecov.yml b/go/src/themaru/vendor/github.com/gin-gonic/gin/codecov.yml new file mode 100644 index 0000000..c9c9a52 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/codecov.yml @@ -0,0 +1,5 @@ +coverage: + notify: + gitter: + default: + url: https://webhooks.gitter.im/e/d90dcdeeab2f1e357165 diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/context.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/context.go new file mode 100644 index 0000000..af747a1 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/context.go @@ -0,0 +1,1023 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "math" + "mime/multipart" + "net" + "net/http" + "net/url" + "os" + "strings" + "time" + + "github.com/gin-contrib/sse" + "github.com/gin-gonic/gin/binding" + "github.com/gin-gonic/gin/render" +) + +// Content-Type MIME of the most common data formats. +const ( + MIMEJSON = binding.MIMEJSON + MIMEHTML = binding.MIMEHTML + MIMEXML = binding.MIMEXML + MIMEXML2 = binding.MIMEXML2 + MIMEPlain = binding.MIMEPlain + MIMEPOSTForm = binding.MIMEPOSTForm + MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm + MIMEYAML = binding.MIMEYAML + BodyBytesKey = "_gin-gonic/gin/bodybyteskey" +) + +const abortIndex int8 = math.MaxInt8 / 2 + +// Context is the most important part of gin. It allows us to pass variables between middleware, +// manage the flow, validate the JSON of a request and render a JSON response for example. +type Context struct { + writermem responseWriter + Request *http.Request + Writer ResponseWriter + + Params Params + handlers HandlersChain + index int8 + + engine *Engine + + // Keys is a key/value pair exclusively for the context of each request. + Keys map[string]interface{} + + // Errors is a list of errors attached to all the handlers/middlewares who used this context. + Errors errorMsgs + + // Accepted defines a list of manually accepted formats for content negotiation. + Accepted []string +} + +/************************************/ +/********** CONTEXT CREATION ********/ +/************************************/ + +func (c *Context) reset() { + c.Writer = &c.writermem + c.Params = c.Params[0:0] + c.handlers = nil + c.index = -1 + c.Keys = nil + c.Errors = c.Errors[0:0] + c.Accepted = nil +} + +// Copy returns a copy of the current context that can be safely used outside the request's scope. +// This has to be used when the context has to be passed to a goroutine. +func (c *Context) Copy() *Context { + var cp = *c + cp.writermem.ResponseWriter = nil + cp.Writer = &cp.writermem + cp.index = abortIndex + cp.handlers = nil + cp.Keys = map[string]interface{}{} + for k, v := range c.Keys { + cp.Keys[k] = v + } + return &cp +} + +// HandlerName returns the main handler's name. For example if the handler is "handleGetUsers()", +// this function will return "main.handleGetUsers". +func (c *Context) HandlerName() string { + return nameOfFunction(c.handlers.Last()) +} + +// HandlerNames returns a list of all registered handlers for this context in descending order, +// following the semantics of HandlerName() +func (c *Context) HandlerNames() []string { + hn := make([]string, 0, len(c.handlers)) + for _, val := range c.handlers { + hn = append(hn, nameOfFunction(val)) + } + return hn +} + +// Handler returns the main handler. +func (c *Context) Handler() HandlerFunc { + return c.handlers.Last() +} + +/************************************/ +/*********** FLOW CONTROL ***********/ +/************************************/ + +// Next should be used only inside middleware. +// It executes the pending handlers in the chain inside the calling handler. +// See example in GitHub. +func (c *Context) Next() { + c.index++ + for c.index < int8(len(c.handlers)) { + c.handlers[c.index](c) + c.index++ + } +} + +// IsAborted returns true if the current context was aborted. +func (c *Context) IsAborted() bool { + return c.index >= abortIndex +} + +// Abort prevents pending handlers from being called. Note that this will not stop the current handler. +// Let's say you have an authorization middleware that validates that the current request is authorized. +// If the authorization fails (ex: the password does not match), call Abort to ensure the remaining handlers +// for this request are not called. +func (c *Context) Abort() { + c.index = abortIndex +} + +// AbortWithStatus calls `Abort()` and writes the headers with the specified status code. +// For example, a failed attempt to authenticate a request could use: context.AbortWithStatus(401). +func (c *Context) AbortWithStatus(code int) { + c.Status(code) + c.Writer.WriteHeaderNow() + c.Abort() +} + +// AbortWithStatusJSON calls `Abort()` and then `JSON` internally. +// This method stops the chain, writes the status code and return a JSON body. +// It also sets the Content-Type as "application/json". +func (c *Context) AbortWithStatusJSON(code int, jsonObj interface{}) { + c.Abort() + c.JSON(code, jsonObj) +} + +// AbortWithError calls `AbortWithStatus()` and `Error()` internally. +// This method stops the chain, writes the status code and pushes the specified error to `c.Errors`. +// See Context.Error() for more details. +func (c *Context) AbortWithError(code int, err error) *Error { + c.AbortWithStatus(code) + return c.Error(err) +} + +/************************************/ +/********* ERROR MANAGEMENT *********/ +/************************************/ + +// Error attaches an error to the current context. The error is pushed to a list of errors. +// It's a good idea to call Error for each error that occurred during the resolution of a request. +// A middleware can be used to collect all the errors and push them to a database together, +// print a log, or append it in the HTTP response. +// Error will panic if err is nil. +func (c *Context) Error(err error) *Error { + if err == nil { + panic("err is nil") + } + + parsedError, ok := err.(*Error) + if !ok { + parsedError = &Error{ + Err: err, + Type: ErrorTypePrivate, + } + } + + c.Errors = append(c.Errors, parsedError) + return parsedError +} + +/************************************/ +/******** METADATA MANAGEMENT********/ +/************************************/ + +// Set is used to store a new key/value pair exclusively for this context. +// It also lazy initializes c.Keys if it was not used previously. +func (c *Context) Set(key string, value interface{}) { + if c.Keys == nil { + c.Keys = make(map[string]interface{}) + } + c.Keys[key] = value +} + +// Get returns the value for the given key, ie: (value, true). +// If the value does not exists it returns (nil, false) +func (c *Context) Get(key string) (value interface{}, exists bool) { + value, exists = c.Keys[key] + return +} + +// MustGet returns the value for the given key if it exists, otherwise it panics. +func (c *Context) MustGet(key string) interface{} { + if value, exists := c.Get(key); exists { + return value + } + panic("Key \"" + key + "\" does not exist") +} + +// GetString returns the value associated with the key as a string. +func (c *Context) GetString(key string) (s string) { + if val, ok := c.Get(key); ok && val != nil { + s, _ = val.(string) + } + return +} + +// GetBool returns the value associated with the key as a boolean. +func (c *Context) GetBool(key string) (b bool) { + if val, ok := c.Get(key); ok && val != nil { + b, _ = val.(bool) + } + return +} + +// GetInt returns the value associated with the key as an integer. +func (c *Context) GetInt(key string) (i int) { + if val, ok := c.Get(key); ok && val != nil { + i, _ = val.(int) + } + return +} + +// GetInt64 returns the value associated with the key as an integer. +func (c *Context) GetInt64(key string) (i64 int64) { + if val, ok := c.Get(key); ok && val != nil { + i64, _ = val.(int64) + } + return +} + +// GetFloat64 returns the value associated with the key as a float64. +func (c *Context) GetFloat64(key string) (f64 float64) { + if val, ok := c.Get(key); ok && val != nil { + f64, _ = val.(float64) + } + return +} + +// GetTime returns the value associated with the key as time. +func (c *Context) GetTime(key string) (t time.Time) { + if val, ok := c.Get(key); ok && val != nil { + t, _ = val.(time.Time) + } + return +} + +// GetDuration returns the value associated with the key as a duration. +func (c *Context) GetDuration(key string) (d time.Duration) { + if val, ok := c.Get(key); ok && val != nil { + d, _ = val.(time.Duration) + } + return +} + +// GetStringSlice returns the value associated with the key as a slice of strings. +func (c *Context) GetStringSlice(key string) (ss []string) { + if val, ok := c.Get(key); ok && val != nil { + ss, _ = val.([]string) + } + return +} + +// GetStringMap returns the value associated with the key as a map of interfaces. +func (c *Context) GetStringMap(key string) (sm map[string]interface{}) { + if val, ok := c.Get(key); ok && val != nil { + sm, _ = val.(map[string]interface{}) + } + return +} + +// GetStringMapString returns the value associated with the key as a map of strings. +func (c *Context) GetStringMapString(key string) (sms map[string]string) { + if val, ok := c.Get(key); ok && val != nil { + sms, _ = val.(map[string]string) + } + return +} + +// GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings. +func (c *Context) GetStringMapStringSlice(key string) (smss map[string][]string) { + if val, ok := c.Get(key); ok && val != nil { + smss, _ = val.(map[string][]string) + } + return +} + +/************************************/ +/************ INPUT DATA ************/ +/************************************/ + +// Param returns the value of the URL param. +// It is a shortcut for c.Params.ByName(key) +// router.GET("/user/:id", func(c *gin.Context) { +// // a GET request to /user/john +// id := c.Param("id") // id == "john" +// }) +func (c *Context) Param(key string) string { + return c.Params.ByName(key) +} + +// Query returns the keyed url query value if it exists, +// otherwise it returns an empty string `("")`. +// It is shortcut for `c.Request.URL.Query().Get(key)` +// GET /path?id=1234&name=Manu&value= +// c.Query("id") == "1234" +// c.Query("name") == "Manu" +// c.Query("value") == "" +// c.Query("wtf") == "" +func (c *Context) Query(key string) string { + value, _ := c.GetQuery(key) + return value +} + +// DefaultQuery returns the keyed url query value if it exists, +// otherwise it returns the specified defaultValue string. +// See: Query() and GetQuery() for further information. +// GET /?name=Manu&lastname= +// c.DefaultQuery("name", "unknown") == "Manu" +// c.DefaultQuery("id", "none") == "none" +// c.DefaultQuery("lastname", "none") == "" +func (c *Context) DefaultQuery(key, defaultValue string) string { + if value, ok := c.GetQuery(key); ok { + return value + } + return defaultValue +} + +// GetQuery is like Query(), it returns the keyed url query value +// if it exists `(value, true)` (even when the value is an empty string), +// otherwise it returns `("", false)`. +// It is shortcut for `c.Request.URL.Query().Get(key)` +// GET /?name=Manu&lastname= +// ("Manu", true) == c.GetQuery("name") +// ("", false) == c.GetQuery("id") +// ("", true) == c.GetQuery("lastname") +func (c *Context) GetQuery(key string) (string, bool) { + if values, ok := c.GetQueryArray(key); ok { + return values[0], ok + } + return "", false +} + +// QueryArray returns a slice of strings for a given query key. +// The length of the slice depends on the number of params with the given key. +func (c *Context) QueryArray(key string) []string { + values, _ := c.GetQueryArray(key) + return values +} + +// GetQueryArray returns a slice of strings for a given query key, plus +// a boolean value whether at least one value exists for the given key. +func (c *Context) GetQueryArray(key string) ([]string, bool) { + if values, ok := c.Request.URL.Query()[key]; ok && len(values) > 0 { + return values, true + } + return []string{}, false +} + +// QueryMap returns a map for a given query key. +func (c *Context) QueryMap(key string) map[string]string { + dicts, _ := c.GetQueryMap(key) + return dicts +} + +// GetQueryMap returns a map for a given query key, plus a boolean value +// whether at least one value exists for the given key. +func (c *Context) GetQueryMap(key string) (map[string]string, bool) { + return c.get(c.Request.URL.Query(), key) +} + +// PostForm returns the specified key from a POST urlencoded form or multipart form +// when it exists, otherwise it returns an empty string `("")`. +func (c *Context) PostForm(key string) string { + value, _ := c.GetPostForm(key) + return value +} + +// DefaultPostForm returns the specified key from a POST urlencoded form or multipart form +// when it exists, otherwise it returns the specified defaultValue string. +// See: PostForm() and GetPostForm() for further information. +func (c *Context) DefaultPostForm(key, defaultValue string) string { + if value, ok := c.GetPostForm(key); ok { + return value + } + return defaultValue +} + +// GetPostForm is like PostForm(key). It returns the specified key from a POST urlencoded +// form or multipart form when it exists `(value, true)` (even when the value is an empty string), +// otherwise it returns ("", false). +// For example, during a PATCH request to update the user's email: +// email=mail@example.com --> ("mail@example.com", true) := GetPostForm("email") // set email to "mail@example.com" +// email= --> ("", true) := GetPostForm("email") // set email to "" +// --> ("", false) := GetPostForm("email") // do nothing with email +func (c *Context) GetPostForm(key string) (string, bool) { + if values, ok := c.GetPostFormArray(key); ok { + return values[0], ok + } + return "", false +} + +// PostFormArray returns a slice of strings for a given form key. +// The length of the slice depends on the number of params with the given key. +func (c *Context) PostFormArray(key string) []string { + values, _ := c.GetPostFormArray(key) + return values +} + +// GetPostFormArray returns a slice of strings for a given form key, plus +// a boolean value whether at least one value exists for the given key. +func (c *Context) GetPostFormArray(key string) ([]string, bool) { + req := c.Request + if err := req.ParseMultipartForm(c.engine.MaxMultipartMemory); err != nil { + if err != http.ErrNotMultipart { + debugPrint("error on parse multipart form array: %v", err) + } + } + if values := req.PostForm[key]; len(values) > 0 { + return values, true + } + return []string{}, false +} + +// PostFormMap returns a map for a given form key. +func (c *Context) PostFormMap(key string) map[string]string { + dicts, _ := c.GetPostFormMap(key) + return dicts +} + +// GetPostFormMap returns a map for a given form key, plus a boolean value +// whether at least one value exists for the given key. +func (c *Context) GetPostFormMap(key string) (map[string]string, bool) { + req := c.Request + if err := req.ParseMultipartForm(c.engine.MaxMultipartMemory); err != nil { + if err != http.ErrNotMultipart { + debugPrint("error on parse multipart form map: %v", err) + } + } + return c.get(req.PostForm, key) +} + +// get is an internal method and returns a map which satisfy conditions. +func (c *Context) get(m map[string][]string, key string) (map[string]string, bool) { + dicts := make(map[string]string) + exist := false + for k, v := range m { + if i := strings.IndexByte(k, '['); i >= 1 && k[0:i] == key { + if j := strings.IndexByte(k[i+1:], ']'); j >= 1 { + exist = true + dicts[k[i+1:][:j]] = v[0] + } + } + } + return dicts, exist +} + +// FormFile returns the first file for the provided form key. +func (c *Context) FormFile(name string) (*multipart.FileHeader, error) { + if c.Request.MultipartForm == nil { + if err := c.Request.ParseMultipartForm(c.engine.MaxMultipartMemory); err != nil { + return nil, err + } + } + _, fh, err := c.Request.FormFile(name) + return fh, err +} + +// MultipartForm is the parsed multipart form, including file uploads. +func (c *Context) MultipartForm() (*multipart.Form, error) { + err := c.Request.ParseMultipartForm(c.engine.MaxMultipartMemory) + return c.Request.MultipartForm, err +} + +// SaveUploadedFile uploads the form file to specific dst. +func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) error { + src, err := file.Open() + if err != nil { + return err + } + defer src.Close() + + out, err := os.Create(dst) + if err != nil { + return err + } + defer out.Close() + + _, err = io.Copy(out, src) + return err +} + +// Bind checks the Content-Type to select a binding engine automatically, +// Depending the "Content-Type" header different bindings are used: +// "application/json" --> JSON binding +// "application/xml" --> XML binding +// otherwise --> returns an error. +// It parses the request's body as JSON if Content-Type == "application/json" using JSON or XML as a JSON input. +// It decodes the json payload into the struct specified as a pointer. +// It writes a 400 error and sets Content-Type header "text/plain" in the response if input is not valid. +func (c *Context) Bind(obj interface{}) error { + b := binding.Default(c.Request.Method, c.ContentType()) + return c.MustBindWith(obj, b) +} + +// BindJSON is a shortcut for c.MustBindWith(obj, binding.JSON). +func (c *Context) BindJSON(obj interface{}) error { + return c.MustBindWith(obj, binding.JSON) +} + +// BindXML is a shortcut for c.MustBindWith(obj, binding.BindXML). +func (c *Context) BindXML(obj interface{}) error { + return c.MustBindWith(obj, binding.XML) +} + +// BindQuery is a shortcut for c.MustBindWith(obj, binding.Query). +func (c *Context) BindQuery(obj interface{}) error { + return c.MustBindWith(obj, binding.Query) +} + +// BindYAML is a shortcut for c.MustBindWith(obj, binding.YAML). +func (c *Context) BindYAML(obj interface{}) error { + return c.MustBindWith(obj, binding.YAML) +} + +// BindUri binds the passed struct pointer using binding.Uri. +// It will abort the request with HTTP 400 if any error occurs. +func (c *Context) BindUri(obj interface{}) error { + if err := c.ShouldBindUri(obj); err != nil { + c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck + return err + } + return nil +} + +// MustBindWith binds the passed struct pointer using the specified binding engine. +// It will abort the request with HTTP 400 if any error occurs. +// See the binding package. +func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error { + if err := c.ShouldBindWith(obj, b); err != nil { + c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck + return err + } + return nil +} + +// ShouldBind checks the Content-Type to select a binding engine automatically, +// Depending the "Content-Type" header different bindings are used: +// "application/json" --> JSON binding +// "application/xml" --> XML binding +// otherwise --> returns an error +// It parses the request's body as JSON if Content-Type == "application/json" using JSON or XML as a JSON input. +// It decodes the json payload into the struct specified as a pointer. +// Like c.Bind() but this method does not set the response status code to 400 and abort if the json is not valid. +func (c *Context) ShouldBind(obj interface{}) error { + b := binding.Default(c.Request.Method, c.ContentType()) + return c.ShouldBindWith(obj, b) +} + +// ShouldBindJSON is a shortcut for c.ShouldBindWith(obj, binding.JSON). +func (c *Context) ShouldBindJSON(obj interface{}) error { + return c.ShouldBindWith(obj, binding.JSON) +} + +// ShouldBindXML is a shortcut for c.ShouldBindWith(obj, binding.XML). +func (c *Context) ShouldBindXML(obj interface{}) error { + return c.ShouldBindWith(obj, binding.XML) +} + +// ShouldBindQuery is a shortcut for c.ShouldBindWith(obj, binding.Query). +func (c *Context) ShouldBindQuery(obj interface{}) error { + return c.ShouldBindWith(obj, binding.Query) +} + +// ShouldBindYAML is a shortcut for c.ShouldBindWith(obj, binding.YAML). +func (c *Context) ShouldBindYAML(obj interface{}) error { + return c.ShouldBindWith(obj, binding.YAML) +} + +// ShouldBindUri binds the passed struct pointer using the specified binding engine. +func (c *Context) ShouldBindUri(obj interface{}) error { + m := make(map[string][]string) + for _, v := range c.Params { + m[v.Key] = []string{v.Value} + } + return binding.Uri.BindUri(m, obj) +} + +// ShouldBindWith binds the passed struct pointer using the specified binding engine. +// See the binding package. +func (c *Context) ShouldBindWith(obj interface{}, b binding.Binding) error { + return b.Bind(c.Request, obj) +} + +// ShouldBindBodyWith is similar with ShouldBindWith, but it stores the request +// body into the context, and reuse when it is called again. +// +// NOTE: This method reads the body before binding. So you should use +// ShouldBindWith for better performance if you need to call only once. +func (c *Context) ShouldBindBodyWith(obj interface{}, bb binding.BindingBody) (err error) { + var body []byte + if cb, ok := c.Get(BodyBytesKey); ok { + if cbb, ok := cb.([]byte); ok { + body = cbb + } + } + if body == nil { + body, err = ioutil.ReadAll(c.Request.Body) + if err != nil { + return err + } + c.Set(BodyBytesKey, body) + } + return bb.BindBody(body, obj) +} + +// ClientIP implements a best effort algorithm to return the real client IP, it parses +// X-Real-IP and X-Forwarded-For in order to work properly with reverse-proxies such us: nginx or haproxy. +// Use X-Forwarded-For before X-Real-Ip as nginx uses X-Real-Ip with the proxy's IP. +func (c *Context) ClientIP() string { + if c.engine.ForwardedByClientIP { + clientIP := c.requestHeader("X-Forwarded-For") + clientIP = strings.TrimSpace(strings.Split(clientIP, ",")[0]) + if clientIP == "" { + clientIP = strings.TrimSpace(c.requestHeader("X-Real-Ip")) + } + if clientIP != "" { + return clientIP + } + } + + if c.engine.AppEngine { + if addr := c.requestHeader("X-Appengine-Remote-Addr"); addr != "" { + return addr + } + } + + if ip, _, err := net.SplitHostPort(strings.TrimSpace(c.Request.RemoteAddr)); err == nil { + return ip + } + + return "" +} + +// ContentType returns the Content-Type header of the request. +func (c *Context) ContentType() string { + return filterFlags(c.requestHeader("Content-Type")) +} + +// IsWebsocket returns true if the request headers indicate that a websocket +// handshake is being initiated by the client. +func (c *Context) IsWebsocket() bool { + if strings.Contains(strings.ToLower(c.requestHeader("Connection")), "upgrade") && + strings.ToLower(c.requestHeader("Upgrade")) == "websocket" { + return true + } + return false +} + +func (c *Context) requestHeader(key string) string { + return c.Request.Header.Get(key) +} + +/************************************/ +/******** RESPONSE RENDERING ********/ +/************************************/ + +// bodyAllowedForStatus is a copy of http.bodyAllowedForStatus non-exported function. +func bodyAllowedForStatus(status int) bool { + switch { + case status >= 100 && status <= 199: + return false + case status == http.StatusNoContent: + return false + case status == http.StatusNotModified: + return false + } + return true +} + +// Status sets the HTTP response code. +func (c *Context) Status(code int) { + c.writermem.WriteHeader(code) +} + +// Header is a intelligent shortcut for c.Writer.Header().Set(key, value). +// It writes a header in the response. +// If value == "", this method removes the header `c.Writer.Header().Del(key)` +func (c *Context) Header(key, value string) { + if value == "" { + c.Writer.Header().Del(key) + return + } + c.Writer.Header().Set(key, value) +} + +// GetHeader returns value from request headers. +func (c *Context) GetHeader(key string) string { + return c.requestHeader(key) +} + +// GetRawData return stream data. +func (c *Context) GetRawData() ([]byte, error) { + return ioutil.ReadAll(c.Request.Body) +} + +// SetCookie adds a Set-Cookie header to the ResponseWriter's headers. +// The provided cookie must have a valid Name. Invalid cookies may be +// silently dropped. +func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool) { + if path == "" { + path = "/" + } + http.SetCookie(c.Writer, &http.Cookie{ + Name: name, + Value: url.QueryEscape(value), + MaxAge: maxAge, + Path: path, + Domain: domain, + Secure: secure, + HttpOnly: httpOnly, + }) +} + +// Cookie returns the named cookie provided in the request or +// ErrNoCookie if not found. And return the named cookie is unescaped. +// If multiple cookies match the given name, only one cookie will +// be returned. +func (c *Context) Cookie(name string) (string, error) { + cookie, err := c.Request.Cookie(name) + if err != nil { + return "", err + } + val, _ := url.QueryUnescape(cookie.Value) + return val, nil +} + +// Render writes the response headers and calls render.Render to render data. +func (c *Context) Render(code int, r render.Render) { + c.Status(code) + + if !bodyAllowedForStatus(code) { + r.WriteContentType(c.Writer) + c.Writer.WriteHeaderNow() + return + } + + if err := r.Render(c.Writer); err != nil { + panic(err) + } +} + +// HTML renders the HTTP template specified by its file name. +// It also updates the HTTP code and sets the Content-Type as "text/html". +// See http://golang.org/doc/articles/wiki/ +func (c *Context) HTML(code int, name string, obj interface{}) { + instance := c.engine.HTMLRender.Instance(name, obj) + c.Render(code, instance) +} + +// IndentedJSON serializes the given struct as pretty JSON (indented + endlines) into the response body. +// It also sets the Content-Type as "application/json". +// WARNING: we recommend to use this only for development purposes since printing pretty JSON is +// more CPU and bandwidth consuming. Use Context.JSON() instead. +func (c *Context) IndentedJSON(code int, obj interface{}) { + c.Render(code, render.IndentedJSON{Data: obj}) +} + +// SecureJSON serializes the given struct as Secure JSON into the response body. +// Default prepends "while(1)," to response body if the given struct is array values. +// It also sets the Content-Type as "application/json". +func (c *Context) SecureJSON(code int, obj interface{}) { + c.Render(code, render.SecureJSON{Prefix: c.engine.secureJsonPrefix, Data: obj}) +} + +// JSONP serializes the given struct as JSON into the response body. +// It add padding to response body to request data from a server residing in a different domain than the client. +// It also sets the Content-Type as "application/javascript". +func (c *Context) JSONP(code int, obj interface{}) { + callback := c.DefaultQuery("callback", "") + if callback == "" { + c.Render(code, render.JSON{Data: obj}) + return + } + c.Render(code, render.JsonpJSON{Callback: callback, Data: obj}) +} + +// JSON serializes the given struct as JSON into the response body. +// It also sets the Content-Type as "application/json". +func (c *Context) JSON(code int, obj interface{}) { + c.Render(code, render.JSON{Data: obj}) +} + +// AsciiJSON serializes the given struct as JSON into the response body with unicode to ASCII string. +// It also sets the Content-Type as "application/json". +func (c *Context) AsciiJSON(code int, obj interface{}) { + c.Render(code, render.AsciiJSON{Data: obj}) +} + +// PureJSON serializes the given struct as JSON into the response body. +// PureJSON, unlike JSON, does not replace special html characters with their unicode entities. +func (c *Context) PureJSON(code int, obj interface{}) { + c.Render(code, render.PureJSON{Data: obj}) +} + +// XML serializes the given struct as XML into the response body. +// It also sets the Content-Type as "application/xml". +func (c *Context) XML(code int, obj interface{}) { + c.Render(code, render.XML{Data: obj}) +} + +// YAML serializes the given struct as YAML into the response body. +func (c *Context) YAML(code int, obj interface{}) { + c.Render(code, render.YAML{Data: obj}) +} + +// ProtoBuf serializes the given struct as ProtoBuf into the response body. +func (c *Context) ProtoBuf(code int, obj interface{}) { + c.Render(code, render.ProtoBuf{Data: obj}) +} + +// String writes the given string into the response body. +func (c *Context) String(code int, format string, values ...interface{}) { + c.Render(code, render.String{Format: format, Data: values}) +} + +// Redirect returns a HTTP redirect to the specific location. +func (c *Context) Redirect(code int, location string) { + c.Render(-1, render.Redirect{ + Code: code, + Location: location, + Request: c.Request, + }) +} + +// Data writes some data into the body stream and updates the HTTP code. +func (c *Context) Data(code int, contentType string, data []byte) { + c.Render(code, render.Data{ + ContentType: contentType, + Data: data, + }) +} + +// DataFromReader writes the specified reader into the body stream and updates the HTTP code. +func (c *Context) DataFromReader(code int, contentLength int64, contentType string, reader io.Reader, extraHeaders map[string]string) { + c.Render(code, render.Reader{ + Headers: extraHeaders, + ContentType: contentType, + ContentLength: contentLength, + Reader: reader, + }) +} + +// File writes the specified file into the body stream in a efficient way. +func (c *Context) File(filepath string) { + http.ServeFile(c.Writer, c.Request, filepath) +} + +// FileAttachment writes the specified file into the body stream in an efficient way +// On the client side, the file will typically be downloaded with the given filename +func (c *Context) FileAttachment(filepath, filename string) { + c.Writer.Header().Set("content-disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename)) + http.ServeFile(c.Writer, c.Request, filepath) +} + +// SSEvent writes a Server-Sent Event into the body stream. +func (c *Context) SSEvent(name string, message interface{}) { + c.Render(-1, sse.Event{ + Event: name, + Data: message, + }) +} + +// Stream sends a streaming response and returns a boolean +// indicates "Is client disconnected in middle of stream" +func (c *Context) Stream(step func(w io.Writer) bool) bool { + w := c.Writer + clientGone := w.CloseNotify() + for { + select { + case <-clientGone: + return true + default: + keepOpen := step(w) + w.Flush() + if !keepOpen { + return false + } + } + } +} + +/************************************/ +/******** CONTENT NEGOTIATION *******/ +/************************************/ + +// Negotiate contains all negotiations data. +type Negotiate struct { + Offered []string + HTMLName string + HTMLData interface{} + JSONData interface{} + XMLData interface{} + Data interface{} +} + +// Negotiate calls different Render according acceptable Accept format. +func (c *Context) Negotiate(code int, config Negotiate) { + switch c.NegotiateFormat(config.Offered...) { + case binding.MIMEJSON: + data := chooseData(config.JSONData, config.Data) + c.JSON(code, data) + + case binding.MIMEHTML: + data := chooseData(config.HTMLData, config.Data) + c.HTML(code, config.HTMLName, data) + + case binding.MIMEXML: + data := chooseData(config.XMLData, config.Data) + c.XML(code, data) + + default: + c.AbortWithError(http.StatusNotAcceptable, errors.New("the accepted formats are not offered by the server")) // nolint: errcheck + } +} + +// NegotiateFormat returns an acceptable Accept format. +func (c *Context) NegotiateFormat(offered ...string) string { + assert1(len(offered) > 0, "you must provide at least one offer") + + if c.Accepted == nil { + c.Accepted = parseAccept(c.requestHeader("Accept")) + } + if len(c.Accepted) == 0 { + return offered[0] + } + for _, accepted := range c.Accepted { + for _, offert := range offered { + // According to RFC 2616 and RFC 2396, non-ASCII characters are not allowed in headers, + // therefore we can just iterate over the string without casting it into []rune + i := 0 + for ; i < len(accepted); i++ { + if accepted[i] == '*' || offert[i] == '*' { + return offert + } + if accepted[i] != offert[i] { + break + } + } + if i == len(accepted) { + return offert + } + } + } + return "" +} + +// SetAccepted sets Accept header data. +func (c *Context) SetAccepted(formats ...string) { + c.Accepted = formats +} + +/************************************/ +/***** GOLANG.ORG/X/NET/CONTEXT *****/ +/************************************/ + +// Deadline returns the time when work done on behalf of this context +// should be canceled. Deadline returns ok==false when no deadline is +// set. Successive calls to Deadline return the same results. +func (c *Context) Deadline() (deadline time.Time, ok bool) { + return +} + +// Done returns a channel that's closed when work done on behalf of this +// context should be canceled. Done may return nil if this context can +// never be canceled. Successive calls to Done return the same value. +func (c *Context) Done() <-chan struct{} { + return nil +} + +// Err returns a non-nil error value after Done is closed, +// successive calls to Err return the same error. +// If Done is not yet closed, Err returns nil. +// If Done is closed, Err returns a non-nil error explaining why: +// Canceled if the context was canceled +// or DeadlineExceeded if the context's deadline passed. +func (c *Context) Err() error { + return nil +} + +// Value returns the value associated with this context for key, or nil +// if no value is associated with key. Successive calls to Value with +// the same key returns the same result. +func (c *Context) Value(key interface{}) interface{} { + if key == 0 { + return c.Request + } + if keyAsString, ok := key.(string); ok { + val, _ := c.Get(keyAsString) + return val + } + return nil +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/context_appengine.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/context_appengine.go new file mode 100644 index 0000000..38c189a --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/context_appengine.go @@ -0,0 +1,11 @@ +// +build appengine + +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +func init() { + defaultAppEngine = true +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/debug.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/debug.go new file mode 100644 index 0000000..6d40a5d --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/debug.go @@ -0,0 +1,103 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import ( + "bytes" + "fmt" + "html/template" + "os" + "runtime" + "strconv" + "strings" +) + +const ginSupportMinGoVer = 8 + +// IsDebugging returns true if the framework is running in debug mode. +// Use SetMode(gin.ReleaseMode) to disable debug mode. +func IsDebugging() bool { + return ginMode == debugCode +} + +// DebugPrintRouteFunc indicates debug log output format. +var DebugPrintRouteFunc func(httpMethod, absolutePath, handlerName string, nuHandlers int) + +func debugPrintRoute(httpMethod, absolutePath string, handlers HandlersChain) { + if IsDebugging() { + nuHandlers := len(handlers) + handlerName := nameOfFunction(handlers.Last()) + if DebugPrintRouteFunc == nil { + debugPrint("%-6s %-25s --> %s (%d handlers)\n", httpMethod, absolutePath, handlerName, nuHandlers) + } else { + DebugPrintRouteFunc(httpMethod, absolutePath, handlerName, nuHandlers) + } + } +} + +func debugPrintLoadTemplate(tmpl *template.Template) { + if IsDebugging() { + var buf bytes.Buffer + for _, tmpl := range tmpl.Templates() { + buf.WriteString("\t- ") + buf.WriteString(tmpl.Name()) + buf.WriteString("\n") + } + debugPrint("Loaded HTML Templates (%d): \n%s\n", len(tmpl.Templates()), buf.String()) + } +} + +func debugPrint(format string, values ...interface{}) { + if IsDebugging() { + if !strings.HasSuffix(format, "\n") { + format += "\n" + } + fmt.Fprintf(os.Stderr, "[GIN-debug] "+format, values...) + } +} + +func getMinVer(v string) (uint64, error) { + first := strings.IndexByte(v, '.') + last := strings.LastIndexByte(v, '.') + if first == last { + return strconv.ParseUint(v[first+1:], 10, 64) + } + return strconv.ParseUint(v[first+1:last], 10, 64) +} + +func debugPrintWARNINGDefault() { + if v, e := getMinVer(runtime.Version()); e == nil && v <= ginSupportMinGoVer { + debugPrint(`[WARNING] Now Gin requires Go 1.8 or later and Go 1.9 will be required soon. + +`) + } + debugPrint(`[WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached. + +`) +} + +func debugPrintWARNINGNew() { + debugPrint(`[WARNING] Running in "debug" mode. Switch to "release" mode in production. + - using env: export GIN_MODE=release + - using code: gin.SetMode(gin.ReleaseMode) + +`) +} + +func debugPrintWARNINGSetHTMLTemplate() { + debugPrint(`[WARNING] Since SetHTMLTemplate() is NOT thread-safe. It should only be called +at initialization. ie. before any route is registered or the router is listening in a socket: + + router := gin.Default() + router.SetHTMLTemplate(template) // << good place + +`) +} + +func debugPrintError(err error) { + if err != nil { + debugPrint("[ERROR] %v\n", err) + } +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/deprecated.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/deprecated.go new file mode 100644 index 0000000..ab44742 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/deprecated.go @@ -0,0 +1,21 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import ( + "log" + + "github.com/gin-gonic/gin/binding" +) + +// BindWith binds the passed struct pointer using the specified binding engine. +// See the binding package. +func (c *Context) BindWith(obj interface{}, b binding.Binding) error { + log.Println(`BindWith(\"interface{}, binding.Binding\") error is going to + be deprecated, please check issue #662 and either use MustBindWith() if you + want HTTP 400 to be automatically returned if any error occur, or use + ShouldBindWith() if you need to manage the error.`) + return c.MustBindWith(obj, b) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/doc.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/doc.go new file mode 100644 index 0000000..1bd0386 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/doc.go @@ -0,0 +1,6 @@ +/* +Package gin implements a HTTP web framework called gin. + +See https://gin-gonic.com/ for more information about gin. +*/ +package gin // import "github.com/gin-gonic/gin" diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/errors.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/errors.go new file mode 100644 index 0000000..6070ff5 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/errors.go @@ -0,0 +1,169 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import ( + "bytes" + "fmt" + "reflect" + + "github.com/gin-gonic/gin/internal/json" +) + +// ErrorType is an unsigned 64-bit error code as defined in the gin spec. +type ErrorType uint64 + +const ( + // ErrorTypeBind is used when Context.Bind() fails. + ErrorTypeBind ErrorType = 1 << 63 + // ErrorTypeRender is used when Context.Render() fails. + ErrorTypeRender ErrorType = 1 << 62 + // ErrorTypePrivate indicates a private error. + ErrorTypePrivate ErrorType = 1 << 0 + // ErrorTypePublic indicates a public error. + ErrorTypePublic ErrorType = 1 << 1 + // ErrorTypeAny indicates any other error. + ErrorTypeAny ErrorType = 1<<64 - 1 + // ErrorTypeNu indicates any other error. + ErrorTypeNu = 2 +) + +// Error represents a error's specification. +type Error struct { + Err error + Type ErrorType + Meta interface{} +} + +type errorMsgs []*Error + +var _ error = &Error{} + +// SetType sets the error's type. +func (msg *Error) SetType(flags ErrorType) *Error { + msg.Type = flags + return msg +} + +// SetMeta sets the error's meta data. +func (msg *Error) SetMeta(data interface{}) *Error { + msg.Meta = data + return msg +} + +// JSON creates a properly formatted JSON +func (msg *Error) JSON() interface{} { + json := H{} + if msg.Meta != nil { + value := reflect.ValueOf(msg.Meta) + switch value.Kind() { + case reflect.Struct: + return msg.Meta + case reflect.Map: + for _, key := range value.MapKeys() { + json[key.String()] = value.MapIndex(key).Interface() + } + default: + json["meta"] = msg.Meta + } + } + if _, ok := json["error"]; !ok { + json["error"] = msg.Error() + } + return json +} + +// MarshalJSON implements the json.Marshaller interface. +func (msg *Error) MarshalJSON() ([]byte, error) { + return json.Marshal(msg.JSON()) +} + +// Error implements the error interface. +func (msg Error) Error() string { + return msg.Err.Error() +} + +// IsType judges one error. +func (msg *Error) IsType(flags ErrorType) bool { + return (msg.Type & flags) > 0 +} + +// ByType returns a readonly copy filtered the byte. +// ie ByType(gin.ErrorTypePublic) returns a slice of errors with type=ErrorTypePublic. +func (a errorMsgs) ByType(typ ErrorType) errorMsgs { + if len(a) == 0 { + return nil + } + if typ == ErrorTypeAny { + return a + } + var result errorMsgs + for _, msg := range a { + if msg.IsType(typ) { + result = append(result, msg) + } + } + return result +} + +// Last returns the last error in the slice. It returns nil if the array is empty. +// Shortcut for errors[len(errors)-1]. +func (a errorMsgs) Last() *Error { + if length := len(a); length > 0 { + return a[length-1] + } + return nil +} + +// Errors returns an array will all the error messages. +// Example: +// c.Error(errors.New("first")) +// c.Error(errors.New("second")) +// c.Error(errors.New("third")) +// c.Errors.Errors() // == []string{"first", "second", "third"} +func (a errorMsgs) Errors() []string { + if len(a) == 0 { + return nil + } + errorStrings := make([]string, len(a)) + for i, err := range a { + errorStrings[i] = err.Error() + } + return errorStrings +} + +func (a errorMsgs) JSON() interface{} { + switch len(a) { + case 0: + return nil + case 1: + return a.Last().JSON() + default: + json := make([]interface{}, len(a)) + for i, err := range a { + json[i] = err.JSON() + } + return json + } +} + +// MarshalJSON implements the json.Marshaller interface. +func (a errorMsgs) MarshalJSON() ([]byte, error) { + return json.Marshal(a.JSON()) +} + +func (a errorMsgs) String() string { + if len(a) == 0 { + return "" + } + var buffer bytes.Buffer + for i, msg := range a { + fmt.Fprintf(&buffer, "Error #%02d: %s\n", i+1, msg.Err) + if msg.Meta != nil { + fmt.Fprintf(&buffer, " Meta: %v\n", msg.Meta) + } + } + return buffer.String() +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/fs.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/fs.go new file mode 100644 index 0000000..7a6738a --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/fs.go @@ -0,0 +1,45 @@ +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import ( + "net/http" + "os" +) + +type onlyfilesFS struct { + fs http.FileSystem +} + +type neuteredReaddirFile struct { + http.File +} + +// Dir returns a http.Filesystem that can be used by http.FileServer(). It is used internally +// in router.Static(). +// if listDirectory == true, then it works the same as http.Dir() otherwise it returns +// a filesystem that prevents http.FileServer() to list the directory files. +func Dir(root string, listDirectory bool) http.FileSystem { + fs := http.Dir(root) + if listDirectory { + return fs + } + return &onlyfilesFS{fs} +} + +// Open conforms to http.Filesystem. +func (fs onlyfilesFS) Open(name string) (http.File, error) { + f, err := fs.fs.Open(name) + if err != nil { + return nil, err + } + return neuteredReaddirFile{f}, nil +} + +// Readdir overrides the http.File default implementation. +func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) { + // this disables directory listing + return nil, nil +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/gin.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/gin.go new file mode 100644 index 0000000..4dbe983 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/gin.go @@ -0,0 +1,477 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import ( + "fmt" + "html/template" + "net" + "net/http" + "os" + "path" + "sync" + + "github.com/gin-gonic/gin/render" +) + +const defaultMultipartMemory = 32 << 20 // 32 MB + +var ( + default404Body = []byte("404 page not found") + default405Body = []byte("405 method not allowed") + defaultAppEngine bool +) + +// HandlerFunc defines the handler used by gin middleware as return value. +type HandlerFunc func(*Context) + +// HandlersChain defines a HandlerFunc array. +type HandlersChain []HandlerFunc + +// Last returns the last handler in the chain. ie. the last handler is the main own. +func (c HandlersChain) Last() HandlerFunc { + if length := len(c); length > 0 { + return c[length-1] + } + return nil +} + +// RouteInfo represents a request route's specification which contains method and path and its handler. +type RouteInfo struct { + Method string + Path string + Handler string + HandlerFunc HandlerFunc +} + +// RoutesInfo defines a RouteInfo array. +type RoutesInfo []RouteInfo + +// Engine is the framework's instance, it contains the muxer, middleware and configuration settings. +// Create an instance of Engine, by using New() or Default() +type Engine struct { + RouterGroup + + // Enables automatic redirection if the current route can't be matched but a + // handler for the path with (without) the trailing slash exists. + // For example if /foo/ is requested but a route only exists for /foo, the + // client is redirected to /foo with http status code 301 for GET requests + // and 307 for all other request methods. + RedirectTrailingSlash bool + + // If enabled, the router tries to fix the current request path, if no + // handle is registered for it. + // First superfluous path elements like ../ or // are removed. + // Afterwards the router does a case-insensitive lookup of the cleaned path. + // If a handle can be found for this route, the router makes a redirection + // to the corrected path with status code 301 for GET requests and 307 for + // all other request methods. + // For example /FOO and /..//Foo could be redirected to /foo. + // RedirectTrailingSlash is independent of this option. + RedirectFixedPath bool + + // If enabled, the router checks if another method is allowed for the + // current route, if the current request can not be routed. + // If this is the case, the request is answered with 'Method Not Allowed' + // and HTTP status code 405. + // If no other Method is allowed, the request is delegated to the NotFound + // handler. + HandleMethodNotAllowed bool + ForwardedByClientIP bool + + // #726 #755 If enabled, it will thrust some headers starting with + // 'X-AppEngine...' for better integration with that PaaS. + AppEngine bool + + // If enabled, the url.RawPath will be used to find parameters. + UseRawPath bool + + // If true, the path value will be unescaped. + // If UseRawPath is false (by default), the UnescapePathValues effectively is true, + // as url.Path gonna be used, which is already unescaped. + UnescapePathValues bool + + // Value of 'maxMemory' param that is given to http.Request's ParseMultipartForm + // method call. + MaxMultipartMemory int64 + + delims render.Delims + secureJsonPrefix string + HTMLRender render.HTMLRender + FuncMap template.FuncMap + allNoRoute HandlersChain + allNoMethod HandlersChain + noRoute HandlersChain + noMethod HandlersChain + pool sync.Pool + trees methodTrees +} + +var _ IRouter = &Engine{} + +// New returns a new blank Engine instance without any middleware attached. +// By default the configuration is: +// - RedirectTrailingSlash: true +// - RedirectFixedPath: false +// - HandleMethodNotAllowed: false +// - ForwardedByClientIP: true +// - UseRawPath: false +// - UnescapePathValues: true +func New() *Engine { + debugPrintWARNINGNew() + engine := &Engine{ + RouterGroup: RouterGroup{ + Handlers: nil, + basePath: "/", + root: true, + }, + FuncMap: template.FuncMap{}, + RedirectTrailingSlash: true, + RedirectFixedPath: false, + HandleMethodNotAllowed: false, + ForwardedByClientIP: true, + AppEngine: defaultAppEngine, + UseRawPath: false, + UnescapePathValues: true, + MaxMultipartMemory: defaultMultipartMemory, + trees: make(methodTrees, 0, 9), + delims: render.Delims{Left: "{{", Right: "}}"}, + secureJsonPrefix: "while(1);", + } + engine.RouterGroup.engine = engine + engine.pool.New = func() interface{} { + return engine.allocateContext() + } + return engine +} + +// Default returns an Engine instance with the Logger and Recovery middleware already attached. +func Default() *Engine { + debugPrintWARNINGDefault() + engine := New() + engine.Use(Logger(), Recovery()) + return engine +} + +func (engine *Engine) allocateContext() *Context { + return &Context{engine: engine} +} + +// Delims sets template left and right delims and returns a Engine instance. +func (engine *Engine) Delims(left, right string) *Engine { + engine.delims = render.Delims{Left: left, Right: right} + return engine +} + +// SecureJsonPrefix sets the secureJsonPrefix used in Context.SecureJSON. +func (engine *Engine) SecureJsonPrefix(prefix string) *Engine { + engine.secureJsonPrefix = prefix + return engine +} + +// LoadHTMLGlob loads HTML files identified by glob pattern +// and associates the result with HTML renderer. +func (engine *Engine) LoadHTMLGlob(pattern string) { + left := engine.delims.Left + right := engine.delims.Right + templ := template.Must(template.New("").Delims(left, right).Funcs(engine.FuncMap).ParseGlob(pattern)) + + if IsDebugging() { + debugPrintLoadTemplate(templ) + engine.HTMLRender = render.HTMLDebug{Glob: pattern, FuncMap: engine.FuncMap, Delims: engine.delims} + return + } + + engine.SetHTMLTemplate(templ) +} + +// LoadHTMLFiles loads a slice of HTML files +// and associates the result with HTML renderer. +func (engine *Engine) LoadHTMLFiles(files ...string) { + if IsDebugging() { + engine.HTMLRender = render.HTMLDebug{Files: files, FuncMap: engine.FuncMap, Delims: engine.delims} + return + } + + templ := template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).Funcs(engine.FuncMap).ParseFiles(files...)) + engine.SetHTMLTemplate(templ) +} + +// SetHTMLTemplate associate a template with HTML renderer. +func (engine *Engine) SetHTMLTemplate(templ *template.Template) { + if len(engine.trees) > 0 { + debugPrintWARNINGSetHTMLTemplate() + } + + engine.HTMLRender = render.HTMLProduction{Template: templ.Funcs(engine.FuncMap)} +} + +// SetFuncMap sets the FuncMap used for template.FuncMap. +func (engine *Engine) SetFuncMap(funcMap template.FuncMap) { + engine.FuncMap = funcMap +} + +// NoRoute adds handlers for NoRoute. It return a 404 code by default. +func (engine *Engine) NoRoute(handlers ...HandlerFunc) { + engine.noRoute = handlers + engine.rebuild404Handlers() +} + +// NoMethod sets the handlers called when... TODO. +func (engine *Engine) NoMethod(handlers ...HandlerFunc) { + engine.noMethod = handlers + engine.rebuild405Handlers() +} + +// Use attaches a global middleware to the router. ie. the middleware attached though Use() will be +// included in the handlers chain for every single request. Even 404, 405, static files... +// For example, this is the right place for a logger or error management middleware. +func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes { + engine.RouterGroup.Use(middleware...) + engine.rebuild404Handlers() + engine.rebuild405Handlers() + return engine +} + +func (engine *Engine) rebuild404Handlers() { + engine.allNoRoute = engine.combineHandlers(engine.noRoute) +} + +func (engine *Engine) rebuild405Handlers() { + engine.allNoMethod = engine.combineHandlers(engine.noMethod) +} + +func (engine *Engine) addRoute(method, path string, handlers HandlersChain) { + assert1(path[0] == '/', "path must begin with '/'") + assert1(method != "", "HTTP method can not be empty") + assert1(len(handlers) > 0, "there must be at least one handler") + + debugPrintRoute(method, path, handlers) + root := engine.trees.get(method) + if root == nil { + root = new(node) + engine.trees = append(engine.trees, methodTree{method: method, root: root}) + } + root.addRoute(path, handlers) +} + +// Routes returns a slice of registered routes, including some useful information, such as: +// the http method, path and the handler name. +func (engine *Engine) Routes() (routes RoutesInfo) { + for _, tree := range engine.trees { + routes = iterate("", tree.method, routes, tree.root) + } + return routes +} + +func iterate(path, method string, routes RoutesInfo, root *node) RoutesInfo { + path += root.path + if len(root.handlers) > 0 { + handlerFunc := root.handlers.Last() + routes = append(routes, RouteInfo{ + Method: method, + Path: path, + Handler: nameOfFunction(handlerFunc), + HandlerFunc: handlerFunc, + }) + } + for _, child := range root.children { + routes = iterate(path, method, routes, child) + } + return routes +} + +// Run attaches the router to a http.Server and starts listening and serving HTTP requests. +// It is a shortcut for http.ListenAndServe(addr, router) +// Note: this method will block the calling goroutine indefinitely unless an error happens. +func (engine *Engine) Run(addr ...string) (err error) { + defer func() { debugPrintError(err) }() + + address := resolveAddress(addr) + debugPrint("Listening and serving HTTP on %s\n", address) + err = http.ListenAndServe(address, engine) + return +} + +// RunTLS attaches the router to a http.Server and starts listening and serving HTTPS (secure) requests. +// It is a shortcut for http.ListenAndServeTLS(addr, certFile, keyFile, router) +// Note: this method will block the calling goroutine indefinitely unless an error happens. +func (engine *Engine) RunTLS(addr, certFile, keyFile string) (err error) { + debugPrint("Listening and serving HTTPS on %s\n", addr) + defer func() { debugPrintError(err) }() + + err = http.ListenAndServeTLS(addr, certFile, keyFile, engine) + return +} + +// RunUnix attaches the router to a http.Server and starts listening and serving HTTP requests +// through the specified unix socket (ie. a file). +// Note: this method will block the calling goroutine indefinitely unless an error happens. +func (engine *Engine) RunUnix(file string) (err error) { + debugPrint("Listening and serving HTTP on unix:/%s", file) + defer func() { debugPrintError(err) }() + + os.Remove(file) + listener, err := net.Listen("unix", file) + if err != nil { + return + } + defer listener.Close() + os.Chmod(file, 0777) + err = http.Serve(listener, engine) + return +} + +// RunFd attaches the router to a http.Server and starts listening and serving HTTP requests +// through the specified file descriptor. +// Note: this method will block the calling goroutine indefinitely unless an error happens. +func (engine *Engine) RunFd(fd int) (err error) { + debugPrint("Listening and serving HTTP on fd@%d", fd) + defer func() { debugPrintError(err) }() + + f := os.NewFile(uintptr(fd), fmt.Sprintf("fd@%d", fd)) + listener, err := net.FileListener(f) + if err != nil { + return + } + defer listener.Close() + err = http.Serve(listener, engine) + return +} + +// ServeHTTP conforms to the http.Handler interface. +func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) { + c := engine.pool.Get().(*Context) + c.writermem.reset(w) + c.Request = req + c.reset() + + engine.handleHTTPRequest(c) + + engine.pool.Put(c) +} + +// HandleContext re-enter a context that has been rewritten. +// This can be done by setting c.Request.URL.Path to your new target. +// Disclaimer: You can loop yourself to death with this, use wisely. +func (engine *Engine) HandleContext(c *Context) { + oldIndexValue := c.index + c.reset() + engine.handleHTTPRequest(c) + + c.index = oldIndexValue +} + +func (engine *Engine) handleHTTPRequest(c *Context) { + httpMethod := c.Request.Method + rPath := c.Request.URL.Path + unescape := false + if engine.UseRawPath && len(c.Request.URL.RawPath) > 0 { + rPath = c.Request.URL.RawPath + unescape = engine.UnescapePathValues + } + rPath = cleanPath(rPath) + + // Find root of the tree for the given HTTP method + t := engine.trees + for i, tl := 0, len(t); i < tl; i++ { + if t[i].method != httpMethod { + continue + } + root := t[i].root + // Find route in tree + handlers, params, tsr := root.getValue(rPath, c.Params, unescape) + if handlers != nil { + c.handlers = handlers + c.Params = params + c.Next() + c.writermem.WriteHeaderNow() + return + } + if httpMethod != "CONNECT" && rPath != "/" { + if tsr && engine.RedirectTrailingSlash { + redirectTrailingSlash(c) + return + } + if engine.RedirectFixedPath && redirectFixedPath(c, root, engine.RedirectFixedPath) { + return + } + } + break + } + + if engine.HandleMethodNotAllowed { + for _, tree := range engine.trees { + if tree.method == httpMethod { + continue + } + if handlers, _, _ := tree.root.getValue(rPath, nil, unescape); handlers != nil { + c.handlers = engine.allNoMethod + serveError(c, http.StatusMethodNotAllowed, default405Body) + return + } + } + } + c.handlers = engine.allNoRoute + serveError(c, http.StatusNotFound, default404Body) +} + +var mimePlain = []string{MIMEPlain} + +func serveError(c *Context, code int, defaultMessage []byte) { + c.writermem.status = code + c.Next() + if c.writermem.Written() { + return + } + if c.writermem.Status() == code { + c.writermem.Header()["Content-Type"] = mimePlain + _, err := c.Writer.Write(defaultMessage) + if err != nil { + debugPrint("cannot write message to writer during serve error: %v", err) + } + return + } + c.writermem.WriteHeaderNow() + return +} + +func redirectTrailingSlash(c *Context) { + req := c.Request + p := req.URL.Path + if prefix := path.Clean(c.Request.Header.Get("X-Forwarded-Prefix")); prefix != "." { + p = prefix + "/" + req.URL.Path + } + code := http.StatusMovedPermanently // Permanent redirect, request with GET method + if req.Method != "GET" { + code = http.StatusTemporaryRedirect + } + + req.URL.Path = p + "/" + if length := len(p); length > 1 && p[length-1] == '/' { + req.URL.Path = p[:length-1] + } + debugPrint("redirecting request %d: %s --> %s", code, p, req.URL.String()) + http.Redirect(c.Writer, req, req.URL.String(), code) + c.writermem.WriteHeaderNow() +} + +func redirectFixedPath(c *Context, root *node, trailingSlash bool) bool { + req := c.Request + rPath := req.URL.Path + + if fixedPath, ok := root.findCaseInsensitivePath(cleanPath(rPath), trailingSlash); ok { + code := http.StatusMovedPermanently // Permanent redirect, request with GET method + if req.Method != "GET" { + code = http.StatusTemporaryRedirect + } + req.URL.Path = string(fixedPath) + debugPrint("redirecting request %d: %s --> %s", code, rPath, req.URL.String()) + http.Redirect(c.Writer, req, req.URL.String(), code) + c.writermem.WriteHeaderNow() + return true + } + return false +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/go.mod b/go/src/themaru/vendor/github.com/gin-gonic/gin/go.mod new file mode 100644 index 0000000..1c5e995 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/go.mod @@ -0,0 +1,18 @@ +module github.com/gin-gonic/gin + +go 1.12 + +require ( + github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 + github.com/golang/protobuf v1.3.1 + github.com/json-iterator/go v1.1.6 + github.com/mattn/go-isatty v0.0.7 + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/stretchr/testify v1.3.0 + github.com/ugorji/go v1.1.4 + golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c + gopkg.in/go-playground/assert.v1 v1.2.1 // indirect + gopkg.in/go-playground/validator.v8 v8.18.2 + gopkg.in/yaml.v2 v2.2.2 +) diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/go.sum b/go/src/themaru/vendor/github.com/gin-gonic/gin/go.sum new file mode 100644 index 0000000..5810468 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/go.sum @@ -0,0 +1,36 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 h1:t8FVkw33L+wilf2QiWkw0UV77qRpcH/JHPKGpKa2E8g= +github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/internal/json/json.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/internal/json/json.go new file mode 100644 index 0000000..480e8bf --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/internal/json/json.go @@ -0,0 +1,22 @@ +// Copyright 2017 Bo-Yi Wu. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +// +build !jsoniter + +package json + +import "encoding/json" + +var ( + // Marshal is exported by gin/json package. + Marshal = json.Marshal + // Unmarshal is exported by gin/json package. + Unmarshal = json.Unmarshal + // MarshalIndent is exported by gin/json package. + MarshalIndent = json.MarshalIndent + // NewDecoder is exported by gin/json package. + NewDecoder = json.NewDecoder + // NewEncoder is exported by gin/json package. + NewEncoder = json.NewEncoder +) diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/internal/json/jsoniter.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/internal/json/jsoniter.go new file mode 100644 index 0000000..fabd7b8 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/internal/json/jsoniter.go @@ -0,0 +1,23 @@ +// Copyright 2017 Bo-Yi Wu. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +// +build jsoniter + +package json + +import "github.com/json-iterator/go" + +var ( + json = jsoniter.ConfigCompatibleWithStandardLibrary + // Marshal is exported by gin/json package. + Marshal = json.Marshal + // Unmarshal is exported by gin/json package. + Unmarshal = json.Unmarshal + // MarshalIndent is exported by gin/json package. + MarshalIndent = json.MarshalIndent + // NewDecoder is exported by gin/json package. + NewDecoder = json.NewDecoder + // NewEncoder is exported by gin/json package. + NewEncoder = json.NewEncoder +) diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/logger.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/logger.go new file mode 100644 index 0000000..5ab4639 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/logger.go @@ -0,0 +1,270 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import ( + "fmt" + "io" + "net/http" + "os" + "time" + + "github.com/mattn/go-isatty" +) + +type consoleColorModeValue int + +const ( + autoColor consoleColorModeValue = iota + disableColor + forceColor +) + +var ( + green = string([]byte{27, 91, 57, 55, 59, 52, 50, 109}) + white = string([]byte{27, 91, 57, 48, 59, 52, 55, 109}) + yellow = string([]byte{27, 91, 57, 48, 59, 52, 51, 109}) + red = string([]byte{27, 91, 57, 55, 59, 52, 49, 109}) + blue = string([]byte{27, 91, 57, 55, 59, 52, 52, 109}) + magenta = string([]byte{27, 91, 57, 55, 59, 52, 53, 109}) + cyan = string([]byte{27, 91, 57, 55, 59, 52, 54, 109}) + reset = string([]byte{27, 91, 48, 109}) + consoleColorMode = autoColor +) + +// LoggerConfig defines the config for Logger middleware. +type LoggerConfig struct { + // Optional. Default value is gin.defaultLogFormatter + Formatter LogFormatter + + // Output is a writer where logs are written. + // Optional. Default value is gin.DefaultWriter. + Output io.Writer + + // SkipPaths is a url path array which logs are not written. + // Optional. + SkipPaths []string +} + +// LogFormatter gives the signature of the formatter function passed to LoggerWithFormatter +type LogFormatter func(params LogFormatterParams) string + +// LogFormatterParams is the structure any formatter will be handed when time to log comes +type LogFormatterParams struct { + Request *http.Request + + // TimeStamp shows the time after the server returns a response. + TimeStamp time.Time + // StatusCode is HTTP response code. + StatusCode int + // Latency is how much time the server cost to process a certain request. + Latency time.Duration + // ClientIP equals Context's ClientIP method. + ClientIP string + // Method is the HTTP method given to the request. + Method string + // Path is a path the client requests. + Path string + // ErrorMessage is set if error has occurred in processing the request. + ErrorMessage string + // isTerm shows whether does gin's output descriptor refers to a terminal. + isTerm bool + // BodySize is the size of the Response Body + BodySize int + // Keys are the keys set on the request's context. + Keys map[string]interface{} +} + +// StatusCodeColor is the ANSI color for appropriately logging http status code to a terminal. +func (p *LogFormatterParams) StatusCodeColor() string { + code := p.StatusCode + + switch { + case code >= http.StatusOK && code < http.StatusMultipleChoices: + return green + case code >= http.StatusMultipleChoices && code < http.StatusBadRequest: + return white + case code >= http.StatusBadRequest && code < http.StatusInternalServerError: + return yellow + default: + return red + } +} + +// MethodColor is the ANSI color for appropriately logging http method to a terminal. +func (p *LogFormatterParams) MethodColor() string { + method := p.Method + + switch method { + case "GET": + return blue + case "POST": + return cyan + case "PUT": + return yellow + case "DELETE": + return red + case "PATCH": + return green + case "HEAD": + return magenta + case "OPTIONS": + return white + default: + return reset + } +} + +// ResetColor resets all escape attributes. +func (p *LogFormatterParams) ResetColor() string { + return reset +} + +// IsOutputColor indicates whether can colors be outputted to the log. +func (p *LogFormatterParams) IsOutputColor() bool { + return consoleColorMode == forceColor || (consoleColorMode == autoColor && p.isTerm) +} + +// defaultLogFormatter is the default log format function Logger middleware uses. +var defaultLogFormatter = func(param LogFormatterParams) string { + var statusColor, methodColor, resetColor string + if param.IsOutputColor() { + statusColor = param.StatusCodeColor() + methodColor = param.MethodColor() + resetColor = param.ResetColor() + } + + if param.Latency > time.Minute { + // Truncate in a golang < 1.8 safe way + param.Latency = param.Latency - param.Latency%time.Second + } + return fmt.Sprintf("[GIN] %v |%s %3d %s| %13v | %15s |%s %-7s %s %s\n%s", + param.TimeStamp.Format("2006/01/02 - 15:04:05"), + statusColor, param.StatusCode, resetColor, + param.Latency, + param.ClientIP, + methodColor, param.Method, resetColor, + param.Path, + param.ErrorMessage, + ) +} + +// DisableConsoleColor disables color output in the console. +func DisableConsoleColor() { + consoleColorMode = disableColor +} + +// ForceConsoleColor force color output in the console. +func ForceConsoleColor() { + consoleColorMode = forceColor +} + +// ErrorLogger returns a handlerfunc for any error type. +func ErrorLogger() HandlerFunc { + return ErrorLoggerT(ErrorTypeAny) +} + +// ErrorLoggerT returns a handlerfunc for a given error type. +func ErrorLoggerT(typ ErrorType) HandlerFunc { + return func(c *Context) { + c.Next() + errors := c.Errors.ByType(typ) + if len(errors) > 0 { + c.JSON(-1, errors) + } + } +} + +// Logger instances a Logger middleware that will write the logs to gin.DefaultWriter. +// By default gin.DefaultWriter = os.Stdout. +func Logger() HandlerFunc { + return LoggerWithConfig(LoggerConfig{}) +} + +// LoggerWithFormatter instance a Logger middleware with the specified log format function. +func LoggerWithFormatter(f LogFormatter) HandlerFunc { + return LoggerWithConfig(LoggerConfig{ + Formatter: f, + }) +} + +// LoggerWithWriter instance a Logger middleware with the specified writer buffer. +// Example: os.Stdout, a file opened in write mode, a socket... +func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc { + return LoggerWithConfig(LoggerConfig{ + Output: out, + SkipPaths: notlogged, + }) +} + +// LoggerWithConfig instance a Logger middleware with config. +func LoggerWithConfig(conf LoggerConfig) HandlerFunc { + formatter := conf.Formatter + if formatter == nil { + formatter = defaultLogFormatter + } + + out := conf.Output + if out == nil { + out = DefaultWriter + } + + notlogged := conf.SkipPaths + + isTerm := true + + if w, ok := out.(*os.File); !ok || os.Getenv("TERM") == "dumb" || + (!isatty.IsTerminal(w.Fd()) && !isatty.IsCygwinTerminal(w.Fd())) { + isTerm = false + } + + var skip map[string]struct{} + + if length := len(notlogged); length > 0 { + skip = make(map[string]struct{}, length) + + for _, path := range notlogged { + skip[path] = struct{}{} + } + } + + return func(c *Context) { + // Start timer + start := time.Now() + path := c.Request.URL.Path + raw := c.Request.URL.RawQuery + + // Process request + c.Next() + + // Log only when path is not being skipped + if _, ok := skip[path]; !ok { + param := LogFormatterParams{ + Request: c.Request, + isTerm: isTerm, + Keys: c.Keys, + } + + // Stop timer + param.TimeStamp = time.Now() + param.Latency = param.TimeStamp.Sub(start) + + param.ClientIP = c.ClientIP() + param.Method = c.Request.Method + param.StatusCode = c.Writer.Status() + param.ErrorMessage = c.Errors.ByType(ErrorTypePrivate).String() + + param.BodySize = c.Writer.Size() + + if raw != "" { + path = path + "?" + raw + } + + param.Path = path + + fmt.Fprint(out, formatter(param)) + } + } +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/mode.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/mode.go new file mode 100644 index 0000000..8aa84aa --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/mode.go @@ -0,0 +1,83 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import ( + "io" + "os" + + "github.com/gin-gonic/gin/binding" +) + +// EnvGinMode indicates environment name for gin mode. +const EnvGinMode = "GIN_MODE" + +const ( + // DebugMode indicates gin mode is debug. + DebugMode = "debug" + // ReleaseMode indicates gin mode is release. + ReleaseMode = "release" + // TestMode indicates gin mode is test. + TestMode = "test" +) +const ( + debugCode = iota + releaseCode + testCode +) + +// DefaultWriter is the default io.Writer used by Gin for debug output and +// middleware output like Logger() or Recovery(). +// Note that both Logger and Recovery provides custom ways to configure their +// output io.Writer. +// To support coloring in Windows use: +// import "github.com/mattn/go-colorable" +// gin.DefaultWriter = colorable.NewColorableStdout() +var DefaultWriter io.Writer = os.Stdout + +// DefaultErrorWriter is the default io.Writer used by Gin to debug errors +var DefaultErrorWriter io.Writer = os.Stderr + +var ginMode = debugCode +var modeName = DebugMode + +func init() { + mode := os.Getenv(EnvGinMode) + SetMode(mode) +} + +// SetMode sets gin mode according to input string. +func SetMode(value string) { + switch value { + case DebugMode, "": + ginMode = debugCode + case ReleaseMode: + ginMode = releaseCode + case TestMode: + ginMode = testCode + default: + panic("gin mode unknown: " + value) + } + if value == "" { + value = DebugMode + } + modeName = value +} + +// DisableBindValidation closes the default validator. +func DisableBindValidation() { + binding.Validator = nil +} + +// EnableJsonDecoderUseNumber sets true for binding.EnableDecoderUseNumberto to +// call the UseNumber method on the JSON Decoder instance. +func EnableJsonDecoderUseNumber() { + binding.EnableDecoderUseNumber = true +} + +// Mode returns currently gin mode. +func Mode() string { + return modeName +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/path.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/path.go new file mode 100644 index 0000000..d1f5962 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/path.go @@ -0,0 +1,123 @@ +// Copyright 2013 Julien Schmidt. All rights reserved. +// Based on the path package, Copyright 2009 The Go Authors. +// Use of this source code is governed by a BSD-style license that can be found +// at https://github.com/julienschmidt/httprouter/blob/master/LICENSE. + +package gin + +// cleanPath is the URL version of path.Clean, it returns a canonical URL path +// for p, eliminating . and .. elements. +// +// The following rules are applied iteratively until no further processing can +// be done: +// 1. Replace multiple slashes with a single slash. +// 2. Eliminate each . path name element (the current directory). +// 3. Eliminate each inner .. path name element (the parent directory) +// along with the non-.. element that precedes it. +// 4. Eliminate .. elements that begin a rooted path: +// that is, replace "/.." by "/" at the beginning of a path. +// +// If the result of this process is an empty string, "/" is returned. +func cleanPath(p string) string { + // Turn empty string into "/" + if p == "" { + return "/" + } + + n := len(p) + var buf []byte + + // Invariants: + // reading from path; r is index of next byte to process. + // writing to buf; w is index of next byte to write. + + // path must start with '/' + r := 1 + w := 1 + + if p[0] != '/' { + r = 0 + buf = make([]byte, n+1) + buf[0] = '/' + } + + trailing := n > 1 && p[n-1] == '/' + + // A bit more clunky without a 'lazybuf' like the path package, but the loop + // gets completely inlined (bufApp). So in contrast to the path package this + // loop has no expensive function calls (except 1x make) + + for r < n { + switch { + case p[r] == '/': + // empty path element, trailing slash is added after the end + r++ + + case p[r] == '.' && r+1 == n: + trailing = true + r++ + + case p[r] == '.' && p[r+1] == '/': + // . element + r += 2 + + case p[r] == '.' && p[r+1] == '.' && (r+2 == n || p[r+2] == '/'): + // .. element: remove to last / + r += 3 + + if w > 1 { + // can backtrack + w-- + + if buf == nil { + for w > 1 && p[w] != '/' { + w-- + } + } else { + for w > 1 && buf[w] != '/' { + w-- + } + } + } + + default: + // real path element. + // add slash if needed + if w > 1 { + bufApp(&buf, p, w, '/') + w++ + } + + // copy element + for r < n && p[r] != '/' { + bufApp(&buf, p, w, p[r]) + w++ + r++ + } + } + } + + // re-append trailing slash + if trailing && w > 1 { + bufApp(&buf, p, w, '/') + w++ + } + + if buf == nil { + return p[:w] + } + return string(buf[:w]) +} + +// internal helper to lazily create a buffer if necessary. +func bufApp(buf *[]byte, s string, w int, c byte) { + if *buf == nil { + if s[w] == c { + return + } + + *buf = make([]byte, len(s)) + copy(*buf, s[:w]) + } + (*buf)[w] = c +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/recovery.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/recovery.go new file mode 100644 index 0000000..bc946c0 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/recovery.go @@ -0,0 +1,151 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "log" + "net" + "net/http" + "net/http/httputil" + "os" + "runtime" + "strings" + "time" +) + +var ( + dunno = []byte("???") + centerDot = []byte("·") + dot = []byte(".") + slash = []byte("/") +) + +// Recovery returns a middleware that recovers from any panics and writes a 500 if there was one. +func Recovery() HandlerFunc { + return RecoveryWithWriter(DefaultErrorWriter) +} + +// RecoveryWithWriter returns a middleware for a given writer that recovers from any panics and writes a 500 if there was one. +func RecoveryWithWriter(out io.Writer) HandlerFunc { + var logger *log.Logger + if out != nil { + logger = log.New(out, "\n\n\x1b[31m", log.LstdFlags) + } + return func(c *Context) { + defer func() { + if err := recover(); err != nil { + // Check for a broken connection, as it is not really a + // condition that warrants a panic stack trace. + var brokenPipe bool + if ne, ok := err.(*net.OpError); ok { + if se, ok := ne.Err.(*os.SyscallError); ok { + if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") { + brokenPipe = true + } + } + } + if logger != nil { + stack := stack(3) + httpRequest, _ := httputil.DumpRequest(c.Request, false) + headers := strings.Split(string(httpRequest), "\r\n") + for idx, header := range headers { + current := strings.Split(header, ":") + if current[0] == "Authorization" { + headers[idx] = current[0] + ": *" + } + } + if brokenPipe { + logger.Printf("%s\n%s%s", err, string(httpRequest), reset) + } else if IsDebugging() { + logger.Printf("[Recovery] %s panic recovered:\n%s\n%s\n%s%s", + timeFormat(time.Now()), strings.Join(headers, "\r\n"), err, stack, reset) + } else { + logger.Printf("[Recovery] %s panic recovered:\n%s\n%s%s", + timeFormat(time.Now()), err, stack, reset) + } + } + + // If the connection is dead, we can't write a status to it. + if brokenPipe { + c.Error(err.(error)) // nolint: errcheck + c.Abort() + } else { + c.AbortWithStatus(http.StatusInternalServerError) + } + } + }() + c.Next() + } +} + +// stack returns a nicely formatted stack frame, skipping skip frames. +func stack(skip int) []byte { + buf := new(bytes.Buffer) // the returned data + // As we loop, we open files and read them. These variables record the currently + // loaded file. + var lines [][]byte + var lastFile string + for i := skip; ; i++ { // Skip the expected number of frames + pc, file, line, ok := runtime.Caller(i) + if !ok { + break + } + // Print this much at least. If we can't find the source, it won't show. + fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc) + if file != lastFile { + data, err := ioutil.ReadFile(file) + if err != nil { + continue + } + lines = bytes.Split(data, []byte{'\n'}) + lastFile = file + } + fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line)) + } + return buf.Bytes() +} + +// source returns a space-trimmed slice of the n'th line. +func source(lines [][]byte, n int) []byte { + n-- // in stack trace, lines are 1-indexed but our array is 0-indexed + if n < 0 || n >= len(lines) { + return dunno + } + return bytes.TrimSpace(lines[n]) +} + +// function returns, if possible, the name of the function containing the PC. +func function(pc uintptr) []byte { + fn := runtime.FuncForPC(pc) + if fn == nil { + return dunno + } + name := []byte(fn.Name()) + // The name includes the path name to the package, which is unnecessary + // since the file name is already included. Plus, it has center dots. + // That is, we see + // runtime/debug.*T·ptrmethod + // and want + // *T.ptrmethod + // Also the package path might contains dot (e.g. code.google.com/...), + // so first eliminate the path prefix + if lastSlash := bytes.LastIndex(name, slash); lastSlash >= 0 { + name = name[lastSlash+1:] + } + if period := bytes.Index(name, dot); period >= 0 { + name = name[period+1:] + } + name = bytes.Replace(name, centerDot, dot, -1) + return name +} + +func timeFormat(t time.Time) string { + var timeString = t.Format("2006/01/02 - 15:04:05") + return timeString +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/render/data.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/data.go new file mode 100644 index 0000000..6ba657b --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/data.go @@ -0,0 +1,25 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package render + +import "net/http" + +// Data contains ContentType and bytes data. +type Data struct { + ContentType string + Data []byte +} + +// Render (Data) writes data with custom ContentType. +func (r Data) Render(w http.ResponseWriter) (err error) { + r.WriteContentType(w) + _, err = w.Write(r.Data) + return +} + +// WriteContentType (Data) writes custom ContentType. +func (r Data) WriteContentType(w http.ResponseWriter) { + writeContentType(w, []string{r.ContentType}) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/render/html.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/html.go new file mode 100644 index 0000000..6696ece --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/html.go @@ -0,0 +1,92 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package render + +import ( + "html/template" + "net/http" +) + +// Delims represents a set of Left and Right delimiters for HTML template rendering. +type Delims struct { + // Left delimiter, defaults to {{. + Left string + // Right delimiter, defaults to }}. + Right string +} + +// HTMLRender interface is to be implemented by HTMLProduction and HTMLDebug. +type HTMLRender interface { + // Instance returns an HTML instance. + Instance(string, interface{}) Render +} + +// HTMLProduction contains template reference and its delims. +type HTMLProduction struct { + Template *template.Template + Delims Delims +} + +// HTMLDebug contains template delims and pattern and function with file list. +type HTMLDebug struct { + Files []string + Glob string + Delims Delims + FuncMap template.FuncMap +} + +// HTML contains template reference and its name with given interface object. +type HTML struct { + Template *template.Template + Name string + Data interface{} +} + +var htmlContentType = []string{"text/html; charset=utf-8"} + +// Instance (HTMLProduction) returns an HTML instance which it realizes Render interface. +func (r HTMLProduction) Instance(name string, data interface{}) Render { + return HTML{ + Template: r.Template, + Name: name, + Data: data, + } +} + +// Instance (HTMLDebug) returns an HTML instance which it realizes Render interface. +func (r HTMLDebug) Instance(name string, data interface{}) Render { + return HTML{ + Template: r.loadTemplate(), + Name: name, + Data: data, + } +} +func (r HTMLDebug) loadTemplate() *template.Template { + if r.FuncMap == nil { + r.FuncMap = template.FuncMap{} + } + if len(r.Files) > 0 { + return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseFiles(r.Files...)) + } + if r.Glob != "" { + return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseGlob(r.Glob)) + } + panic("the HTML debug render was created without files or glob pattern") +} + +// Render (HTML) executes template and writes its result with custom ContentType for response. +func (r HTML) Render(w http.ResponseWriter) error { + r.WriteContentType(w) + + if r.Name == "" { + return r.Template.Execute(w, r.Data) + } + return r.Template.ExecuteTemplate(w, r.Name, r.Data) +} + +// WriteContentType (HTML) writes HTML ContentType. +func (r HTML) WriteContentType(w http.ResponseWriter) { + writeContentType(w, htmlContentType) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/render/json.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/json.go new file mode 100644 index 0000000..18f27fa --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/json.go @@ -0,0 +1,194 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package render + +import ( + "bytes" + "fmt" + "html/template" + "net/http" + + "github.com/gin-gonic/gin/internal/json" +) + +// JSON contains the given interface object. +type JSON struct { + Data interface{} +} + +// IndentedJSON contains the given interface object. +type IndentedJSON struct { + Data interface{} +} + +// SecureJSON contains the given interface object and its prefix. +type SecureJSON struct { + Prefix string + Data interface{} +} + +// JsonpJSON contains the given interface object its callback. +type JsonpJSON struct { + Callback string + Data interface{} +} + +// AsciiJSON contains the given interface object. +type AsciiJSON struct { + Data interface{} +} + +// SecureJSONPrefix is a string which represents SecureJSON prefix. +type SecureJSONPrefix string + +// PureJSON contains the given interface object. +type PureJSON struct { + Data interface{} +} + +var jsonContentType = []string{"application/json; charset=utf-8"} +var jsonpContentType = []string{"application/javascript; charset=utf-8"} +var jsonAsciiContentType = []string{"application/json"} + +// Render (JSON) writes data with custom ContentType. +func (r JSON) Render(w http.ResponseWriter) (err error) { + if err = WriteJSON(w, r.Data); err != nil { + panic(err) + } + return +} + +// WriteContentType (JSON) writes JSON ContentType. +func (r JSON) WriteContentType(w http.ResponseWriter) { + writeContentType(w, jsonContentType) +} + +// WriteJSON marshals the given interface object and writes it with custom ContentType. +func WriteJSON(w http.ResponseWriter, obj interface{}) error { + writeContentType(w, jsonContentType) + jsonBytes, err := json.Marshal(obj) + if err != nil { + return err + } + _, err = w.Write(jsonBytes) + return err +} + +// Render (IndentedJSON) marshals the given interface object and writes it with custom ContentType. +func (r IndentedJSON) Render(w http.ResponseWriter) error { + r.WriteContentType(w) + jsonBytes, err := json.MarshalIndent(r.Data, "", " ") + if err != nil { + return err + } + _, err = w.Write(jsonBytes) + return err +} + +// WriteContentType (IndentedJSON) writes JSON ContentType. +func (r IndentedJSON) WriteContentType(w http.ResponseWriter) { + writeContentType(w, jsonContentType) +} + +// Render (SecureJSON) marshals the given interface object and writes it with custom ContentType. +func (r SecureJSON) Render(w http.ResponseWriter) error { + r.WriteContentType(w) + jsonBytes, err := json.Marshal(r.Data) + if err != nil { + return err + } + // if the jsonBytes is array values + if bytes.HasPrefix(jsonBytes, []byte("[")) && bytes.HasSuffix(jsonBytes, []byte("]")) { + _, err = w.Write([]byte(r.Prefix)) + if err != nil { + return err + } + } + _, err = w.Write(jsonBytes) + return err +} + +// WriteContentType (SecureJSON) writes JSON ContentType. +func (r SecureJSON) WriteContentType(w http.ResponseWriter) { + writeContentType(w, jsonContentType) +} + +// Render (JsonpJSON) marshals the given interface object and writes it and its callback with custom ContentType. +func (r JsonpJSON) Render(w http.ResponseWriter) (err error) { + r.WriteContentType(w) + ret, err := json.Marshal(r.Data) + if err != nil { + return err + } + + if r.Callback == "" { + _, err = w.Write(ret) + return err + } + + callback := template.JSEscapeString(r.Callback) + _, err = w.Write([]byte(callback)) + if err != nil { + return err + } + _, err = w.Write([]byte("(")) + if err != nil { + return err + } + _, err = w.Write(ret) + if err != nil { + return err + } + _, err = w.Write([]byte(")")) + if err != nil { + return err + } + + return nil +} + +// WriteContentType (JsonpJSON) writes Javascript ContentType. +func (r JsonpJSON) WriteContentType(w http.ResponseWriter) { + writeContentType(w, jsonpContentType) +} + +// Render (AsciiJSON) marshals the given interface object and writes it with custom ContentType. +func (r AsciiJSON) Render(w http.ResponseWriter) (err error) { + r.WriteContentType(w) + ret, err := json.Marshal(r.Data) + if err != nil { + return err + } + + var buffer bytes.Buffer + for _, r := range string(ret) { + cvt := string(r) + if r >= 128 { + cvt = fmt.Sprintf("\\u%04x", int64(r)) + } + buffer.WriteString(cvt) + } + + _, err = w.Write(buffer.Bytes()) + return err +} + +// WriteContentType (AsciiJSON) writes JSON ContentType. +func (r AsciiJSON) WriteContentType(w http.ResponseWriter) { + writeContentType(w, jsonAsciiContentType) +} + +// Render (PureJSON) writes custom ContentType and encodes the given interface object. +func (r PureJSON) Render(w http.ResponseWriter) error { + r.WriteContentType(w) + encoder := json.NewEncoder(w) + encoder.SetEscapeHTML(false) + return encoder.Encode(r.Data) +} + +// WriteContentType (PureJSON) writes custom ContentType. +func (r PureJSON) WriteContentType(w http.ResponseWriter) { + writeContentType(w, jsonContentType) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/render/msgpack.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/msgpack.go new file mode 100644 index 0000000..dc681fc --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/msgpack.go @@ -0,0 +1,35 @@ +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package render + +import ( + "net/http" + + "github.com/ugorji/go/codec" +) + +// MsgPack contains the given interface object. +type MsgPack struct { + Data interface{} +} + +var msgpackContentType = []string{"application/msgpack; charset=utf-8"} + +// WriteContentType (MsgPack) writes MsgPack ContentType. +func (r MsgPack) WriteContentType(w http.ResponseWriter) { + writeContentType(w, msgpackContentType) +} + +// Render (MsgPack) encodes the given interface object and writes data with custom ContentType. +func (r MsgPack) Render(w http.ResponseWriter) error { + return WriteMsgPack(w, r.Data) +} + +// WriteMsgPack writes MsgPack ContentType and encodes the given interface object. +func WriteMsgPack(w http.ResponseWriter, obj interface{}) error { + writeContentType(w, msgpackContentType) + var mh codec.MsgpackHandle + return codec.NewEncoder(w, &mh).Encode(obj) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/render/protobuf.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/protobuf.go new file mode 100644 index 0000000..15aca99 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/protobuf.go @@ -0,0 +1,36 @@ +// Copyright 2018 Gin Core Team. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package render + +import ( + "net/http" + + "github.com/golang/protobuf/proto" +) + +// ProtoBuf contains the given interface object. +type ProtoBuf struct { + Data interface{} +} + +var protobufContentType = []string{"application/x-protobuf"} + +// Render (ProtoBuf) marshals the given interface object and writes data with custom ContentType. +func (r ProtoBuf) Render(w http.ResponseWriter) error { + r.WriteContentType(w) + + bytes, err := proto.Marshal(r.Data.(proto.Message)) + if err != nil { + return err + } + + _, err = w.Write(bytes) + return err +} + +// WriteContentType (ProtoBuf) writes ProtoBuf ContentType. +func (r ProtoBuf) WriteContentType(w http.ResponseWriter) { + writeContentType(w, protobufContentType) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/render/reader.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/reader.go new file mode 100644 index 0000000..312af74 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/reader.go @@ -0,0 +1,43 @@ +// Copyright 2018 Gin Core Team. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package render + +import ( + "io" + "net/http" + "strconv" +) + +// Reader contains the IO reader and its length, and custom ContentType and other headers. +type Reader struct { + ContentType string + ContentLength int64 + Reader io.Reader + Headers map[string]string +} + +// Render (Reader) writes data with custom ContentType and headers. +func (r Reader) Render(w http.ResponseWriter) (err error) { + r.WriteContentType(w) + r.Headers["Content-Length"] = strconv.FormatInt(r.ContentLength, 10) + r.writeHeaders(w, r.Headers) + _, err = io.Copy(w, r.Reader) + return +} + +// WriteContentType (Reader) writes custom ContentType. +func (r Reader) WriteContentType(w http.ResponseWriter) { + writeContentType(w, []string{r.ContentType}) +} + +// writeHeaders writes custom Header. +func (r Reader) writeHeaders(w http.ResponseWriter, headers map[string]string) { + header := w.Header() + for k, v := range headers { + if header.Get(k) == "" { + header.Set(k, v) + } + } +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/render/redirect.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/redirect.go new file mode 100644 index 0000000..c006691 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/redirect.go @@ -0,0 +1,29 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package render + +import ( + "fmt" + "net/http" +) + +// Redirect contains the http request reference and redirects status code and location. +type Redirect struct { + Code int + Request *http.Request + Location string +} + +// Render (Redirect) redirects the http request to new location and writes redirect response. +func (r Redirect) Render(w http.ResponseWriter) error { + if (r.Code < http.StatusMultipleChoices || r.Code > http.StatusPermanentRedirect) && r.Code != http.StatusCreated { + panic(fmt.Sprintf("Cannot redirect with status code %d", r.Code)) + } + http.Redirect(w, r.Request, r.Location, r.Code) + return nil +} + +// WriteContentType (Redirect) don't write any ContentType. +func (r Redirect) WriteContentType(http.ResponseWriter) {} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/render/render.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/render.go new file mode 100644 index 0000000..abfc79f --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/render.go @@ -0,0 +1,41 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package render + +import "net/http" + +// Render interface is to be implemented by JSON, XML, HTML, YAML and so on. +type Render interface { + // Render writes data with custom ContentType. + Render(http.ResponseWriter) error + // WriteContentType writes custom ContentType. + WriteContentType(w http.ResponseWriter) +} + +var ( + _ Render = JSON{} + _ Render = IndentedJSON{} + _ Render = SecureJSON{} + _ Render = JsonpJSON{} + _ Render = XML{} + _ Render = String{} + _ Render = Redirect{} + _ Render = Data{} + _ Render = HTML{} + _ HTMLRender = HTMLDebug{} + _ HTMLRender = HTMLProduction{} + _ Render = YAML{} + _ Render = MsgPack{} + _ Render = Reader{} + _ Render = AsciiJSON{} + _ Render = ProtoBuf{} +) + +func writeContentType(w http.ResponseWriter, value []string) { + header := w.Header() + if val := header["Content-Type"]; len(val) == 0 { + header["Content-Type"] = value + } +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/render/text.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/text.go new file mode 100644 index 0000000..4e52d4c --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/text.go @@ -0,0 +1,40 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package render + +import ( + "fmt" + "io" + "net/http" +) + +// String contains the given interface object slice and its format. +type String struct { + Format string + Data []interface{} +} + +var plainContentType = []string{"text/plain; charset=utf-8"} + +// Render (String) writes data with custom ContentType. +func (r String) Render(w http.ResponseWriter) error { + return WriteString(w, r.Format, r.Data) +} + +// WriteContentType (String) writes Plain ContentType. +func (r String) WriteContentType(w http.ResponseWriter) { + writeContentType(w, plainContentType) +} + +// WriteString writes data according to its format and write custom ContentType. +func WriteString(w http.ResponseWriter, format string, data []interface{}) (err error) { + writeContentType(w, plainContentType) + if len(data) > 0 { + _, err = fmt.Fprintf(w, format, data...) + return + } + _, err = io.WriteString(w, format) + return +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/render/xml.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/xml.go new file mode 100644 index 0000000..cc5390a --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/xml.go @@ -0,0 +1,28 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package render + +import ( + "encoding/xml" + "net/http" +) + +// XML contains the given interface object. +type XML struct { + Data interface{} +} + +var xmlContentType = []string{"application/xml; charset=utf-8"} + +// Render (XML) encodes the given interface object and writes data with custom ContentType. +func (r XML) Render(w http.ResponseWriter) error { + r.WriteContentType(w) + return xml.NewEncoder(w).Encode(r.Data) +} + +// WriteContentType (XML) writes XML ContentType for response. +func (r XML) WriteContentType(w http.ResponseWriter) { + writeContentType(w, xmlContentType) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/render/yaml.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/yaml.go new file mode 100644 index 0000000..0df7836 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/render/yaml.go @@ -0,0 +1,36 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package render + +import ( + "net/http" + + "gopkg.in/yaml.v2" +) + +// YAML contains the given interface object. +type YAML struct { + Data interface{} +} + +var yamlContentType = []string{"application/x-yaml; charset=utf-8"} + +// Render (YAML) marshals the given interface object and writes data with custom ContentType. +func (r YAML) Render(w http.ResponseWriter) error { + r.WriteContentType(w) + + bytes, err := yaml.Marshal(r.Data) + if err != nil { + return err + } + + _, err = w.Write(bytes) + return err +} + +// WriteContentType (YAML) writes YAML ContentType for response. +func (r YAML) WriteContentType(w http.ResponseWriter) { + writeContentType(w, yamlContentType) +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/response_writer.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/response_writer.go new file mode 100644 index 0000000..2682668 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/response_writer.go @@ -0,0 +1,126 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import ( + "bufio" + "io" + "net" + "net/http" +) + +const ( + noWritten = -1 + defaultStatus = http.StatusOK +) + +// ResponseWriter ... +type ResponseWriter interface { + http.ResponseWriter + http.Hijacker + http.Flusher + http.CloseNotifier + + // Returns the HTTP response status code of the current request. + Status() int + + // Returns the number of bytes already written into the response http body. + // See Written() + Size() int + + // Writes the string into the response body. + WriteString(string) (int, error) + + // Returns true if the response body was already written. + Written() bool + + // Forces to write the http header (status code + headers). + WriteHeaderNow() + + // get the http.Pusher for server push + Pusher() http.Pusher +} + +type responseWriter struct { + http.ResponseWriter + size int + status int +} + +var _ ResponseWriter = &responseWriter{} + +func (w *responseWriter) reset(writer http.ResponseWriter) { + w.ResponseWriter = writer + w.size = noWritten + w.status = defaultStatus +} + +func (w *responseWriter) WriteHeader(code int) { + if code > 0 && w.status != code { + if w.Written() { + debugPrint("[WARNING] Headers were already written. Wanted to override status code %d with %d", w.status, code) + } + w.status = code + } +} + +func (w *responseWriter) WriteHeaderNow() { + if !w.Written() { + w.size = 0 + w.ResponseWriter.WriteHeader(w.status) + } +} + +func (w *responseWriter) Write(data []byte) (n int, err error) { + w.WriteHeaderNow() + n, err = w.ResponseWriter.Write(data) + w.size += n + return +} + +func (w *responseWriter) WriteString(s string) (n int, err error) { + w.WriteHeaderNow() + n, err = io.WriteString(w.ResponseWriter, s) + w.size += n + return +} + +func (w *responseWriter) Status() int { + return w.status +} + +func (w *responseWriter) Size() int { + return w.size +} + +func (w *responseWriter) Written() bool { + return w.size != noWritten +} + +// Hijack implements the http.Hijacker interface. +func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { + if w.size < 0 { + w.size = 0 + } + return w.ResponseWriter.(http.Hijacker).Hijack() +} + +// CloseNotify implements the http.CloseNotify interface. +func (w *responseWriter) CloseNotify() <-chan bool { + return w.ResponseWriter.(http.CloseNotifier).CloseNotify() +} + +// Flush implements the http.Flush interface. +func (w *responseWriter) Flush() { + w.WriteHeaderNow() + w.ResponseWriter.(http.Flusher).Flush() +} + +func (w *responseWriter) Pusher() (pusher http.Pusher) { + if pusher, ok := w.ResponseWriter.(http.Pusher); ok { + return pusher + } + return nil +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/routergroup.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/routergroup.go new file mode 100644 index 0000000..a1e6c92 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/routergroup.go @@ -0,0 +1,228 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import ( + "net/http" + "path" + "regexp" + "strings" +) + +// IRouter defines all router handle interface includes single and group router. +type IRouter interface { + IRoutes + Group(string, ...HandlerFunc) *RouterGroup +} + +// IRoutes defines all router handle interface. +type IRoutes interface { + Use(...HandlerFunc) IRoutes + + Handle(string, string, ...HandlerFunc) IRoutes + Any(string, ...HandlerFunc) IRoutes + GET(string, ...HandlerFunc) IRoutes + POST(string, ...HandlerFunc) IRoutes + DELETE(string, ...HandlerFunc) IRoutes + PATCH(string, ...HandlerFunc) IRoutes + PUT(string, ...HandlerFunc) IRoutes + OPTIONS(string, ...HandlerFunc) IRoutes + HEAD(string, ...HandlerFunc) IRoutes + + StaticFile(string, string) IRoutes + Static(string, string) IRoutes + StaticFS(string, http.FileSystem) IRoutes +} + +// RouterGroup is used internally to configure router, a RouterGroup is associated with +// a prefix and an array of handlers (middleware). +type RouterGroup struct { + Handlers HandlersChain + basePath string + engine *Engine + root bool +} + +var _ IRouter = &RouterGroup{} + +// Use adds middleware to the group, see example code in GitHub. +func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes { + group.Handlers = append(group.Handlers, middleware...) + return group.returnObj() +} + +// Group creates a new router group. You should add all the routes that have common middlewares or the same path prefix. +// For example, all the routes that use a common middleware for authorization could be grouped. +func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup { + return &RouterGroup{ + Handlers: group.combineHandlers(handlers), + basePath: group.calculateAbsolutePath(relativePath), + engine: group.engine, + } +} + +// BasePath returns the base path of router group. +// For example, if v := router.Group("/rest/n/v1/api"), v.BasePath() is "/rest/n/v1/api". +func (group *RouterGroup) BasePath() string { + return group.basePath +} + +func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes { + absolutePath := group.calculateAbsolutePath(relativePath) + handlers = group.combineHandlers(handlers) + group.engine.addRoute(httpMethod, absolutePath, handlers) + return group.returnObj() +} + +// Handle registers a new request handle and middleware with the given path and method. +// The last handler should be the real handler, the other ones should be middleware that can and should be shared among different routes. +// See the example code in GitHub. +// +// For GET, POST, PUT, PATCH and DELETE requests the respective shortcut +// functions can be used. +// +// This function is intended for bulk loading and to allow the usage of less +// frequently used, non-standardized or custom methods (e.g. for internal +// communication with a proxy). +func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes { + if matches, err := regexp.MatchString("^[A-Z]+$", httpMethod); !matches || err != nil { + panic("http method " + httpMethod + " is not valid") + } + return group.handle(httpMethod, relativePath, handlers) +} + +// POST is a shortcut for router.Handle("POST", path, handle). +func (group *RouterGroup) POST(relativePath string, handlers ...HandlerFunc) IRoutes { + return group.handle("POST", relativePath, handlers) +} + +// GET is a shortcut for router.Handle("GET", path, handle). +func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes { + return group.handle("GET", relativePath, handlers) +} + +// DELETE is a shortcut for router.Handle("DELETE", path, handle). +func (group *RouterGroup) DELETE(relativePath string, handlers ...HandlerFunc) IRoutes { + return group.handle("DELETE", relativePath, handlers) +} + +// PATCH is a shortcut for router.Handle("PATCH", path, handle). +func (group *RouterGroup) PATCH(relativePath string, handlers ...HandlerFunc) IRoutes { + return group.handle("PATCH", relativePath, handlers) +} + +// PUT is a shortcut for router.Handle("PUT", path, handle). +func (group *RouterGroup) PUT(relativePath string, handlers ...HandlerFunc) IRoutes { + return group.handle("PUT", relativePath, handlers) +} + +// OPTIONS is a shortcut for router.Handle("OPTIONS", path, handle). +func (group *RouterGroup) OPTIONS(relativePath string, handlers ...HandlerFunc) IRoutes { + return group.handle("OPTIONS", relativePath, handlers) +} + +// HEAD is a shortcut for router.Handle("HEAD", path, handle). +func (group *RouterGroup) HEAD(relativePath string, handlers ...HandlerFunc) IRoutes { + return group.handle("HEAD", relativePath, handlers) +} + +// Any registers a route that matches all the HTTP methods. +// GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE. +func (group *RouterGroup) Any(relativePath string, handlers ...HandlerFunc) IRoutes { + group.handle("GET", relativePath, handlers) + group.handle("POST", relativePath, handlers) + group.handle("PUT", relativePath, handlers) + group.handle("PATCH", relativePath, handlers) + group.handle("HEAD", relativePath, handlers) + group.handle("OPTIONS", relativePath, handlers) + group.handle("DELETE", relativePath, handlers) + group.handle("CONNECT", relativePath, handlers) + group.handle("TRACE", relativePath, handlers) + return group.returnObj() +} + +// StaticFile registers a single route in order to serve a single file of the local filesystem. +// router.StaticFile("favicon.ico", "./resources/favicon.ico") +func (group *RouterGroup) StaticFile(relativePath, filepath string) IRoutes { + if strings.Contains(relativePath, ":") || strings.Contains(relativePath, "*") { + panic("URL parameters can not be used when serving a static file") + } + handler := func(c *Context) { + c.File(filepath) + } + group.GET(relativePath, handler) + group.HEAD(relativePath, handler) + return group.returnObj() +} + +// Static serves files from the given file system root. +// Internally a http.FileServer is used, therefore http.NotFound is used instead +// of the Router's NotFound handler. +// To use the operating system's file system implementation, +// use : +// router.Static("/static", "/var/www") +func (group *RouterGroup) Static(relativePath, root string) IRoutes { + return group.StaticFS(relativePath, Dir(root, false)) +} + +// StaticFS works just like `Static()` but a custom `http.FileSystem` can be used instead. +// Gin by default user: gin.Dir() +func (group *RouterGroup) StaticFS(relativePath string, fs http.FileSystem) IRoutes { + if strings.Contains(relativePath, ":") || strings.Contains(relativePath, "*") { + panic("URL parameters can not be used when serving a static folder") + } + handler := group.createStaticHandler(relativePath, fs) + urlPattern := path.Join(relativePath, "/*filepath") + + // Register GET and HEAD handlers + group.GET(urlPattern, handler) + group.HEAD(urlPattern, handler) + return group.returnObj() +} + +func (group *RouterGroup) createStaticHandler(relativePath string, fs http.FileSystem) HandlerFunc { + absolutePath := group.calculateAbsolutePath(relativePath) + fileServer := http.StripPrefix(absolutePath, http.FileServer(fs)) + + return func(c *Context) { + if _, nolisting := fs.(*onlyfilesFS); nolisting { + c.Writer.WriteHeader(http.StatusNotFound) + } + + file := c.Param("filepath") + // Check if file exists and/or if we have permission to access it + if _, err := fs.Open(file); err != nil { + c.Writer.WriteHeader(http.StatusNotFound) + c.handlers = group.engine.noRoute + // Reset index + c.index = -1 + return + } + + fileServer.ServeHTTP(c.Writer, c.Request) + } +} + +func (group *RouterGroup) combineHandlers(handlers HandlersChain) HandlersChain { + finalSize := len(group.Handlers) + len(handlers) + if finalSize >= int(abortIndex) { + panic("too many handlers") + } + mergedHandlers := make(HandlersChain, finalSize) + copy(mergedHandlers, group.Handlers) + copy(mergedHandlers[len(group.Handlers):], handlers) + return mergedHandlers +} + +func (group *RouterGroup) calculateAbsolutePath(relativePath string) string { + return joinPaths(group.basePath, relativePath) +} + +func (group *RouterGroup) returnObj() IRoutes { + if group.root { + return group.engine + } + return group +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/test_helpers.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/test_helpers.go new file mode 100644 index 0000000..3a7a5dd --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/test_helpers.go @@ -0,0 +1,16 @@ +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import "net/http" + +// CreateTestContext returns a fresh engine and context for testing purposes +func CreateTestContext(w http.ResponseWriter) (c *Context, r *Engine) { + r = New() + c = r.allocateContext() + c.reset() + c.writermem.reset(w) + return +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/tree.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/tree.go new file mode 100644 index 0000000..ada62ce --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/tree.go @@ -0,0 +1,627 @@ +// Copyright 2013 Julien Schmidt. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be found +// at https://github.com/julienschmidt/httprouter/blob/master/LICENSE + +package gin + +import ( + "net/url" + "strings" + "unicode" +) + +// Param is a single URL parameter, consisting of a key and a value. +type Param struct { + Key string + Value string +} + +// Params is a Param-slice, as returned by the router. +// The slice is ordered, the first URL parameter is also the first slice value. +// It is therefore safe to read values by the index. +type Params []Param + +// Get returns the value of the first Param which key matches the given name. +// If no matching Param is found, an empty string is returned. +func (ps Params) Get(name string) (string, bool) { + for _, entry := range ps { + if entry.Key == name { + return entry.Value, true + } + } + return "", false +} + +// ByName returns the value of the first Param which key matches the given name. +// If no matching Param is found, an empty string is returned. +func (ps Params) ByName(name string) (va string) { + va, _ = ps.Get(name) + return +} + +type methodTree struct { + method string + root *node +} + +type methodTrees []methodTree + +func (trees methodTrees) get(method string) *node { + for _, tree := range trees { + if tree.method == method { + return tree.root + } + } + return nil +} + +func min(a, b int) int { + if a <= b { + return a + } + return b +} + +func countParams(path string) uint8 { + var n uint + for i := 0; i < len(path); i++ { + if path[i] != ':' && path[i] != '*' { + continue + } + n++ + } + if n >= 255 { + return 255 + } + return uint8(n) +} + +type nodeType uint8 + +const ( + static nodeType = iota // default + root + param + catchAll +) + +type node struct { + path string + indices string + children []*node + handlers HandlersChain + priority uint32 + nType nodeType + maxParams uint8 + wildChild bool +} + +// increments priority of the given child and reorders if necessary. +func (n *node) incrementChildPrio(pos int) int { + n.children[pos].priority++ + prio := n.children[pos].priority + + // adjust position (move to front) + newPos := pos + for newPos > 0 && n.children[newPos-1].priority < prio { + // swap node positions + n.children[newPos-1], n.children[newPos] = n.children[newPos], n.children[newPos-1] + + newPos-- + } + + // build new index char string + if newPos != pos { + n.indices = n.indices[:newPos] + // unchanged prefix, might be empty + n.indices[pos:pos+1] + // the index char we move + n.indices[newPos:pos] + n.indices[pos+1:] // rest without char at 'pos' + } + + return newPos +} + +// addRoute adds a node with the given handle to the path. +// Not concurrency-safe! +func (n *node) addRoute(path string, handlers HandlersChain) { + fullPath := path + n.priority++ + numParams := countParams(path) + + // non-empty tree + if len(n.path) > 0 || len(n.children) > 0 { + walk: + for { + // Update maxParams of the current node + if numParams > n.maxParams { + n.maxParams = numParams + } + + // Find the longest common prefix. + // This also implies that the common prefix contains no ':' or '*' + // since the existing key can't contain those chars. + i := 0 + max := min(len(path), len(n.path)) + for i < max && path[i] == n.path[i] { + i++ + } + + // Split edge + if i < len(n.path) { + child := node{ + path: n.path[i:], + wildChild: n.wildChild, + indices: n.indices, + children: n.children, + handlers: n.handlers, + priority: n.priority - 1, + } + + // Update maxParams (max of all children) + for i := range child.children { + if child.children[i].maxParams > child.maxParams { + child.maxParams = child.children[i].maxParams + } + } + + n.children = []*node{&child} + // []byte for proper unicode char conversion, see #65 + n.indices = string([]byte{n.path[i]}) + n.path = path[:i] + n.handlers = nil + n.wildChild = false + } + + // Make new node a child of this node + if i < len(path) { + path = path[i:] + + if n.wildChild { + n = n.children[0] + n.priority++ + + // Update maxParams of the child node + if numParams > n.maxParams { + n.maxParams = numParams + } + numParams-- + + // Check if the wildcard matches + if len(path) >= len(n.path) && n.path == path[:len(n.path)] { + // check for longer wildcard, e.g. :name and :names + if len(n.path) >= len(path) || path[len(n.path)] == '/' { + continue walk + } + } + + pathSeg := path + if n.nType != catchAll { + pathSeg = strings.SplitN(path, "/", 2)[0] + } + prefix := fullPath[:strings.Index(fullPath, pathSeg)] + n.path + panic("'" + pathSeg + + "' in new path '" + fullPath + + "' conflicts with existing wildcard '" + n.path + + "' in existing prefix '" + prefix + + "'") + } + + c := path[0] + + // slash after param + if n.nType == param && c == '/' && len(n.children) == 1 { + n = n.children[0] + n.priority++ + continue walk + } + + // Check if a child with the next path byte exists + for i := 0; i < len(n.indices); i++ { + if c == n.indices[i] { + i = n.incrementChildPrio(i) + n = n.children[i] + continue walk + } + } + + // Otherwise insert it + if c != ':' && c != '*' { + // []byte for proper unicode char conversion, see #65 + n.indices += string([]byte{c}) + child := &node{ + maxParams: numParams, + } + n.children = append(n.children, child) + n.incrementChildPrio(len(n.indices) - 1) + n = child + } + n.insertChild(numParams, path, fullPath, handlers) + return + + } else if i == len(path) { // Make node a (in-path) leaf + if n.handlers != nil { + panic("handlers are already registered for path '" + fullPath + "'") + } + n.handlers = handlers + } + return + } + } else { // Empty tree + n.insertChild(numParams, path, fullPath, handlers) + n.nType = root + } +} + +func (n *node) insertChild(numParams uint8, path string, fullPath string, handlers HandlersChain) { + var offset int // already handled bytes of the path + + // find prefix until first wildcard (beginning with ':' or '*') + for i, max := 0, len(path); numParams > 0; i++ { + c := path[i] + if c != ':' && c != '*' { + continue + } + + // find wildcard end (either '/' or path end) + end := i + 1 + for end < max && path[end] != '/' { + switch path[end] { + // the wildcard name must not contain ':' and '*' + case ':', '*': + panic("only one wildcard per path segment is allowed, has: '" + + path[i:] + "' in path '" + fullPath + "'") + default: + end++ + } + } + + // check if this Node existing children which would be + // unreachable if we insert the wildcard here + if len(n.children) > 0 { + panic("wildcard route '" + path[i:end] + + "' conflicts with existing children in path '" + fullPath + "'") + } + + // check if the wildcard has a name + if end-i < 2 { + panic("wildcards must be named with a non-empty name in path '" + fullPath + "'") + } + + if c == ':' { // param + // split path at the beginning of the wildcard + if i > 0 { + n.path = path[offset:i] + offset = i + } + + child := &node{ + nType: param, + maxParams: numParams, + } + n.children = []*node{child} + n.wildChild = true + n = child + n.priority++ + numParams-- + + // if the path doesn't end with the wildcard, then there + // will be another non-wildcard subpath starting with '/' + if end < max { + n.path = path[offset:end] + offset = end + + child := &node{ + maxParams: numParams, + priority: 1, + } + n.children = []*node{child} + n = child + } + + } else { // catchAll + if end != max || numParams > 1 { + panic("catch-all routes are only allowed at the end of the path in path '" + fullPath + "'") + } + + if len(n.path) > 0 && n.path[len(n.path)-1] == '/' { + panic("catch-all conflicts with existing handle for the path segment root in path '" + fullPath + "'") + } + + // currently fixed width 1 for '/' + i-- + if path[i] != '/' { + panic("no / before catch-all in path '" + fullPath + "'") + } + + n.path = path[offset:i] + + // first node: catchAll node with empty path + child := &node{ + wildChild: true, + nType: catchAll, + maxParams: 1, + } + n.children = []*node{child} + n.indices = string(path[i]) + n = child + n.priority++ + + // second node: node holding the variable + child = &node{ + path: path[i:], + nType: catchAll, + maxParams: 1, + handlers: handlers, + priority: 1, + } + n.children = []*node{child} + + return + } + } + + // insert remaining path part and handle to the leaf + n.path = path[offset:] + n.handlers = handlers +} + +// getValue returns the handle registered with the given path (key). The values of +// wildcards are saved to a map. +// If no handle can be found, a TSR (trailing slash redirect) recommendation is +// made if a handle exists with an extra (without the) trailing slash for the +// given path. +func (n *node) getValue(path string, po Params, unescape bool) (handlers HandlersChain, p Params, tsr bool) { + p = po +walk: // Outer loop for walking the tree + for { + if len(path) > len(n.path) { + if path[:len(n.path)] == n.path { + path = path[len(n.path):] + // If this node does not have a wildcard (param or catchAll) + // child, we can just look up the next child node and continue + // to walk down the tree + if !n.wildChild { + c := path[0] + for i := 0; i < len(n.indices); i++ { + if c == n.indices[i] { + n = n.children[i] + continue walk + } + } + + // Nothing found. + // We can recommend to redirect to the same URL without a + // trailing slash if a leaf exists for that path. + tsr = path == "/" && n.handlers != nil + return + } + + // handle wildcard child + n = n.children[0] + switch n.nType { + case param: + // find param end (either '/' or path end) + end := 0 + for end < len(path) && path[end] != '/' { + end++ + } + + // save param value + if cap(p) < int(n.maxParams) { + p = make(Params, 0, n.maxParams) + } + i := len(p) + p = p[:i+1] // expand slice within preallocated capacity + p[i].Key = n.path[1:] + val := path[:end] + if unescape { + var err error + if p[i].Value, err = url.QueryUnescape(val); err != nil { + p[i].Value = val // fallback, in case of error + } + } else { + p[i].Value = val + } + + // we need to go deeper! + if end < len(path) { + if len(n.children) > 0 { + path = path[end:] + n = n.children[0] + continue walk + } + + // ... but we can't + tsr = len(path) == end+1 + return + } + + if handlers = n.handlers; handlers != nil { + return + } + if len(n.children) == 1 { + // No handle found. Check if a handle for this path + a + // trailing slash exists for TSR recommendation + n = n.children[0] + tsr = n.path == "/" && n.handlers != nil + } + + return + + case catchAll: + // save param value + if cap(p) < int(n.maxParams) { + p = make(Params, 0, n.maxParams) + } + i := len(p) + p = p[:i+1] // expand slice within preallocated capacity + p[i].Key = n.path[2:] + if unescape { + var err error + if p[i].Value, err = url.QueryUnescape(path); err != nil { + p[i].Value = path // fallback, in case of error + } + } else { + p[i].Value = path + } + + handlers = n.handlers + return + + default: + panic("invalid node type") + } + } + } else if path == n.path { + // We should have reached the node containing the handle. + // Check if this node has a handle registered. + if handlers = n.handlers; handlers != nil { + return + } + + if path == "/" && n.wildChild && n.nType != root { + tsr = true + return + } + + // No handle found. Check if a handle for this path + a + // trailing slash exists for trailing slash recommendation + for i := 0; i < len(n.indices); i++ { + if n.indices[i] == '/' { + n = n.children[i] + tsr = (len(n.path) == 1 && n.handlers != nil) || + (n.nType == catchAll && n.children[0].handlers != nil) + return + } + } + + return + } + + // Nothing found. We can recommend to redirect to the same URL with an + // extra trailing slash if a leaf exists for that path + tsr = (path == "/") || + (len(n.path) == len(path)+1 && n.path[len(path)] == '/' && + path == n.path[:len(n.path)-1] && n.handlers != nil) + return + } +} + +// findCaseInsensitivePath makes a case-insensitive lookup of the given path and tries to find a handler. +// It can optionally also fix trailing slashes. +// It returns the case-corrected path and a bool indicating whether the lookup +// was successful. +func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) (ciPath []byte, found bool) { + ciPath = make([]byte, 0, len(path)+1) // preallocate enough memory + + // Outer loop for walking the tree + for len(path) >= len(n.path) && strings.ToLower(path[:len(n.path)]) == strings.ToLower(n.path) { + path = path[len(n.path):] + ciPath = append(ciPath, n.path...) + + if len(path) > 0 { + // If this node does not have a wildcard (param or catchAll) child, + // we can just look up the next child node and continue to walk down + // the tree + if !n.wildChild { + r := unicode.ToLower(rune(path[0])) + for i, index := range n.indices { + // must use recursive approach since both index and + // ToLower(index) could exist. We must check both. + if r == unicode.ToLower(index) { + out, found := n.children[i].findCaseInsensitivePath(path, fixTrailingSlash) + if found { + return append(ciPath, out...), true + } + } + } + + // Nothing found. We can recommend to redirect to the same URL + // without a trailing slash if a leaf exists for that path + found = fixTrailingSlash && path == "/" && n.handlers != nil + return + } + + n = n.children[0] + switch n.nType { + case param: + // find param end (either '/' or path end) + k := 0 + for k < len(path) && path[k] != '/' { + k++ + } + + // add param value to case insensitive path + ciPath = append(ciPath, path[:k]...) + + // we need to go deeper! + if k < len(path) { + if len(n.children) > 0 { + path = path[k:] + n = n.children[0] + continue + } + + // ... but we can't + if fixTrailingSlash && len(path) == k+1 { + return ciPath, true + } + return + } + + if n.handlers != nil { + return ciPath, true + } else if fixTrailingSlash && len(n.children) == 1 { + // No handle found. Check if a handle for this path + a + // trailing slash exists + n = n.children[0] + if n.path == "/" && n.handlers != nil { + return append(ciPath, '/'), true + } + } + return + + case catchAll: + return append(ciPath, path...), true + + default: + panic("invalid node type") + } + } else { + // We should have reached the node containing the handle. + // Check if this node has a handle registered. + if n.handlers != nil { + return ciPath, true + } + + // No handle found. + // Try to fix the path by adding a trailing slash + if fixTrailingSlash { + for i := 0; i < len(n.indices); i++ { + if n.indices[i] == '/' { + n = n.children[i] + if (len(n.path) == 1 && n.handlers != nil) || + (n.nType == catchAll && n.children[0].handlers != nil) { + return append(ciPath, '/'), true + } + return + } + } + } + return + } + } + + // Nothing found. + // Try to fix the path by adding / removing a trailing slash + if fixTrailingSlash { + if path == "/" { + return ciPath, true + } + if len(path)+1 == len(n.path) && n.path[len(path)] == '/' && + strings.ToLower(path) == strings.ToLower(n.path[:len(path)]) && + n.handlers != nil { + return append(ciPath, n.path...), true + } + } + return +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/utils.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/utils.go new file mode 100644 index 0000000..f4532d5 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/utils.go @@ -0,0 +1,151 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +import ( + "encoding/xml" + "net/http" + "os" + "path" + "reflect" + "runtime" + "strings" +) + +// BindKey indicates a default bind key. +const BindKey = "_gin-gonic/gin/bindkey" + +// Bind is a helper function for given interface object and returns a Gin middleware. +func Bind(val interface{}) HandlerFunc { + value := reflect.ValueOf(val) + if value.Kind() == reflect.Ptr { + panic(`Bind struct can not be a pointer. Example: + Use: gin.Bind(Struct{}) instead of gin.Bind(&Struct{}) +`) + } + typ := value.Type() + + return func(c *Context) { + obj := reflect.New(typ).Interface() + if c.Bind(obj) == nil { + c.Set(BindKey, obj) + } + } +} + +// WrapF is a helper function for wrapping http.HandlerFunc and returns a Gin middleware. +func WrapF(f http.HandlerFunc) HandlerFunc { + return func(c *Context) { + f(c.Writer, c.Request) + } +} + +// WrapH is a helper function for wrapping http.Handler and returns a Gin middleware. +func WrapH(h http.Handler) HandlerFunc { + return func(c *Context) { + h.ServeHTTP(c.Writer, c.Request) + } +} + +// H is a shortcut for map[string]interface{} +type H map[string]interface{} + +// MarshalXML allows type H to be used with xml.Marshal. +func (h H) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + start.Name = xml.Name{ + Space: "", + Local: "map", + } + if err := e.EncodeToken(start); err != nil { + return err + } + for key, value := range h { + elem := xml.StartElement{ + Name: xml.Name{Space: "", Local: key}, + Attr: []xml.Attr{}, + } + if err := e.EncodeElement(value, elem); err != nil { + return err + } + } + + return e.EncodeToken(xml.EndElement{Name: start.Name}) +} + +func assert1(guard bool, text string) { + if !guard { + panic(text) + } +} + +func filterFlags(content string) string { + for i, char := range content { + if char == ' ' || char == ';' { + return content[:i] + } + } + return content +} + +func chooseData(custom, wildcard interface{}) interface{} { + if custom == nil { + if wildcard == nil { + panic("negotiation config is invalid") + } + return wildcard + } + return custom +} + +func parseAccept(acceptHeader string) []string { + parts := strings.Split(acceptHeader, ",") + out := make([]string, 0, len(parts)) + for _, part := range parts { + if part = strings.TrimSpace(strings.Split(part, ";")[0]); part != "" { + out = append(out, part) + } + } + return out +} + +func lastChar(str string) uint8 { + if str == "" { + panic("The length of the string can't be 0") + } + return str[len(str)-1] +} + +func nameOfFunction(f interface{}) string { + return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name() +} + +func joinPaths(absolutePath, relativePath string) string { + if relativePath == "" { + return absolutePath + } + + finalPath := path.Join(absolutePath, relativePath) + appendSlash := lastChar(relativePath) == '/' && lastChar(finalPath) != '/' + if appendSlash { + return finalPath + "/" + } + return finalPath +} + +func resolveAddress(addr []string) string { + switch len(addr) { + case 0: + if port := os.Getenv("PORT"); port != "" { + debugPrint("Environment variable PORT=\"%s\"", port) + return ":" + port + } + debugPrint("Environment variable PORT is undefined. Using port :8080 by default") + return ":8080" + case 1: + return addr[0] + default: + panic("too much parameters") + } +} diff --git a/go/src/themaru/vendor/github.com/gin-gonic/gin/version.go b/go/src/themaru/vendor/github.com/gin-gonic/gin/version.go new file mode 100644 index 0000000..07e7859 --- /dev/null +++ b/go/src/themaru/vendor/github.com/gin-gonic/gin/version.go @@ -0,0 +1,8 @@ +// Copyright 2018 Gin Core Team. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package gin + +// Version is the current gin framework's version. +const Version = "v1.4.0" diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/AUTHORS b/go/src/themaru/vendor/github.com/golang/protobuf/AUTHORS new file mode 100644 index 0000000..15167cd --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/CONTRIBUTORS b/go/src/themaru/vendor/github.com/golang/protobuf/CONTRIBUTORS new file mode 100644 index 0000000..1c4577e --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/LICENSE b/go/src/themaru/vendor/github.com/golang/protobuf/LICENSE new file mode 100644 index 0000000..0f64693 --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/LICENSE @@ -0,0 +1,28 @@ +Copyright 2010 The Go Authors. All rights reserved. + +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. + diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/clone.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/clone.go new file mode 100644 index 0000000..3cd3249 --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/clone.go @@ -0,0 +1,253 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2011 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. + +// Protocol buffer deep copy and merge. +// TODO: RawMessage. + +package proto + +import ( + "fmt" + "log" + "reflect" + "strings" +) + +// Clone returns a deep copy of a protocol buffer. +func Clone(src Message) Message { + in := reflect.ValueOf(src) + if in.IsNil() { + return src + } + out := reflect.New(in.Type().Elem()) + 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. +// 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 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() { + panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src)) + } + if in.IsNil() { + return // Merge from nil src is a noop + } + if m, ok := dst.(generatedMerger); ok { + m.XXX_Merge(src) + return + } + mergeStruct(out.Elem(), in.Elem()) +} + +func mergeStruct(out, in reflect.Value) { + sprop := GetProperties(in.Type()) + for i := 0; i < in.NumField(); i++ { + f := in.Type().Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) + } + + 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() + } + } + + uf := in.FieldByName("XXX_unrecognized") + if !uf.IsValid() { + return + } + uin := uf.Bytes() + if len(uin) > 0 { + out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...)) + } +} + +// mergeAny performs a merge between two values of the same type. +// viaPtr indicates whether the values were indirected through a pointer (implying proto2). +// prop is set if this is a struct field (it may be nil). +func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) { + if in.Type() == protoMessageType { + if !in.IsNil() { + if out.IsNil() { + out.Set(reflect.ValueOf(Clone(in.Interface().(Message)))) + } else { + Merge(out.Interface().(Message), in.Interface().(Message)) + } + } + return + } + switch in.Kind() { + case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, + reflect.String, reflect.Uint32, reflect.Uint64: + if !viaPtr && isProto3Zero(in) { + return + } + out.Set(in) + case reflect.Interface: + // Probably a oneof field; copy non-nil values. + if in.IsNil() { + return + } + // Allocate destination if it is not set, or set to a different type. + // Otherwise we will merge as normal. + if out.IsNil() || out.Elem().Type() != in.Elem().Type() { + out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T) + } + mergeAny(out.Elem(), in.Elem(), false, nil) + case reflect.Map: + if in.Len() == 0 { + return + } + if out.IsNil() { + out.Set(reflect.MakeMap(in.Type())) + } + // For maps with value types of *T or []byte we need to deep copy each value. + elemKind := in.Type().Elem().Kind() + for _, key := range in.MapKeys() { + var val reflect.Value + switch elemKind { + case reflect.Ptr: + val = reflect.New(in.Type().Elem().Elem()) + mergeAny(val, in.MapIndex(key), false, nil) + case reflect.Slice: + val = in.MapIndex(key) + val = reflect.ValueOf(append([]byte{}, val.Bytes()...)) + default: + val = in.MapIndex(key) + } + out.SetMapIndex(key, val) + } + case reflect.Ptr: + if in.IsNil() { + return + } + if out.IsNil() { + out.Set(reflect.New(in.Elem().Type())) + } + mergeAny(out.Elem(), in.Elem(), true, nil) + case reflect.Slice: + if in.IsNil() { + return + } + if in.Type().Elem().Kind() == reflect.Uint8 { + // []byte is a scalar bytes field, not a repeated field. + + // Edge case: if this is in a proto3 message, a zero length + // bytes field is considered the zero value, and should not + // be merged. + if prop != nil && prop.proto3 && in.Len() == 0 { + return + } + + // Make a deep copy. + // Append to []byte{} instead of []byte(nil) so that we never end up + // with a nil result. + out.SetBytes(append([]byte{}, in.Bytes()...)) + return + } + n := in.Len() + if out.IsNil() { + out.Set(reflect.MakeSlice(in.Type(), 0, n)) + } + switch in.Type().Elem().Kind() { + case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, + reflect.String, reflect.Uint32, reflect.Uint64: + out.Set(reflect.AppendSlice(out, in)) + default: + for i := 0; i < n; i++ { + x := reflect.Indirect(reflect.New(in.Type().Elem())) + mergeAny(x, in.Index(i), false, nil) + out.Set(reflect.Append(out, x)) + } + } + case reflect.Struct: + mergeStruct(out, in) + default: + // unknown type, so not a protocol buffer + log.Printf("proto: don't know how to copy %v", in) + } +} + +func mergeExtension(out, in map[int32]Extension) { + for extNum, eIn := range in { + eOut := Extension{desc: eIn.desc} + if eIn.value != nil { + v := reflect.New(reflect.TypeOf(eIn.value)).Elem() + mergeAny(v, reflect.ValueOf(eIn.value), false, nil) + eOut.value = v.Interface() + } + if eIn.enc != nil { + eOut.enc = make([]byte, len(eIn.enc)) + copy(eOut.enc, eIn.enc) + } + + out[extNum] = eOut + } +} diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/decode.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/decode.go new file mode 100644 index 0000000..63b0f08 --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/decode.go @@ -0,0 +1,427 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Routines for decoding protocol buffer data to construct in-memory representations. + */ + +import ( + "errors" + "fmt" + "io" +) + +// errOverflow is returned when an integer is too large to be represented. +var errOverflow = errors.New("proto: integer overflow") + +// ErrInternalBadWireType is returned by generated code when an incorrect +// wire type is encountered. It does not get returned to user code. +var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof") + +// 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. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func DecodeVarint(buf []byte) (x uint64, n int) { + for shift := uint(0); shift < 64; shift += 7 { + if n >= len(buf) { + return 0, 0 + } + b := uint64(buf[n]) + n++ + x |= (b & 0x7F) << shift + if (b & 0x80) == 0 { + return x, n + } + } + + // The number is too large to represent in a 64-bit value. + return 0, 0 +} + +func (p *Buffer) decodeVarintSlow() (x uint64, err error) { + i := p.index + l := len(p.buf) + + for shift := uint(0); shift < 64; shift += 7 { + if i >= l { + err = io.ErrUnexpectedEOF + return + } + b := p.buf[i] + i++ + x |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + p.index = i + return + } + } + + // The number is too large to represent in a 64-bit value. + err = errOverflow + return +} + +// DecodeVarint reads a varint-encoded integer from the Buffer. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func (p *Buffer) DecodeVarint() (x uint64, err error) { + i := p.index + buf := p.buf + + if i >= len(buf) { + return 0, io.ErrUnexpectedEOF + } else if buf[i] < 0x80 { + p.index++ + return uint64(buf[i]), nil + } else if len(buf)-i < 10 { + return p.decodeVarintSlow() + } + + var b uint64 + // we already checked the first byte + x = uint64(buf[i]) - 0x80 + i++ + + b = uint64(buf[i]) + i++ + x += b << 7 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 7 + + b = uint64(buf[i]) + i++ + x += b << 14 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 14 + + b = uint64(buf[i]) + i++ + x += b << 21 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 21 + + b = uint64(buf[i]) + i++ + x += b << 28 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 28 + + b = uint64(buf[i]) + i++ + x += b << 35 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 35 + + b = uint64(buf[i]) + i++ + x += b << 42 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 42 + + b = uint64(buf[i]) + i++ + x += b << 49 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 49 + + b = uint64(buf[i]) + i++ + x += b << 56 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 56 + + b = uint64(buf[i]) + i++ + x += b << 63 + if b&0x80 == 0 { + goto done + } + + return 0, errOverflow + +done: + p.index = i + return x, nil +} + +// DecodeFixed64 reads a 64-bit integer from the Buffer. +// This is the format for the +// fixed64, sfixed64, and double protocol buffer types. +func (p *Buffer) DecodeFixed64() (x uint64, err error) { + // x, err already 0 + i := p.index + 8 + if i < 0 || i > len(p.buf) { + err = io.ErrUnexpectedEOF + return + } + p.index = i + + x = uint64(p.buf[i-8]) + x |= uint64(p.buf[i-7]) << 8 + x |= uint64(p.buf[i-6]) << 16 + x |= uint64(p.buf[i-5]) << 24 + x |= uint64(p.buf[i-4]) << 32 + x |= uint64(p.buf[i-3]) << 40 + x |= uint64(p.buf[i-2]) << 48 + x |= uint64(p.buf[i-1]) << 56 + return +} + +// DecodeFixed32 reads a 32-bit integer from the Buffer. +// This is the format for the +// fixed32, sfixed32, and float protocol buffer types. +func (p *Buffer) DecodeFixed32() (x uint64, err error) { + // x, err already 0 + i := p.index + 4 + if i < 0 || i > len(p.buf) { + err = io.ErrUnexpectedEOF + return + } + p.index = i + + x = uint64(p.buf[i-4]) + x |= uint64(p.buf[i-3]) << 8 + x |= uint64(p.buf[i-2]) << 16 + x |= uint64(p.buf[i-1]) << 24 + return +} + +// DecodeZigzag64 reads a zigzag-encoded 64-bit integer +// from the Buffer. +// This is the format used for the sint64 protocol buffer type. +func (p *Buffer) DecodeZigzag64() (x uint64, err error) { + x, err = p.DecodeVarint() + if err != nil { + return + } + x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63) + return +} + +// DecodeZigzag32 reads a zigzag-encoded 32-bit integer +// from the Buffer. +// This is the format used for the sint32 protocol buffer type. +func (p *Buffer) DecodeZigzag32() (x uint64, err error) { + x, err = p.DecodeVarint() + if err != nil { + return + } + x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31)) + return +} + +// 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. +func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) { + n, err := p.DecodeVarint() + if err != nil { + return nil, err + } + + nb := int(n) + if nb < 0 { + return nil, fmt.Errorf("proto: bad byte length %d", nb) + } + end := p.index + nb + if end < p.index || end > len(p.buf) { + return nil, io.ErrUnexpectedEOF + } + + if !alloc { + // todo: check if can get more uses of alloc=false + buf = p.buf[p.index:end] + p.index += nb + return + } + + buf = make([]byte, nb) + copy(buf, p.buf[p.index:]) + p.index += nb + return +} + +// DecodeStringBytes reads an encoded string from the Buffer. +// This is the format used for the proto2 string type. +func (p *Buffer) DecodeStringBytes() (s string, err error) { + buf, err := p.DecodeRawBytes(false) + if err != nil { + return + } + return string(buf), nil +} + +// Unmarshaler is the interface representing objects that can +// 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. +// +// Unmarshal resets pb before starting to unmarshal, so any +// existing data in pb is always removed. Use UnmarshalMerge +// to preserve and append to existing data. +func Unmarshal(buf []byte, pb Message) error { + pb.Reset() + 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 +// writes the decoded result to pb. If the struct underlying pb does not match +// the data in buf, the results can be unpredictable. +// +// UnmarshalMerge merges into existing data in pb. +// Most code should use Unmarshal instead. +func UnmarshalMerge(buf []byte, pb Message) error { + 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) +} + +// DecodeMessage reads a count-delimited message from the Buffer. +func (p *Buffer) DecodeMessage(pb Message) error { + enc, err := p.DecodeRawBytes(false) + if err != nil { + return err + } + return NewBuffer(enc).Unmarshal(pb) +} + +// 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 { + b := p.buf[p.index:] + x, y := findEndGroup(b) + if x < 0 { + return io.ErrUnexpectedEOF + } + err := Unmarshal(b[:x], pb) + p.index += y + return err +} + +// Unmarshal parses the protocol buffer representation in the +// Buffer and places the decoded result in pb. If the struct +// underlying pb does not match the data in the buffer, the results can be +// unpredictable. +// +// 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 + } + + // 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 +} diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/deprecated.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/deprecated.go new file mode 100644 index 0000000..35b882c --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/deprecated.go @@ -0,0 +1,63 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2018 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 "errors" + +// Deprecated: do not use. +type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 } + +// Deprecated: do not use. +func GetStats() Stats { return Stats{} } + +// Deprecated: do not use. +func MarshalMessageSet(interface{}) ([]byte, error) { + return nil, errors.New("proto: not implemented") +} + +// Deprecated: do not use. +func UnmarshalMessageSet([]byte, interface{}) error { + return errors.New("proto: not implemented") +} + +// Deprecated: do not use. +func MarshalMessageSetJSON(interface{}) ([]byte, error) { + return nil, errors.New("proto: not implemented") +} + +// Deprecated: do not use. +func UnmarshalMessageSetJSON([]byte, interface{}) error { + return errors.New("proto: not implemented") +} + +// Deprecated: do not use. +func RegisterMessageSetType(Message, int32, string) {} diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/discard.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/discard.go new file mode 100644 index 0000000..dea2617 --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/discard.go @@ -0,0 +1,350 @@ +// 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 + +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. +// +// When unmarshaling a message with unrecognized fields, the tags and values +// of such fields are preserved in the Message. This allows a later call to +// marshal to be able to produce a message that continues to have those +// unrecognized fields. To avoid this, DiscardUnknown is used to +// explicitly clear the unknown fields after unmarshaling. +// +// 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 + di := getDiscardInfo(tf) + dfi.discard = func(src pointer) { + sps := src.getPointerSlice() + for _, sp := range sps { + if !sp.isNil() { + di.discard(sp) + } + } + } + default: // E.g., *pb.T + di := getDiscardInfo(tf) + dfi.discard = func(src pointer) { + sp := src.getPointer() + if !sp.isNil() { + di.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() { + return + } + v = v.Elem() + if v.Kind() != reflect.Struct { + return + } + t := v.Type() + + for i := 0; i < v.NumField(); i++ { + f := t.Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + vf := v.Field(i) + 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("%T.%s cannot be a slice of pointers to primitive types", m, f.Name)) + } + + switch tf.Kind() { + case reflect.Struct: + switch { + case !isPointer: + panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name)) + case isSlice: // E.g., []*pb.T + for j := 0; j < vf.Len(); j++ { + discardLegacy(vf.Index(j).Interface().(Message)) + } + default: // E.g., *pb.T + discardLegacy(vf.Interface().(Message)) + } + case reflect.Map: + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name)) + default: // E.g., map[K]V + tv := vf.Type().Elem() + if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T) + for _, key := range vf.MapKeys() { + val := vf.MapIndex(key) + discardLegacy(val.Interface().(Message)) + } + } + } + case reflect.Interface: + // Must be oneof field. + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name)) + default: // E.g., test_proto.isCommunique_Union interface + if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" { + vf = vf.Elem() // E.g., *test_proto.Communique_Msg + if !vf.IsNil() { + vf = vf.Elem() // E.g., test_proto.Communique_Msg + vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value + if vf.Kind() == reflect.Ptr { + discardLegacy(vf.Interface().(Message)) + } + } + } + } + } + } + + if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() { + if vf.Type() != reflect.TypeOf([]byte{}) { + panic("expected XXX_unrecognized to be of type []byte") + } + vf.Set(reflect.ValueOf([]byte(nil))) + } + + // For proto2 messages, only discard unknown fields in message extensions + // that have been accessed via GetExtension. + if em, err := extendable(m); err == nil { + // Ignore lock since discardLegacy is not concurrency safe. + emm, _ := em.extensionsRead() + for _, mx := range emm { + if m, ok := mx.value.(Message); ok { + discardLegacy(m) + } + } + } +} diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/encode.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/encode.go new file mode 100644 index 0000000..3abfed2 --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/encode.go @@ -0,0 +1,203 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Routines for encoding data into the wire format for protocol buffers. + */ + +import ( + "errors" + "reflect" +) + +var ( + // errRepeatedHasNil is the error returned if Marshal is called with + // a struct with a repeated field containing a nil element. + errRepeatedHasNil = errors.New("proto: repeated field has nil element") + + // errOneofHasNil is the error returned if Marshal is called with + // a struct with a oneof field containing a nil element. + errOneofHasNil = errors.New("proto: oneof field has nil value") + + // ErrNil is the error returned if Marshal is called with nil. + ErrNil = errors.New("proto: Marshal called with nil") + + // ErrTooLarge is the error returned if Marshal is called with a + // message that encodes to >2GB. + ErrTooLarge = errors.New("proto: message encodes to over 2 GB") +) + +// The fundamental encoders that put bytes on the wire. +// Those that take integer types all accept uint64 and are +// therefore of type valueEncoder. + +const maxVarintBytes = 10 // maximum length of a varint + +// EncodeVarint returns the varint encoding of x. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +// Not used by the package itself, but helpful to clients +// wishing to use the same encoding. +func EncodeVarint(x uint64) []byte { + var buf [maxVarintBytes]byte + var n int + for n = 0; x > 127; n++ { + buf[n] = 0x80 | uint8(x&0x7F) + x >>= 7 + } + buf[n] = uint8(x) + n++ + return buf[0:n] +} + +// EncodeVarint writes a varint-encoded integer to the Buffer. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func (p *Buffer) EncodeVarint(x uint64) error { + for x >= 1<<7 { + p.buf = append(p.buf, uint8(x&0x7f|0x80)) + x >>= 7 + } + p.buf = append(p.buf, uint8(x)) + return nil +} + +// SizeVarint returns the varint encoding size of an integer. +func SizeVarint(x uint64) int { + switch { + case x < 1<<7: + return 1 + case x < 1<<14: + return 2 + case x < 1<<21: + return 3 + case x < 1<<28: + return 4 + case x < 1<<35: + return 5 + case x < 1<<42: + return 6 + case x < 1<<49: + return 7 + case x < 1<<56: + return 8 + case x < 1<<63: + return 9 + } + return 10 +} + +// EncodeFixed64 writes a 64-bit integer to the Buffer. +// This is the format for the +// fixed64, sfixed64, and double protocol buffer types. +func (p *Buffer) EncodeFixed64(x uint64) error { + p.buf = append(p.buf, + uint8(x), + uint8(x>>8), + uint8(x>>16), + uint8(x>>24), + uint8(x>>32), + uint8(x>>40), + uint8(x>>48), + uint8(x>>56)) + return nil +} + +// EncodeFixed32 writes a 32-bit integer to the Buffer. +// This is the format for the +// fixed32, sfixed32, and float protocol buffer types. +func (p *Buffer) EncodeFixed32(x uint64) error { + p.buf = append(p.buf, + uint8(x), + uint8(x>>8), + uint8(x>>16), + uint8(x>>24)) + return nil +} + +// EncodeZigzag64 writes a zigzag-encoded 64-bit integer +// to the Buffer. +// This is the format used for the sint64 protocol buffer type. +func (p *Buffer) EncodeZigzag64(x uint64) error { + // use signed number to get arithmetic right shift. + return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} + +// EncodeZigzag32 writes a zigzag-encoded 32-bit integer +// to the Buffer. +// This is the format used for the sint32 protocol buffer type. +func (p *Buffer) EncodeZigzag32(x uint64) error { + // use signed number to get arithmetic right shift. + return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) +} + +// EncodeRawBytes writes a count-delimited byte buffer to the Buffer. +// This is the format used for the bytes protocol buffer +// type and for embedded messages. +func (p *Buffer) EncodeRawBytes(b []byte) error { + p.EncodeVarint(uint64(len(b))) + p.buf = append(p.buf, b...) + return nil +} + +// EncodeStringBytes writes an encoded string to the Buffer. +// This is the format used for the proto2 string type. +func (p *Buffer) EncodeStringBytes(s string) error { + p.EncodeVarint(uint64(len(s))) + p.buf = append(p.buf, s...) + return nil +} + +// Marshaler is the interface representing objects that can marshal themselves. +type Marshaler interface { + Marshal() ([]byte, error) +} + +// EncodeMessage writes the protocol buffer to the Buffer, +// prefixed by a varint-encoded length. +func (p *Buffer) EncodeMessage(pb Message) error { + siz := Size(pb) + p.EncodeVarint(uint64(siz)) + return p.Marshal(pb) +} + +// All protocol buffer fields are nillable, but be careful. +func isNil(v reflect.Value) bool { + switch v.Kind() { + case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + return v.IsNil() + } + return false +} diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/equal.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/equal.go new file mode 100644 index 0000000..f9b6e41 --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/equal.go @@ -0,0 +1,301 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2011 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. + +// Protocol buffer comparison. + +package proto + +import ( + "bytes" + "log" + "reflect" + "strings" +) + +/* +Equal returns true iff protocol buffers a and b are equal. +The arguments must both be pointers to protocol buffer structs. + +Equality is defined in this way: + - Two messages are equal iff they are the same type, + corresponding fields are equal, unknown field sets + are equal, and extensions sets are equal. + - Two set scalar fields are equal iff their values are equal. + If the fields are of a floating-point type, remember that + NaN != x for all x, including NaN. If the message is defined + in a proto3 .proto file, fields are not "set"; specifically, + zero length proto3 "bytes" fields are equal (nil == {}). + - Two repeated fields are equal iff their lengths are the same, + and their corresponding elements are equal. Note a "bytes" field, + although represented by []byte, is not a repeated field and the + rule for the scalar fields described above applies. + - Two unset fields are equal. + - Two unknown field sets are equal if their current + encoded state is equal. + - Two extension sets are equal iff they have corresponding + elements that are pairwise equal. + - Two map fields are equal iff their lengths are the same, + and they contain the same set of elements. Zero-length map + fields are equal. + - Every other combination of things are not equal. + +The return value is undefined if a and b are not protocol buffers. +*/ +func Equal(a, b Message) bool { + if a == nil || b == nil { + return a == b + } + v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b) + if v1.Type() != v2.Type() { + return false + } + if v1.Kind() == reflect.Ptr { + if v1.IsNil() { + return v2.IsNil() + } + if v2.IsNil() { + return false + } + v1, v2 = v1.Elem(), v2.Elem() + } + if v1.Kind() != reflect.Struct { + return false + } + return equalStruct(v1, v2) +} + +// v1 and v2 are known to have the same type. +func equalStruct(v1, v2 reflect.Value) bool { + sprop := GetProperties(v1.Type()) + for i := 0; i < v1.NumField(); i++ { + f := v1.Type().Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + f1, f2 := v1.Field(i), v2.Field(i) + if f.Type.Kind() == reflect.Ptr { + if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 { + // both unset + continue + } else if n1 != n2 { + // set/unset mismatch + return false + } + f1, f2 = f1.Elem(), f2.Elem() + } + if !equalAny(f1, f2, sprop.Prop[i]) { + return false + } + } + + if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() { + em2 := v2.FieldByName("XXX_InternalExtensions") + if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) { + return false + } + } + + if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() { + em2 := v2.FieldByName("XXX_extensions") + if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) { + return false + } + } + + uf := v1.FieldByName("XXX_unrecognized") + if !uf.IsValid() { + return true + } + + u1 := uf.Bytes() + u2 := v2.FieldByName("XXX_unrecognized").Bytes() + return bytes.Equal(u1, u2) +} + +// v1 and v2 are known to have the same type. +// prop may be nil. +func equalAny(v1, v2 reflect.Value, prop *Properties) bool { + if v1.Type() == protoMessageType { + m1, _ := v1.Interface().(Message) + m2, _ := v2.Interface().(Message) + return Equal(m1, m2) + } + switch v1.Kind() { + case reflect.Bool: + return v1.Bool() == v2.Bool() + case reflect.Float32, reflect.Float64: + return v1.Float() == v2.Float() + case reflect.Int32, reflect.Int64: + return v1.Int() == v2.Int() + case reflect.Interface: + // Probably a oneof field; compare the inner values. + n1, n2 := v1.IsNil(), v2.IsNil() + if n1 || n2 { + return n1 == n2 + } + e1, e2 := v1.Elem(), v2.Elem() + if e1.Type() != e2.Type() { + return false + } + return equalAny(e1, e2, nil) + case reflect.Map: + if v1.Len() != v2.Len() { + return false + } + for _, key := range v1.MapKeys() { + val2 := v2.MapIndex(key) + if !val2.IsValid() { + // This key was not found in the second map. + return false + } + if !equalAny(v1.MapIndex(key), val2, nil) { + return false + } + } + return true + case reflect.Ptr: + // Maps may have nil values in them, so check for nil. + if v1.IsNil() && v2.IsNil() { + return true + } + if v1.IsNil() != v2.IsNil() { + return false + } + return equalAny(v1.Elem(), v2.Elem(), prop) + case reflect.Slice: + if v1.Type().Elem().Kind() == reflect.Uint8 { + // short circuit: []byte + + // Edge case: if this is in a proto3 message, a zero length + // bytes field is considered the zero value. + if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 { + return true + } + if v1.IsNil() != v2.IsNil() { + return false + } + return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte)) + } + + if v1.Len() != v2.Len() { + return false + } + for i := 0; i < v1.Len(); i++ { + if !equalAny(v1.Index(i), v2.Index(i), prop) { + return false + } + } + return true + case reflect.String: + return v1.Interface().(string) == v2.Interface().(string) + case reflect.Struct: + return equalStruct(v1, v2) + case reflect.Uint32, reflect.Uint64: + return v1.Uint() == v2.Uint() + } + + // unknown type, so not a protocol buffer + log.Printf("proto: don't know how to compare %v", v1) + return false +} + +// base is the struct type that the extensions are based on. +// x1 and x2 are InternalExtensions. +func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool { + em1, _ := x1.extensionsRead() + em2, _ := x2.extensionsRead() + return equalExtMap(base, em1, em2) +} + +func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool { + if len(em1) != len(em2) { + return false + } + + for extNum, e1 := range em1 { + e2, ok := em2[extNum] + if !ok { + return false + } + + m1 := extensionAsLegacyType(e1.value) + m2 := extensionAsLegacyType(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) { + return false + } + continue + } + + // At least one is encoded. To do a semantically correct comparison + // we need to unmarshal them first. + var desc *ExtensionDesc + if m := extensionMaps[base]; m != nil { + 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) + return false + } + var err error + if m1 == nil { + m1, err = decodeExtension(e1.enc, desc) + } + if m2 == nil && err == nil { + m2, err = decodeExtension(e2.enc, desc) + } + if err != nil { + // The encoded form is invalid. + log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err) + return false + } + if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) { + return false + } + } + + return true +} diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/extensions.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/extensions.go new file mode 100644 index 0000000..fa88add --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/extensions.go @@ -0,0 +1,607 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Types and routines for supporting protocol buffer extensions. + */ + +import ( + "errors" + "fmt" + "io" + "reflect" + "strconv" + "sync" +) + +// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message. +var ErrMissingExtension = errors.New("proto: missing extension") + +// ExtensionRange represents a range of message extensions for a protocol buffer. +// Used in code generated by the protocol compiler. +type ExtensionRange struct { + Start, End int32 // both inclusive +} + +// extendableProto is an interface implemented by any protocol buffer generated by the current +// proto compiler that may be extended. +type extendableProto interface { + Message + ExtensionRangeArray() []ExtensionRange + extensionsWrite() map[int32]Extension + extensionsRead() (map[int32]Extension, sync.Locker) +} + +// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous +// version of the proto compiler that may be extended. +type extendableProtoV1 interface { + Message + ExtensionRangeArray() []ExtensionRange + ExtensionMap() map[int32]Extension +} + +// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto. +type extensionAdapter struct { + extendableProtoV1 +} + +func (e extensionAdapter) extensionsWrite() map[int32]Extension { + return e.ExtensionMap() +} + +func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) { + return e.ExtensionMap(), notLocker{} +} + +// notLocker is a sync.Locker whose Lock and Unlock methods are nops. +type notLocker struct{} + +func (n notLocker) Lock() {} +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, 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 + } + // 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. +// +// Each generated message struct type embeds an anonymous XXX_InternalExtensions field, +// thus gaining the unexported 'extensions' method, which can be called only from the proto package. +// +// The methods of XXX_InternalExtensions are not concurrency safe in general, +// but calls to logically read-only methods such as has and get may be executed concurrently. +type XXX_InternalExtensions struct { + // The struct must be indirect so that if a user inadvertently copies a + // generated message and its embedded XXX_InternalExtensions, they + // avoid the mayhem of a copied mutex. + // + // The mutex serializes all logically read-only operations to p.extensionMap. + // It is up to the client to ensure that write operations to p.extensionMap are + // mutually exclusive with other accesses. + p *struct { + mu sync.Mutex + extensionMap map[int32]Extension + } +} + +// extensionsWrite returns the extension map, creating it on first use. +func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension { + if e.p == nil { + e.p = new(struct { + mu sync.Mutex + extensionMap map[int32]Extension + }) + e.p.extensionMap = make(map[int32]Extension) + } + return e.p.extensionMap +} + +// extensionsRead returns the extensions map for read-only use. It may be nil. +// The caller must hold the returned mutex's lock when accessing Elements within the map. +func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) { + if e.p == nil { + return nil, nil + } + return e.p.extensionMap, &e.p.mu +} + +// ExtensionDesc represents an extension specification. +// Used in generated code from the protocol compiler. +type ExtensionDesc struct { + ExtendedType Message // nil pointer to the type that is being extended + ExtensionType interface{} // nil pointer to the extension type + Field int32 // field number + Name string // fully-qualified name of extension, for text formatting + Tag string // protobuf tag style + Filename string // name of the file in which the extension is defined +} + +func (ed *ExtensionDesc) repeated() bool { + t := reflect.TypeOf(ed.ExtensionType) + return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 +} + +// Extension represents an extension in a message. +type Extension struct { + // When an extension is stored in a message using SetExtension + // only desc and value are set. When the message is marshaled + // enc will be set to the encoded form of the message. + // + // When a message is unmarshaled and contains extensions, each + // extension will have only enc set. When such an extension is + // accessed using GetExtension (or GetExtensions) desc and value + // will be set. + desc *ExtensionDesc + + // value is a concrete value for the extension field. Let the type of + // desc.ExtensionType be the "API type" and the type of Extension.value + // be the "storage type". The API type and storage type are the same except: + // * For scalars (except []byte), the API type uses *T, + // while the storage type uses T. + // * For repeated fields, the API type uses []T, while the storage type + // uses *[]T. + // + // The reason for the divergence is so that the storage type more naturally + // matches what is expected of when retrieving the values through the + // protobuf reflection APIs. + // + // The value may only be populated if desc is also populated. + value interface{} + + // enc is the raw bytes for the extension field. + enc []byte +} + +// SetRawExtension is for testing only. +func SetRawExtension(base Message, id int32, b []byte) { + epb, err := extendable(base) + if err != nil { + return + } + extmap := epb.extensionsWrite() + extmap[id] = Extension{enc: b} +} + +// isExtensionField returns true iff the given field number is in an extension range. +func isExtensionField(pb extendableProto, field int32) bool { + for _, er := range pb.ExtensionRangeArray() { + if er.Start <= field && field <= er.End { + return true + } + } + return false +} + +// checkExtensionTypes checks that the given extension is valid for pb. +func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error { + var pbi interface{} = pb + // Check the extended type. + if ea, ok := pbi.(extensionAdapter); ok { + pbi = ea.extendableProtoV1 + } + if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b { + return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a) + } + // Check the range. + if !isExtensionField(pb, extension.Field) { + return errors.New("proto: bad extension number; not in declared ranges") + } + return nil +} + +// extPropKey is sufficient to uniquely identify an extension. +type extPropKey struct { + base reflect.Type + field int32 +} + +var extProp = struct { + sync.RWMutex + m map[extPropKey]*Properties +}{ + m: make(map[extPropKey]*Properties), +} + +func extensionProperties(ed *ExtensionDesc) *Properties { + key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field} + + extProp.RLock() + if prop, ok := extProp.m[key]; ok { + extProp.RUnlock() + return prop + } + extProp.RUnlock() + + extProp.Lock() + defer extProp.Unlock() + // Check again. + if prop, ok := extProp.m[key]; ok { + return prop + } + + prop := new(Properties) + prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil) + extProp.m[key] = prop + return prop +} + +// HasExtension returns whether the given extension is present in pb. +func HasExtension(pb Message, extension *ExtensionDesc) bool { + // TODO: Check types, field numbers, etc.? + epb, err := extendable(pb) + if err != nil { + return false + } + extmap, mu := epb.extensionsRead() + if extmap == nil { + return false + } + mu.Lock() + _, ok := extmap[extension.Field] + mu.Unlock() + return ok +} + +// ClearExtension removes the given extension from pb. +func ClearExtension(pb Message, extension *ExtensionDesc) { + epb, err := extendable(pb) + if err != nil { + return + } + // TODO: Check types, field numbers, etc.? + extmap := epb.extensionsWrite() + delete(extmap, extension.Field) +} + +// 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) { + 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 err := checkExtensionTypes(epb, extension); err != nil { + return nil, err + } + } + + emap, mu := epb.extensionsRead() + if emap == nil { + return defaultExtensionValue(extension) + } + mu.Lock() + defer mu.Unlock() + e, ok := emap[extension.Field] + if !ok { + // defaultExtensionValue returns the default value or + // ErrMissingExtension if there is no default. + return defaultExtensionValue(extension) + } + + if e.value != nil { + // Already decoded. Check the descriptor, though. + if e.desc != extension { + // This shouldn't happen. If it does, it means that + // GetExtension was called twice with two different + // descriptors with the same field number. + return nil, errors.New("proto: descriptor conflict") + } + return extensionAsLegacyType(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 + } + + // Remember the decoded version and drop the encoded version. + // That way it is safe to mutate what we return. + e.value = extensionAsStorageType(v) + e.desc = extension + e.enc = nil + emap[extension.Field] = e + return extensionAsLegacyType(e.value), nil +} + +// 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) + + sf, _, err := fieldDefault(t, props) + if err != nil { + return nil, err + } + + if sf == nil || sf.value == nil { + // There is no default value. + return nil, ErrMissingExtension + } + + if t.Kind() != reflect.Ptr { + // We do not need to return a Ptr, we can directly return sf.value. + return sf.value, nil + } + + // We need to return an interface{} that is a pointer to sf.value. + value := reflect.New(t).Elem() + value.Set(reflect.New(value.Type().Elem())) + if sf.kind == reflect.Int32 { + // We may have an int32 or an enum, but the underlying data is int32. + // Since we can't set an int32 into a non int32 reflect.value directly + // set it as a int32. + value.Elem().SetInt(int64(sf.value.(int32))) + } else { + value.Elem().Set(reflect.ValueOf(sf.value)) + } + return value.Interface(), nil +} + +// decodeExtension decodes an extension encoded in b. +func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) { + t := reflect.TypeOf(extension.ExtensionType) + unmarshal := typeUnmarshaler(t, extension.Tag) + + // t is a pointer to a struct, pointer to basic type or a slice. + // Allocate space to store the pointer/slice. + value := reflect.New(t).Elem() + + var err error + for { + 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 len(b) == 0 { + break + } + } + return value.Interface(), nil +} + +// 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(epb, e) + if err == ErrMissingExtension { + err = nil + } + if err != nil { + return + } + } + return +} + +// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order. +// 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, err := extendable(pb) + if err != nil { + return nil, err + } + registeredExtensions := RegisteredExtensions(pb) + + emap, mu := epb.extensionsRead() + if emap == nil { + return nil, nil + } + mu.Lock() + defer mu.Unlock() + extensions := make([]*ExtensionDesc, 0, len(emap)) + for extid, e := range emap { + desc := e.desc + if desc == nil { + desc = registeredExtensions[extid] + if desc == nil { + desc = &ExtensionDesc{Field: extid} + } + } + + extensions = append(extensions, desc) + } + return extensions, nil +} + +// SetExtension sets the specified extension of pb to the specified value. +func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error { + epb, err := extendable(pb) + if err != nil { + return err + } + if err := checkExtensionTypes(epb, extension); err != nil { + return err + } + typ := reflect.TypeOf(extension.ExtensionType) + if typ != reflect.TypeOf(value) { + return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType) + } + // nil extension values need to be caught early, because the + // encoder can't distinguish an ErrNil due to a nil extension + // from an ErrNil due to a missing field. Extensions are + // always optional, so the encoder would just swallow the error + // and drop all the extensions from the encoded message. + if reflect.ValueOf(value).IsNil() { + return fmt.Errorf("proto: SetExtension called with nil value of type %T", value) + } + + extmap := epb.extensionsWrite() + extmap[extension.Field] = Extension{desc: extension, value: extensionAsStorageType(value)} + return nil +} + +// ClearAllExtensions clears all extensions from pb. +func ClearAllExtensions(pb Message) { + epb, err := extendable(pb) + if err != nil { + return + } + m := epb.extensionsWrite() + for k := range m { + delete(m, k) + } +} + +// A global registry of extensions. +// The generated code will register the generated descriptors by calling RegisterExtension. + +var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc) + +// RegisterExtension is called from the generated code. +func RegisterExtension(desc *ExtensionDesc) { + st := reflect.TypeOf(desc.ExtendedType).Elem() + m := extensionMaps[st] + if m == nil { + m = make(map[int32]*ExtensionDesc) + extensionMaps[st] = m + } + if _, ok := m[desc.Field]; ok { + panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field))) + } + m[desc.Field] = desc +} + +// RegisteredExtensions returns a map of the registered extensions of a +// protocol buffer struct, indexed by the extension number. +// The argument pb should be a nil pointer to the struct type. +func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc { + return extensionMaps[reflect.TypeOf(pb).Elem()] +} + +// extensionAsLegacyType converts an value in the storage type as the API type. +// See Extension.value. +func extensionAsLegacyType(v interface{}) interface{} { + switch rv := reflect.ValueOf(v); rv.Kind() { + case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String: + // Represent primitive types as a pointer to the value. + rv2 := reflect.New(rv.Type()) + rv2.Elem().Set(rv) + v = rv2.Interface() + case reflect.Ptr: + // Represent slice types as the value itself. + switch rv.Type().Elem().Kind() { + case reflect.Slice: + if rv.IsNil() { + v = reflect.Zero(rv.Type().Elem()).Interface() + } else { + v = rv.Elem().Interface() + } + } + } + return v +} + +// extensionAsStorageType converts an value in the API type as the storage type. +// See Extension.value. +func extensionAsStorageType(v interface{}) interface{} { + switch rv := reflect.ValueOf(v); rv.Kind() { + case reflect.Ptr: + // Represent slice types as the value itself. + switch rv.Type().Elem().Kind() { + case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String: + if rv.IsNil() { + v = reflect.Zero(rv.Type().Elem()).Interface() + } else { + v = rv.Elem().Interface() + } + } + case reflect.Slice: + // Represent slice types as a pointer to the value. + if rv.Type().Elem().Kind() != reflect.Uint8 { + rv2 := reflect.New(rv.Type()) + rv2.Elem().Set(rv) + v = rv2.Interface() + } + } + return v +} diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/lib.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/lib.go new file mode 100644 index 0000000..fdd328b --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/lib.go @@ -0,0 +1,965 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Package proto converts data structures to and from the wire format of +protocol buffers. It works in concert with the Go source code generated +for .proto files by the protocol compiler. + +A summary of the properties of the protocol buffer interface +for a protocol buffer variable v: + + - Names are turned from camel_case to CamelCase for export. + - There are no methods on v to set fields; just treat + them as structure fields. + - There are getters that return a field's value if set, + and return the field's default value if unset. + The getters work even if the receiver is a nil message. + - The zero value for a struct is its correct initialization state. + All desired fields must be set before marshaling. + - A Reset() method will restore a protobuf struct to its zero state. + - Non-repeated fields are pointers to the values; nil means unset. + That is, optional or required field int32 f becomes F *int32. + - Repeated fields are slices. + - Helper functions are available to aid the setting of fields. + msg.Foo = proto.String("hello") // set field + - Constants are defined to hold the default values of all fields that + have them. They have the form Default_StructName_FieldName. + Because the getter methods handle defaulted values, + direct use of these constants should be rare. + - Enums are given type names and maps from names to values. + Enum values are prefixed by the enclosing message's name, or by the + enum's type name if it is a top-level enum. Enum types have a String + method, and a Enum method to assist in message construction. + - Nested messages, groups and enums have type names prefixed with the name of + the surrounding message type. + - Extensions are given descriptor names that start with E_, + followed by an underscore-delimited list of the nested messages + that contain it (if any) followed by the CamelCased name of the + extension field itself. HasExtension, ClearExtension, GetExtension + and SetExtension are functions for manipulating extensions. + - Oneof field sets are given a single field in their message, + with distinguished wrapper types for each possible field value. + - Marshal and Unmarshal are functions to encode and decode the wire format. + +When the .proto file specifies `syntax="proto3"`, there are some differences: + + - Non-repeated fields of non-message type are values instead of pointers. + - Enum types do not get an Enum method. + +The simplest way to describe this is to see an example. +Given file test.proto, containing + + package example; + + enum FOO { X = 17; } + + message Test { + required string label = 1; + optional int32 type = 2 [default=77]; + repeated int64 reps = 3; + optional group OptionalGroup = 4 { + required string RequiredField = 5; + } + oneof union { + int32 number = 6; + string name = 7; + } + } + +The resulting file, test.pb.go, is: + + package example + + import proto "github.com/golang/protobuf/proto" + import math "math" + + type FOO int32 + const ( + FOO_X FOO = 17 + ) + var FOO_name = map[int32]string{ + 17: "X", + } + var FOO_value = map[string]int32{ + "X": 17, + } + + func (x FOO) Enum() *FOO { + p := new(FOO) + *p = x + return p + } + func (x FOO) String() string { + return proto.EnumName(FOO_name, int32(x)) + } + func (x *FOO) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FOO_value, data) + if err != nil { + return err + } + *x = FOO(value) + return nil + } + + type Test struct { + Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"` + Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"` + Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"` + Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"` + // Types that are valid to be assigned to Union: + // *Test_Number + // *Test_Name + Union isTest_Union `protobuf_oneof:"union"` + XXX_unrecognized []byte `json:"-"` + } + func (m *Test) Reset() { *m = Test{} } + func (m *Test) String() string { return proto.CompactTextString(m) } + func (*Test) ProtoMessage() {} + + type isTest_Union interface { + isTest_Union() + } + + type Test_Number struct { + Number int32 `protobuf:"varint,6,opt,name=number"` + } + type Test_Name struct { + Name string `protobuf:"bytes,7,opt,name=name"` + } + + func (*Test_Number) isTest_Union() {} + func (*Test_Name) isTest_Union() {} + + func (m *Test) GetUnion() isTest_Union { + if m != nil { + return m.Union + } + return nil + } + const Default_Test_Type int32 = 77 + + func (m *Test) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" + } + + func (m *Test) GetType() int32 { + if m != nil && m.Type != nil { + return *m.Type + } + return Default_Test_Type + } + + func (m *Test) GetOptionalgroup() *Test_OptionalGroup { + if m != nil { + return m.Optionalgroup + } + return nil + } + + type Test_OptionalGroup struct { + RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"` + } + func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} } + func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) } + + func (m *Test_OptionalGroup) GetRequiredField() string { + if m != nil && m.RequiredField != nil { + return *m.RequiredField + } + return "" + } + + func (m *Test) GetNumber() int32 { + if x, ok := m.GetUnion().(*Test_Number); ok { + return x.Number + } + return 0 + } + + func (m *Test) GetName() string { + if x, ok := m.GetUnion().(*Test_Name); ok { + return x.Name + } + return "" + } + + func init() { + proto.RegisterEnum("example.FOO", FOO_name, FOO_value) + } + +To create and play with a Test object: + + package main + + import ( + "log" + + "github.com/golang/protobuf/proto" + pb "./example.pb" + ) + + func main() { + test := &pb.Test{ + Label: proto.String("hello"), + Type: proto.Int32(17), + Reps: []int64{1, 2, 3}, + Optionalgroup: &pb.Test_OptionalGroup{ + RequiredField: proto.String("good bye"), + }, + Union: &pb.Test_Name{"fred"}, + } + data, err := proto.Marshal(test) + if err != nil { + log.Fatal("marshaling error: ", err) + } + newTest := &pb.Test{} + err = proto.Unmarshal(data, newTest) + if err != nil { + log.Fatal("unmarshaling error: ", err) + } + // Now test and newTest contain the same data. + if test.GetLabel() != newTest.GetLabel() { + log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel()) + } + // Use a type switch to determine which oneof was set. + switch u := test.Union.(type) { + case *pb.Test_Number: // u.Number contains the number. + case *pb.Test_Name: // u.Name contains the string. + } + // etc. + } +*/ +package proto + +import ( + "encoding/json" + "fmt" + "log" + "reflect" + "sort" + "strconv" + "sync" +) + +// RequiredNotSetError is an error type returned by either Marshal or Unmarshal. +// Marshal reports this when a required field is not initialized. +// Unmarshal reports this when a required field is missing from the wire data. +type RequiredNotSetError struct{ field string } + +func (e *RequiredNotSetError) Error() string { + if e.field == "" { + return fmt.Sprintf("proto: required field not set") + } + return fmt.Sprintf("proto: required field %q not set", e.field) +} +func (e *RequiredNotSetError) RequiredNotSet() bool { + return true +} + +type invalidUTF8Error struct{ field string } + +func (e *invalidUTF8Error) Error() string { + if e.field == "" { + return "proto: invalid UTF-8 detected" + } + return fmt.Sprintf("proto: field %q contains invalid UTF-8", e.field) +} +func (e *invalidUTF8Error) InvalidUTF8() bool { + return true +} + +// errInvalidUTF8 is a sentinel error to identify fields with invalid UTF-8. +// This error should not be exposed to the external API as such errors should +// be recreated with the field information. +var errInvalidUTF8 = &invalidUTF8Error{} + +// isNonFatal reports whether the error is either a RequiredNotSet error +// or a InvalidUTF8 error. +func isNonFatal(err error) bool { + if re, ok := err.(interface{ RequiredNotSet() bool }); ok && re.RequiredNotSet() { + return true + } + if re, ok := err.(interface{ InvalidUTF8() bool }); ok && re.InvalidUTF8() { + return true + } + return false +} + +type nonFatal struct{ E error } + +// Merge merges err into nf and reports whether it was successful. +// Otherwise it returns false for any fatal non-nil errors. +func (nf *nonFatal) Merge(err error) (ok bool) { + if err == nil { + return true // not an error + } + if !isNonFatal(err) { + return false // fatal error + } + if nf.E == nil { + nf.E = err // store first instance of non-fatal error + } + return true +} + +// Message is implemented by generated protocol buffer messages. +type Message interface { + Reset() + String() string + ProtoMessage() +} + +// A Buffer is a buffer manager for marshaling and unmarshaling +// protocol buffers. It may be reused between invocations to +// reduce memory usage. It is not necessary to use a Buffer; +// the global functions Marshal and Unmarshal create a +// temporary Buffer and are fine for most applications. +type Buffer struct { + buf []byte // encode/decode byte stream + index int // read point + + deterministic bool +} + +// NewBuffer allocates a new Buffer and initializes its internal data to +// the contents of the argument slice. +func NewBuffer(e []byte) *Buffer { + return &Buffer{buf: e} +} + +// Reset resets the Buffer, ready for marshaling a new protocol buffer. +func (p *Buffer) Reset() { + p.buf = p.buf[0:0] // for reading/writing + p.index = 0 // for reading +} + +// SetBuf replaces the internal buffer with the slice, +// ready for unmarshaling the contents of the slice. +func (p *Buffer) SetBuf(s []byte) { + p.buf = s + p.index = 0 +} + +// 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. + */ + +// Bool is a helper routine that allocates a new bool value +// to store v and returns a pointer to it. +func Bool(v bool) *bool { + return &v +} + +// Int32 is a helper routine that allocates a new int32 value +// to store v and returns a pointer to it. +func Int32(v int32) *int32 { + return &v +} + +// Int is a helper routine that allocates a new int32 value +// to store v and returns a pointer to it, but unlike Int32 +// its argument value is an int. +func Int(v int) *int32 { + p := new(int32) + *p = int32(v) + return p +} + +// Int64 is a helper routine that allocates a new int64 value +// to store v and returns a pointer to it. +func Int64(v int64) *int64 { + return &v +} + +// Float32 is a helper routine that allocates a new float32 value +// to store v and returns a pointer to it. +func Float32(v float32) *float32 { + return &v +} + +// Float64 is a helper routine that allocates a new float64 value +// to store v and returns a pointer to it. +func Float64(v float64) *float64 { + return &v +} + +// Uint32 is a helper routine that allocates a new uint32 value +// to store v and returns a pointer to it. +func Uint32(v uint32) *uint32 { + return &v +} + +// Uint64 is a helper routine that allocates a new uint64 value +// to store v and returns a pointer to it. +func Uint64(v uint64) *uint64 { + return &v +} + +// String is a helper routine that allocates a new string value +// to store v and returns a pointer to it. +func String(v string) *string { + return &v +} + +// EnumName is a helper function to simplify printing protocol buffer enums +// by name. Given an enum map and a value, it returns a useful string. +func EnumName(m map[int32]string, v int32) string { + s, ok := m[v] + if ok { + return s + } + return strconv.Itoa(int(v)) +} + +// UnmarshalJSONEnum is a helper function to simplify recovering enum int values +// from their JSON-encoded representation. Given a map from the enum's symbolic +// names to its int values, and a byte buffer containing the JSON-encoded +// value, it returns an int32 that can be cast to the enum type by the caller. +// +// The function can deal with both JSON representations, numeric and symbolic. +func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) { + if data[0] == '"' { + // New style: enums are strings. + var repr string + if err := json.Unmarshal(data, &repr); err != nil { + return -1, err + } + val, ok := m[repr] + if !ok { + return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr) + } + return val, nil + } + // Old style: enums are ints. + var val int32 + if err := json.Unmarshal(data, &val); err != nil { + return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName) + } + return val, nil +} + +// DebugPrint dumps the encoded data in b in a debugging format with a header +// including the string s. Used in testing but made available for general debugging. +func (p *Buffer) DebugPrint(s string, b []byte) { + var u uint64 + + obuf := p.buf + index := p.index + p.buf = b + p.index = 0 + depth := 0 + + fmt.Printf("\n--- %s ---\n", s) + +out: + for { + for i := 0; i < depth; i++ { + fmt.Print(" ") + } + + index := p.index + if index == len(p.buf) { + break + } + + op, err := p.DecodeVarint() + if err != nil { + fmt.Printf("%3d: fetching op err %v\n", index, err) + break out + } + tag := op >> 3 + wire := op & 7 + + switch wire { + default: + fmt.Printf("%3d: t=%3d unknown wire=%d\n", + index, tag, wire) + break out + + case WireBytes: + var r []byte + + r, err = p.DecodeRawBytes(false) + if err != nil { + break out + } + fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r)) + if len(r) <= 6 { + for i := 0; i < len(r); i++ { + fmt.Printf(" %.2x", r[i]) + } + } else { + for i := 0; i < 3; i++ { + fmt.Printf(" %.2x", r[i]) + } + fmt.Printf(" ..") + for i := len(r) - 3; i < len(r); i++ { + fmt.Printf(" %.2x", r[i]) + } + } + fmt.Printf("\n") + + case WireFixed32: + u, err = p.DecodeFixed32() + if err != nil { + fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u) + + case WireFixed64: + u, err = p.DecodeFixed64() + if err != nil { + fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u) + + case WireVarint: + u, err = p.DecodeVarint() + if err != nil { + fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u) + + case WireStartGroup: + fmt.Printf("%3d: t=%3d start\n", index, tag) + depth++ + + case WireEndGroup: + depth-- + fmt.Printf("%3d: t=%3d end\n", index, tag) + } + } + + if depth != 0 { + fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth) + } + fmt.Printf("\n") + + p.buf = obuf + p.index = index +} + +// SetDefaults sets unset protocol buffer fields to their default values. +// It only modifies fields that are both unset and have defined defaults. +// It recursively sets default values in any non-nil sub-messages. +func SetDefaults(pb Message) { + setDefaults(reflect.ValueOf(pb), true, false) +} + +// v is a pointer to a struct. +func setDefaults(v reflect.Value, recur, zeros bool) { + v = v.Elem() + + defaultMu.RLock() + dm, ok := defaults[v.Type()] + defaultMu.RUnlock() + if !ok { + dm = buildDefaultMessage(v.Type()) + defaultMu.Lock() + defaults[v.Type()] = dm + defaultMu.Unlock() + } + + for _, sf := range dm.scalars { + f := v.Field(sf.index) + if !f.IsNil() { + // field already set + continue + } + dv := sf.value + if dv == nil && !zeros { + // no explicit default, and don't want to set zeros + continue + } + fptr := f.Addr().Interface() // **T + // TODO: Consider batching the allocations we do here. + switch sf.kind { + case reflect.Bool: + b := new(bool) + if dv != nil { + *b = dv.(bool) + } + *(fptr.(**bool)) = b + case reflect.Float32: + f := new(float32) + if dv != nil { + *f = dv.(float32) + } + *(fptr.(**float32)) = f + case reflect.Float64: + f := new(float64) + if dv != nil { + *f = dv.(float64) + } + *(fptr.(**float64)) = f + case reflect.Int32: + // might be an enum + if ft := f.Type(); ft != int32PtrType { + // enum + f.Set(reflect.New(ft.Elem())) + if dv != nil { + f.Elem().SetInt(int64(dv.(int32))) + } + } else { + // int32 field + i := new(int32) + if dv != nil { + *i = dv.(int32) + } + *(fptr.(**int32)) = i + } + case reflect.Int64: + i := new(int64) + if dv != nil { + *i = dv.(int64) + } + *(fptr.(**int64)) = i + case reflect.String: + s := new(string) + if dv != nil { + *s = dv.(string) + } + *(fptr.(**string)) = s + case reflect.Uint8: + // exceptional case: []byte + var b []byte + if dv != nil { + db := dv.([]byte) + b = make([]byte, len(db)) + copy(b, db) + } else { + b = []byte{} + } + *(fptr.(*[]byte)) = b + case reflect.Uint32: + u := new(uint32) + if dv != nil { + *u = dv.(uint32) + } + *(fptr.(**uint32)) = u + case reflect.Uint64: + u := new(uint64) + if dv != nil { + *u = dv.(uint64) + } + *(fptr.(**uint64)) = u + default: + log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind) + } + } + + for _, ni := range dm.nested { + f := v.Field(ni) + // f is *T or []*T or map[T]*T + switch f.Kind() { + case reflect.Ptr: + if f.IsNil() { + continue + } + setDefaults(f, recur, zeros) + + case reflect.Slice: + for i := 0; i < f.Len(); i++ { + e := f.Index(i) + if e.IsNil() { + continue + } + setDefaults(e, recur, zeros) + } + + case reflect.Map: + for _, k := range f.MapKeys() { + e := f.MapIndex(k) + if e.IsNil() { + continue + } + setDefaults(e, recur, zeros) + } + } + } +} + +var ( + // defaults maps a protocol buffer struct type to a slice of the fields, + // with its scalar fields set to their proto-declared non-zero default values. + defaultMu sync.RWMutex + defaults = make(map[reflect.Type]defaultMessage) + + int32PtrType = reflect.TypeOf((*int32)(nil)) +) + +// defaultMessage represents information about the default values of a message. +type defaultMessage struct { + scalars []scalarField + nested []int // struct field index of nested messages +} + +type scalarField struct { + index int // struct field index + kind reflect.Kind // element type (the T in *T or []T) + value interface{} // the proto-declared default value, or nil +} + +// t is a struct type. +func buildDefaultMessage(t reflect.Type) (dm defaultMessage) { + sprop := GetProperties(t) + for _, prop := range sprop.Prop { + fi, ok := sprop.decoderTags.get(prop.Tag) + if !ok { + // XXX_unrecognized + continue + } + ft := t.Field(fi).Type + + sf, nested, err := fieldDefault(ft, prop) + switch { + case err != nil: + log.Print(err) + case nested: + dm.nested = append(dm.nested, fi) + case sf != nil: + sf.index = fi + dm.scalars = append(dm.scalars, *sf) + } + } + + return dm +} + +// fieldDefault returns the scalarField for field type ft. +// sf will be nil if the field can not have a default. +// nestedMessage will be true if this is a nested message. +// Note that sf.index is not set on return. +func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) { + var canHaveDefault bool + switch ft.Kind() { + case reflect.Ptr: + if ft.Elem().Kind() == reflect.Struct { + nestedMessage = true + } else { + canHaveDefault = true // proto2 scalar field + } + + case reflect.Slice: + switch ft.Elem().Kind() { + case reflect.Ptr: + nestedMessage = true // repeated message + case reflect.Uint8: + canHaveDefault = true // bytes field + } + + case reflect.Map: + if ft.Elem().Kind() == reflect.Ptr { + nestedMessage = true // map with message values + } + } + + if !canHaveDefault { + if nestedMessage { + return nil, true, nil + } + return nil, false, nil + } + + // We now know that ft is a pointer or slice. + sf = &scalarField{kind: ft.Elem().Kind()} + + // scalar fields without defaults + if !prop.HasDefault { + return sf, false, nil + } + + // a scalar field: either *T or []byte + switch ft.Elem().Kind() { + case reflect.Bool: + x, err := strconv.ParseBool(prop.Default) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err) + } + sf.value = x + case reflect.Float32: + x, err := strconv.ParseFloat(prop.Default, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err) + } + sf.value = float32(x) + case reflect.Float64: + x, err := strconv.ParseFloat(prop.Default, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err) + } + sf.value = x + case reflect.Int32: + x, err := strconv.ParseInt(prop.Default, 10, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err) + } + sf.value = int32(x) + case reflect.Int64: + x, err := strconv.ParseInt(prop.Default, 10, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err) + } + sf.value = x + case reflect.String: + sf.value = prop.Default + case reflect.Uint8: + // []byte (not *uint8) + sf.value = []byte(prop.Default) + case reflect.Uint32: + x, err := strconv.ParseUint(prop.Default, 10, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err) + } + sf.value = uint32(x) + case reflect.Uint64: + x, err := strconv.ParseUint(prop.Default, 10, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err) + } + sf.value = x + default: + return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind()) + } + + 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. +func mapKeys(vs []reflect.Value) sort.Interface { + s := mapKeySorter{vs: vs} + + // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps. + if len(vs) == 0 { + return s + } + switch vs[0].Kind() { + case reflect.Int32, reflect.Int64: + 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 +} + +type mapKeySorter struct { + vs []reflect.Value + less func(a, b reflect.Value) bool +} + +func (s mapKeySorter) Len() int { return len(s.vs) } +func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] } +func (s mapKeySorter) Less(i, j int) bool { + return s.less(s.vs[i], s.vs[j]) +} + +// isProto3Zero reports whether v is a zero proto3 value. +func isProto3Zero(v reflect.Value) bool { + switch v.Kind() { + case reflect.Bool: + return !v.Bool() + case reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint32, reflect.Uint64: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.String: + return v.String() == "" + } + return false +} + +const ( + // ProtoPackageIsVersion3 is referenced from generated protocol buffer files + // to assert that that code is compatible with this version of the proto package. + ProtoPackageIsVersion3 = true + + // ProtoPackageIsVersion2 is referenced from generated protocol buffer files + // to assert that that code is compatible with this version of the proto package. + ProtoPackageIsVersion2 = true + + // ProtoPackageIsVersion1 is referenced from generated protocol buffer files + // to assert that that code is compatible with this version of the proto package. + ProtoPackageIsVersion1 = 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 +} diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/message_set.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/message_set.go new file mode 100644 index 0000000..f48a756 --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/message_set.go @@ -0,0 +1,181 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Support for message sets. + */ + +import ( + "errors" +) + +// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID. +// A message type ID is required for storing a protocol buffer in a message set. +var errNoMessageTypeID = errors.New("proto does not have a message type ID") + +// The first two types (_MessageSet_Item and messageSet) +// model what the protocol compiler produces for the following protocol message: +// message MessageSet { +// repeated group Item = 1 { +// required int32 type_id = 2; +// required string message = 3; +// }; +// } +// That is the MessageSet wire format. We can't use a proto to generate these +// because that would introduce a circular dependency between it and this package. + +type _MessageSet_Item struct { + TypeId *int32 `protobuf:"varint,2,req,name=type_id"` + Message []byte `protobuf:"bytes,3,req,name=message"` +} + +type messageSet struct { + Item []*_MessageSet_Item `protobuf:"group,1,rep"` + XXX_unrecognized []byte + // TODO: caching? +} + +// Make sure messageSet is a Message. +var _ Message = (*messageSet)(nil) + +// messageTypeIder is an interface satisfied by a protocol buffer type +// that may be stored in a MessageSet. +type messageTypeIder interface { + MessageTypeId() int32 +} + +func (ms *messageSet) find(pb Message) *_MessageSet_Item { + mti, ok := pb.(messageTypeIder) + if !ok { + return nil + } + id := mti.MessageTypeId() + for _, item := range ms.Item { + if *item.TypeId == id { + return item + } + } + return nil +} + +func (ms *messageSet) Has(pb Message) bool { + return ms.find(pb) != nil +} + +func (ms *messageSet) Unmarshal(pb Message) error { + if item := ms.find(pb); item != nil { + return Unmarshal(item.Message, pb) + } + if _, ok := pb.(messageTypeIder); !ok { + return errNoMessageTypeID + } + return nil // TODO: return error instead? +} + +func (ms *messageSet) Marshal(pb Message) error { + msg, err := Marshal(pb) + if err != nil { + return err + } + if item := ms.find(pb); item != nil { + // reuse existing item + item.Message = msg + return nil + } + + mti, ok := pb.(messageTypeIder) + if !ok { + return errNoMessageTypeID + } + + mtid := mti.MessageTypeId() + ms.Item = append(ms.Item, &_MessageSet_Item{ + TypeId: &mtid, + Message: msg, + }) + return nil +} + +func (ms *messageSet) Reset() { *ms = messageSet{} } +func (ms *messageSet) String() string { return CompactTextString(ms) } +func (*messageSet) ProtoMessage() {} + +// Support for the message_set_wire_format message option. + +func skipVarint(buf []byte) []byte { + i := 0 + for ; buf[i]&0x80 != 0; i++ { + } + return buf[i+1:] +} + +// unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. +// 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) { + case *XXX_InternalExtensions: + m = exts.extensionsWrite() + case map[int32]Extension: + m = exts + default: + return errors.New("proto: not an extension map") + } + + ms := new(messageSet) + if err := Unmarshal(buf, ms); err != nil { + return err + } + for _, item := range ms.Item { + id := *item.TypeId + msg := item.Message + + // Restore wire type and field number varint, plus length varint. + // Be careful to preserve duplicate items. + b := EncodeVarint(uint64(id)<<3 | WireBytes) + if ext, ok := m[id]; ok { + // Existing data; rip off the tag and length varint + // so we join the new data correctly. + // We can assume that ext.enc is set because we are unmarshaling. + o := ext.enc[len(b):] // skip wire type and field number + _, n := DecodeVarint(o) // calculate length of length varint + o = o[n:] // skip length varint + msg = append(o, msg...) // join old data and new data + } + b = append(b, EncodeVarint(uint64(len(msg)))...) + b = append(b, msg...) + + m[id] = Extension{enc: b} + } + return nil +} diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/pointer_reflect.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/pointer_reflect.go new file mode 100644 index 0000000..94fa919 --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/pointer_reflect.go @@ -0,0 +1,360 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 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. + +// +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 + +import ( + "reflect" + "sync" +) + +const unsafeAllowed = false + +// 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 + +// toField returns a field equivalent to the given reflect field. +func toField(f *reflect.StructField) field { + return f.Index +} + +// 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 } + +// 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 +} + +// 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)} +} + +// toAddrPointer converts an interface to a pointer that points to +// the interface data. +func toAddrPointer(i *interface{}, isptr, deref bool) pointer { + v := reflect.ValueOf(*i) + u := reflect.New(v.Type()) + u.Elem().Set(v) + if deref { + u = u.Elem() + } + return pointer{v: u} +} + +// 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() +} + +// 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 { + s.SetLen(n + 1) + } else { + s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem()))) + } + 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())) +} + +// 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) + } + // 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 +} + +// 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 + } + // 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)) + } + p.v.Elem().Set(slice) +} +func (p pointer) appendInt32Slice(v int32) { + grow(p.v.Elem()).SetInt(int64(v)) +} + +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) +} + +// 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 +} + +// 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 + } + s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v)) + for _, p := range v { + s = reflect.Append(s, p.v) + } + p.v.Elem().Set(s) +} + +// 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 pointer) asPointerTo(t reflect.Type) reflect.Value { + // TODO: check that p.v.Type().Elem() == t? + return p.v +} + +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 +} + +var atomicLock sync.Mutex diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go new file mode 100644 index 0000000..dbfffe0 --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go @@ -0,0 +1,313 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 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. + +// +build !purego,!appengine,!js + +// This file contains the implementation of the proto field accesses using package unsafe. + +package proto + +import ( + "reflect" + "sync/atomic" + "unsafe" +) + +const unsafeAllowed = true + +// 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 + +// toField returns a field equivalent to the given reflect field. +func toField(f *reflect.StructField) field { + return field(f.Offset) +} + +// 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 != invalidField +} + +// 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 +} + +// 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]} +} + +// toAddrPointer converts an interface to a pointer that points to +// the interface data. +func toAddrPointer(i *interface{}, isptr, deref bool) (p 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. + p = pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)} + } else { + // The interface is not of pointer type. The data word is the pointer + // to the data. + p = pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} + } + if deref { + p.p = *(*unsafe.Pointer)(p.p) + } + 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())} +} + +// 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))} +} + +func (p pointer) isNil() bool { + return p.p == nil +} + +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) +} + +// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist. +/* + func (p pointer) toInt32Ptr() **int32 { + return (**int32)(p.p) + } + 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 +} + +// 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) +} + +// 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 +} + +// 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) +} + +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) +} + +// 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) +} + +// 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 +} + +// 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)) +} diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/properties.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/properties.go new file mode 100644 index 0000000..79668ff --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/properties.go @@ -0,0 +1,545 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +/* + * Routines for encoding data into the wire format for protocol buffers. + */ + +import ( + "fmt" + "log" + "os" + "reflect" + "sort" + "strconv" + "strings" + "sync" +) + +const debug bool = false + +// Constants that identify the encoding of a value on the wire. +const ( + WireVarint = 0 + WireFixed64 = 1 + WireBytes = 2 + WireStartGroup = 3 + WireEndGroup = 4 + WireFixed32 = 5 +) + +// 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. +type tagMap struct { + fastTags []int + slowTags map[int]int +} + +// tagMapFastLimit is the upper bound on the tag number that will be stored in +// the tagMap slice rather than its map. +const tagMapFastLimit = 1024 + +func (p *tagMap) get(t int) (int, bool) { + if t > 0 && t < tagMapFastLimit { + if t >= len(p.fastTags) { + return 0, false + } + fi := p.fastTags[t] + return fi, fi >= 0 + } + fi, ok := p.slowTags[t] + return fi, ok +} + +func (p *tagMap) put(t int, fi int) { + if t > 0 && t < tagMapFastLimit { + for len(p.fastTags) < t+1 { + p.fastTags = append(p.fastTags, -1) + } + p.fastTags[t] = fi + return + } + if p.slowTags == nil { + p.slowTags = make(map[int]int) + } + p.slowTags[t] = fi +} + +// StructProperties represents properties for all the fields of a struct. +// decoderTags and decoderOrigNames should only be used by the decoder. +type StructProperties struct { + Prop []*Properties // properties for each field + reqCount int // required count + 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 + + // OneofTypes contains information about the oneof fields in this message. + // It is keyed by the original name of a field. + OneofTypes map[string]*OneofProperties +} + +// OneofProperties represents information about a specific field in a oneof. +type OneofProperties struct { + Type reflect.Type // pointer to generated struct type for this oneof field + Field int // struct field number of the containing oneof in the message + Prop *Properties +} + +// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec. +// See encode.go, (*Buffer).enc_struct. + +func (sp *StructProperties) Len() int { return len(sp.order) } +func (sp *StructProperties) Less(i, j int) bool { + return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag +} +func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] } + +// Properties represents the protocol-specific behavior of a single struct field. +type Properties struct { + Name string // name of the field, for error messages + OrigName string // original name before protocol compiler (always set) + JSONName string // name to use for JSON; determined by protoc + Wire string + WireType int + Tag int + Required bool + Optional bool + Repeated bool + Packed bool // relevant for repeated primitives only + Enum string // set for enum types only + proto3 bool // whether this is known to be a proto3 field + oneof bool // whether this is a oneof field + + Default string // default value + HasDefault bool // whether an explicit default was provided + + stype reflect.Type // set for struct types only + sprop *StructProperties // set for struct types only + + mtype reflect.Type // set for map types only + MapKeyProp *Properties // set for map types only + MapValProp *Properties // set for map types only +} + +// String formats the properties in the protobuf struct field tag style. +func (p *Properties) String() string { + s := p.Wire + s += "," + s += strconv.Itoa(p.Tag) + if p.Required { + s += ",req" + } + if p.Optional { + s += ",opt" + } + if p.Repeated { + s += ",rep" + } + if p.Packed { + s += ",packed" + } + s += ",name=" + p.OrigName + if p.JSONName != p.OrigName { + s += ",json=" + p.JSONName + } + if p.proto3 { + s += ",proto3" + } + if p.oneof { + s += ",oneof" + } + if len(p.Enum) > 0 { + s += ",enum=" + p.Enum + } + if p.HasDefault { + s += ",def=" + p.Default + } + return s +} + +// Parse populates p by parsing a string in the protobuf struct field tag style. +func (p *Properties) Parse(s string) { + // "bytes,49,opt,name=foo,def=hello!" + fields := strings.Split(s, ",") // breaks def=, but handled below. + if len(fields) < 2 { + fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s) + return + } + + p.Wire = fields[0] + switch p.Wire { + case "varint": + p.WireType = WireVarint + case "fixed32": + p.WireType = WireFixed32 + case "fixed64": + p.WireType = WireFixed64 + case "zigzag32": + p.WireType = WireVarint + case "zigzag64": + p.WireType = WireVarint + case "bytes", "group": + p.WireType = WireBytes + // no numeric converter for non-numeric types + default: + fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s) + return + } + + var err error + p.Tag, err = strconv.Atoi(fields[1]) + if err != nil { + return + } + +outer: + for i := 2; i < len(fields); i++ { + f := fields[i] + switch { + case f == "req": + p.Required = true + case f == "opt": + p.Optional = true + case f == "rep": + p.Repeated = true + case f == "packed": + p.Packed = true + case strings.HasPrefix(f, "name="): + p.OrigName = f[5:] + case strings.HasPrefix(f, "json="): + p.JSONName = f[5:] + case strings.HasPrefix(f, "enum="): + p.Enum = f[5:] + case f == "proto3": + p.proto3 = true + case f == "oneof": + p.oneof = true + case strings.HasPrefix(f, "def="): + p.HasDefault = true + p.Default = f[4:] // rest of string + if i+1 < len(fields) { + // Commas aren't escaped, and def is always last. + p.Default += "," + strings.Join(fields[i+1:], ",") + break outer + } + } + } +} + +var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem() + +// setFieldProps initializes the field properties for submessages and maps. +func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) { + switch t1 := typ; t1.Kind() { + case reflect.Ptr: + if t1.Elem().Kind() == reflect.Struct { + p.stype = t1.Elem() + } + + case reflect.Slice: + if t2 := t1.Elem(); t2.Kind() == reflect.Ptr && t2.Elem().Kind() == reflect.Struct { + p.stype = t2.Elem() + } + + case reflect.Map: + p.mtype = t1 + p.MapKeyProp = &Properties{} + p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) + p.MapValProp = &Properties{} + vtype := p.mtype.Elem() + if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice { + // The value type is not a message (*T) or bytes ([]byte), + // so we need encoders for the pointer to this type. + vtype = reflect.PtrTo(vtype) + } + p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) + } + + if p.stype != nil { + if lockGetProp { + p.sprop = GetProperties(p.stype) + } else { + p.sprop = getPropertiesLocked(p.stype) + } + } +} + +var ( + marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() +) + +// 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) +} + +func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) { + // "bytes,49,opt,def=hello!" + p.Name = name + p.OrigName = name + if tag == "" { + return + } + p.Parse(tag) + p.setFieldProps(typ, f, lockGetProp) +} + +var ( + propertiesMu sync.RWMutex + propertiesMap = make(map[reflect.Type]*StructProperties) +) + +// GetProperties returns the list of properties for the type represented by t. +// t must represent a generated struct type of a protocol message. +func GetProperties(t reflect.Type) *StructProperties { + if t.Kind() != reflect.Struct { + panic("proto: type must have kind struct") + } + + // Most calls to GetProperties in a long-running program will be + // retrieving details for types we have seen before. + propertiesMu.RLock() + sprop, ok := propertiesMap[t] + propertiesMu.RUnlock() + if ok { + return sprop + } + + propertiesMu.Lock() + sprop = getPropertiesLocked(t) + propertiesMu.Unlock() + return sprop +} + +type ( + oneofFuncsIface interface { + XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) + } + oneofWrappersIface interface { + XXX_OneofWrappers() []interface{} + } +) + +// getPropertiesLocked requires that propertiesMu is held. +func getPropertiesLocked(t reflect.Type) *StructProperties { + if prop, ok := propertiesMap[t]; ok { + return prop + } + + prop := new(StructProperties) + // in case of recursive protos, fill this in now. + propertiesMap[t] = prop + + // build properties + prop.Prop = make([]*Properties, t.NumField()) + prop.order = make([]int, t.NumField()) + + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + p := new(Properties) + name := f.Name + p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false) + + oneof := f.Tag.Get("protobuf_oneof") // special case + if oneof != "" { + // Oneof fields don't use the traditional protobuf tag. + p.OrigName = oneof + } + prop.Prop[i] = p + prop.order[i] = i + if debug { + print(i, " ", f.Name, " ", t.String(), " ") + if p.Tag > 0 { + print(p.String()) + } + print("\n") + } + } + + // Re-order prop.order. + sort.Sort(prop) + + var oots []interface{} + switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) { + case oneofFuncsIface: + _, _, _, oots = m.XXX_OneofFuncs() + case oneofWrappersIface: + oots = m.XXX_OneofWrappers() + } + if len(oots) > 0 { + // Interpret oneof metadata. + prop.OneofTypes = make(map[string]*OneofProperties) + for _, oot := range oots { + oop := &OneofProperties{ + Type: reflect.ValueOf(oot).Type(), // *T + Prop: new(Properties), + } + sft := oop.Type.Elem().Field(0) + oop.Prop.Name = sft.Name + oop.Prop.Parse(sft.Tag.Get("protobuf")) + // There will be exactly one interface field that + // this new value is assignable to. + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if f.Type.Kind() != reflect.Interface { + continue + } + if !oop.Type.AssignableTo(f.Type) { + continue + } + oop.Field = i + break + } + prop.OneofTypes[oop.Prop.OrigName] = oop + } + } + + // build required counts + // build tags + reqCount := 0 + prop.decoderOrigNames = make(map[string]int) + for i, p := range prop.Prop { + if strings.HasPrefix(p.Name, "XXX_") { + // Internal fields should not appear in tags/origNames maps. + // They are handled specially when encoding and decoding. + continue + } + if p.Required { + reqCount++ + } + prop.decoderTags.put(p.Tag, i) + prop.decoderOrigNames[p.OrigName] = i + } + prop.reqCount = reqCount + + return prop +} + +// A global registry of enum types. +// The generated code will register the generated maps by calling RegisterEnum. + +var enumValueMaps = make(map[string]map[string]int32) + +// RegisterEnum is called from the generated code to install the enum descriptor +// maps into the global table to aid parsing text format protocol buffers. +func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) { + if _, ok := enumValueMaps[typeName]; ok { + panic("proto: duplicate enum registered: " + typeName) + } + enumValueMaps[typeName] = valueMap +} + +// EnumValueMap returns the mapping from names to integers of the +// enum type enumType, or a nil if not found. +func EnumValueMap(enumType string) map[string]int32 { + return enumValueMaps[enumType] +} + +// A registry of all linked message types. +// The string is a fully-qualified proto name ("pkg.Message"). +var ( + 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 := protoTypedNils[name]; ok { + // TODO: Some day, make this a panic. + log.Printf("proto: duplicate proto type registered: %s", name) + return + } + t := reflect.TypeOf(x) + 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 +} + +// MessageName returns the fully-qualified proto name for the given message type. +func MessageName(x Message) string { + type xname interface { + XXX_MessageName() string + } + if m, ok := x.(xname); ok { + return m.XXX_MessageName() + } + return revProtoTypes[reflect.TypeOf(x)] +} + +// MessageType returns the message type (pointer to struct) for a named message. +// 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 ( + protoFiles = make(map[string][]byte) // file name => fileDescriptor +) + +// RegisterFile is called from generated code and maps from the +// full file name of a .proto file to its compressed FileDescriptorProto. +func RegisterFile(filename string, fileDescriptor []byte) { + protoFiles[filename] = fileDescriptor +} + +// FileDescriptor returns the compressed FileDescriptorProto for a .proto file. +func FileDescriptor(filename string) []byte { return protoFiles[filename] } diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/table_marshal.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/table_marshal.go new file mode 100644 index 0000000..5cb11fa --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/table_marshal.go @@ -0,0 +1,2776 @@ +// 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 ( + "errors" + "fmt" + "math" + "reflect" + "sort" + "strconv" + "strings" + "sync" + "sync/atomic" + "unicode/utf8" +) + +// a sizer takes a pointer to a field and the size of its tag, computes the size of +// the encoded data. +type sizer func(pointer, int) int + +// a marshaler takes a byte slice, a pointer to a field, and its tag (in wire format), +// marshals the field to the end of the slice, returns the slice and error (if any). +type marshaler func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) + +// marshalInfo is the information used for marshaling a message. +type marshalInfo struct { + typ reflect.Type + fields []*marshalFieldInfo + unrecognized field // offset of XXX_unrecognized + extensions field // offset of XXX_InternalExtensions + v1extensions field // offset of XXX_extensions + sizecache field // offset of XXX_sizecache + initialized int32 // 0 -- only typ is set, 1 -- fully initialized + messageset bool // uses message set wire format + hasmarshaler bool // has custom marshaler + sync.RWMutex // protect extElems map, also for initialization + extElems map[int32]*marshalElemInfo // info of extension elements +} + +// marshalFieldInfo is the information used for marshaling a field of a message. +type marshalFieldInfo struct { + field field + wiretag uint64 // tag in wire format + tagsize int // size of tag in wire format + sizer sizer + marshaler marshaler + isPointer bool + required bool // field is required + name string // name of the field, for error reporting + oneofElems map[reflect.Type]*marshalElemInfo // info of oneof elements +} + +// marshalElemInfo is the information used for marshaling an extension or oneof element. +type marshalElemInfo struct { + wiretag uint64 // tag in wire format + tagsize int // size of tag in wire format + sizer sizer + marshaler marshaler + isptr bool // elem is pointer typed, thus interface of this type is a direct interface (extension only) + deref bool // dereference the pointer before operating on it; implies isptr +} + +var ( + marshalInfoMap = map[reflect.Type]*marshalInfo{} + marshalInfoLock sync.Mutex +) + +// getMarshalInfo returns the information to marshal a given type of message. +// The info it returns may not necessarily initialized. +// t is the type of the message (NOT the pointer to it). +func getMarshalInfo(t reflect.Type) *marshalInfo { + marshalInfoLock.Lock() + u, ok := marshalInfoMap[t] + if !ok { + u = &marshalInfo{typ: t} + marshalInfoMap[t] = u + } + marshalInfoLock.Unlock() + return u +} + +// Size is the entry point from generated code, +// and should be ONLY called by generated code. +// It computes the size of encoded data of msg. +// a is a pointer to a place to store cached marshal info. +func (a *InternalMessageInfo) Size(msg Message) int { + u := getMessageMarshalInfo(msg, a) + ptr := toPointer(&msg) + if ptr.isNil() { + // We get here if msg is a typed nil ((*SomeMessage)(nil)), + // so it satisfies the interface, and msg == nil wouldn't + // catch it. We don't want crash in this case. + return 0 + } + return u.size(ptr) +} + +// Marshal is the entry point from generated code, +// and should be ONLY called by generated code. +// It marshals msg to the end of b. +// a is a pointer to a place to store cached marshal info. +func (a *InternalMessageInfo) Marshal(b []byte, msg Message, deterministic bool) ([]byte, error) { + u := getMessageMarshalInfo(msg, a) + ptr := toPointer(&msg) + if ptr.isNil() { + // We get here if msg is a typed nil ((*SomeMessage)(nil)), + // so it satisfies the interface, and msg == nil wouldn't + // catch it. We don't want crash in this case. + return b, ErrNil + } + return u.marshal(b, ptr, deterministic) +} + +func getMessageMarshalInfo(msg interface{}, a *InternalMessageInfo) *marshalInfo { + // u := a.marshal, but atomically. + // We use an atomic here to ensure memory consistency. + u := atomicLoadMarshalInfo(&a.marshal) + if u == nil { + // Get marshal information from type of message. + t := reflect.ValueOf(msg).Type() + if t.Kind() != reflect.Ptr { + panic(fmt.Sprintf("cannot handle non-pointer message type %v", t)) + } + u = getMarshalInfo(t.Elem()) + // Store it in the cache for later users. + // a.marshal = u, but atomically. + atomicStoreMarshalInfo(&a.marshal, u) + } + return u +} + +// size is the main function to compute the size of the encoded data of a message. +// ptr is the pointer to the message. +func (u *marshalInfo) size(ptr pointer) int { + if atomic.LoadInt32(&u.initialized) == 0 { + u.computeMarshalInfo() + } + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if u.hasmarshaler { + m := ptr.asPointerTo(u.typ).Interface().(Marshaler) + b, _ := m.Marshal() + return len(b) + } + + n := 0 + for _, f := range u.fields { + if f.isPointer && ptr.offset(f.field).getPointer().isNil() { + // nil pointer always marshals to nothing + continue + } + n += f.sizer(ptr.offset(f.field), f.tagsize) + } + if u.extensions.IsValid() { + e := ptr.offset(u.extensions).toExtensions() + if u.messageset { + n += u.sizeMessageSet(e) + } else { + n += u.sizeExtensions(e) + } + } + if u.v1extensions.IsValid() { + m := *ptr.offset(u.v1extensions).toOldExtensions() + n += u.sizeV1Extensions(m) + } + if u.unrecognized.IsValid() { + s := *ptr.offset(u.unrecognized).toBytes() + n += len(s) + } + // cache the result for use in marshal + if u.sizecache.IsValid() { + atomic.StoreInt32(ptr.offset(u.sizecache).toInt32(), int32(n)) + } + return n +} + +// cachedsize gets the size from cache. If there is no cache (i.e. message is not generated), +// fall back to compute the size. +func (u *marshalInfo) cachedsize(ptr pointer) int { + if u.sizecache.IsValid() { + return int(atomic.LoadInt32(ptr.offset(u.sizecache).toInt32())) + } + return u.size(ptr) +} + +// marshal is the main function to marshal a message. It takes a byte slice and appends +// the encoded data to the end of the slice, returns the slice and error (if any). +// ptr is the pointer to the message. +// If deterministic is true, map is marshaled in deterministic order. +func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte, error) { + if atomic.LoadInt32(&u.initialized) == 0 { + u.computeMarshalInfo() + } + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if u.hasmarshaler { + m := ptr.asPointerTo(u.typ).Interface().(Marshaler) + b1, err := m.Marshal() + b = append(b, b1...) + return b, err + } + + var err, errLater error + // The old marshaler encodes extensions at beginning. + if u.extensions.IsValid() { + e := ptr.offset(u.extensions).toExtensions() + if u.messageset { + b, err = u.appendMessageSet(b, e, deterministic) + } else { + b, err = u.appendExtensions(b, e, deterministic) + } + if err != nil { + return b, err + } + } + if u.v1extensions.IsValid() { + m := *ptr.offset(u.v1extensions).toOldExtensions() + b, err = u.appendV1Extensions(b, m, deterministic) + if err != nil { + return b, err + } + } + for _, f := range u.fields { + if f.required { + if ptr.offset(f.field).getPointer().isNil() { + // Required field is not set. + // We record the error but keep going, to give a complete marshaling. + if errLater == nil { + errLater = &RequiredNotSetError{f.name} + } + continue + } + } + if f.isPointer && ptr.offset(f.field).getPointer().isNil() { + // nil pointer always marshals to nothing + continue + } + b, err = f.marshaler(b, ptr.offset(f.field), f.wiretag, deterministic) + if err != nil { + if err1, ok := err.(*RequiredNotSetError); ok { + // Required field in submessage is not set. + // We record the error but keep going, to give a complete marshaling. + if errLater == nil { + errLater = &RequiredNotSetError{f.name + "." + err1.field} + } + continue + } + if err == errRepeatedHasNil { + err = errors.New("proto: repeated field " + f.name + " has nil element") + } + if err == errInvalidUTF8 { + if errLater == nil { + fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name + errLater = &invalidUTF8Error{fullName} + } + continue + } + return b, err + } + } + if u.unrecognized.IsValid() { + s := *ptr.offset(u.unrecognized).toBytes() + b = append(b, s...) + } + return b, errLater +} + +// computeMarshalInfo initializes the marshal info. +func (u *marshalInfo) computeMarshalInfo() { + u.Lock() + defer u.Unlock() + if u.initialized != 0 { // non-atomic read is ok as it is protected by the lock + return + } + + t := u.typ + u.unrecognized = invalidField + u.extensions = invalidField + u.v1extensions = invalidField + u.sizecache = invalidField + + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + if reflect.PtrTo(t).Implements(marshalerType) { + u.hasmarshaler = true + atomic.StoreInt32(&u.initialized, 1) + return + } + + // get oneof implementers + var oneofImplementers []interface{} + switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) { + case oneofFuncsIface: + _, _, _, oneofImplementers = m.XXX_OneofFuncs() + case oneofWrappersIface: + oneofImplementers = m.XXX_OneofWrappers() + } + + n := t.NumField() + + // deal with XXX fields first + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if !strings.HasPrefix(f.Name, "XXX_") { + continue + } + switch f.Name { + case "XXX_sizecache": + u.sizecache = toField(&f) + case "XXX_unrecognized": + u.unrecognized = toField(&f) + case "XXX_InternalExtensions": + u.extensions = toField(&f) + u.messageset = f.Tag.Get("protobuf_messageset") == "1" + case "XXX_extensions": + u.v1extensions = toField(&f) + case "XXX_NoUnkeyedLiteral": + // nothing to do + default: + panic("unknown XXX field: " + f.Name) + } + n-- + } + + // normal fields + fields := make([]marshalFieldInfo, n) // batch allocation + u.fields = make([]*marshalFieldInfo, 0, n) + for i, j := 0, 0; i < t.NumField(); i++ { + f := t.Field(i) + + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + field := &fields[j] + j++ + field.name = f.Name + u.fields = append(u.fields, field) + if f.Tag.Get("protobuf_oneof") != "" { + field.computeOneofFieldInfo(&f, oneofImplementers) + continue + } + if f.Tag.Get("protobuf") == "" { + // field has no tag (not in generated message), ignore it + u.fields = u.fields[:len(u.fields)-1] + j-- + continue + } + field.computeMarshalFieldInfo(&f) + } + + // fields are marshaled in tag order on the wire. + sort.Sort(byTag(u.fields)) + + atomic.StoreInt32(&u.initialized, 1) +} + +// helper for sorting fields by tag +type byTag []*marshalFieldInfo + +func (a byTag) Len() int { return len(a) } +func (a byTag) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byTag) Less(i, j int) bool { return a[i].wiretag < a[j].wiretag } + +// getExtElemInfo returns the information to marshal an extension element. +// The info it returns is initialized. +func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo { + // get from cache first + u.RLock() + e, ok := u.extElems[desc.Field] + u.RUnlock() + if ok { + return e + } + + t := reflect.TypeOf(desc.ExtensionType) // pointer or slice to basic type or struct + tags := strings.Split(desc.Tag, ",") + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + if t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct { + t = t.Elem() + } + sizer, marshaler := typeMarshaler(t, tags, false, false) + var deref bool + if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 { + t = reflect.PtrTo(t) + deref = true + } + e = &marshalElemInfo{ + wiretag: uint64(tag)<<3 | wt, + tagsize: SizeVarint(uint64(tag) << 3), + sizer: sizer, + marshaler: marshaler, + isptr: t.Kind() == reflect.Ptr, + deref: deref, + } + + // update cache + u.Lock() + if u.extElems == nil { + u.extElems = make(map[int32]*marshalElemInfo) + } + u.extElems[desc.Field] = e + u.Unlock() + return e +} + +// computeMarshalFieldInfo fills up the information to marshal a field. +func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) { + // parse protobuf tag of the field. + // tag has format of "bytes,49,opt,name=foo,def=hello!" + tags := strings.Split(f.Tag.Get("protobuf"), ",") + if tags[0] == "" { + return + } + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + if tags[2] == "req" { + fi.required = true + } + fi.setTag(f, tag, wt) + fi.setMarshaler(f, tags) +} + +func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) { + fi.field = toField(f) + fi.wiretag = math.MaxInt32 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire. + fi.isPointer = true + fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f) + fi.oneofElems = make(map[reflect.Type]*marshalElemInfo) + + ityp := f.Type // interface type + for _, o := range oneofImplementers { + t := reflect.TypeOf(o) + if !t.Implements(ityp) { + continue + } + sf := t.Elem().Field(0) // oneof implementer is a struct with a single field + tags := strings.Split(sf.Tag.Get("protobuf"), ",") + tag, err := strconv.Atoi(tags[1]) + if err != nil { + panic("tag is not an integer") + } + wt := wiretype(tags[0]) + sizer, marshaler := typeMarshaler(sf.Type, tags, false, true) // oneof should not omit any zero value + fi.oneofElems[t.Elem()] = &marshalElemInfo{ + wiretag: uint64(tag)<<3 | wt, + tagsize: SizeVarint(uint64(tag) << 3), + sizer: sizer, + marshaler: marshaler, + } + } +} + +// wiretype returns the wire encoding of the type. +func wiretype(encoding string) uint64 { + switch encoding { + case "fixed32": + return WireFixed32 + case "fixed64": + return WireFixed64 + case "varint", "zigzag32", "zigzag64": + return WireVarint + case "bytes": + return WireBytes + case "group": + return WireStartGroup + } + panic("unknown wire type " + encoding) +} + +// setTag fills up the tag (in wire format) and its size in the info of a field. +func (fi *marshalFieldInfo) setTag(f *reflect.StructField, tag int, wt uint64) { + fi.field = toField(f) + fi.wiretag = uint64(tag)<<3 | wt + fi.tagsize = SizeVarint(uint64(tag) << 3) +} + +// setMarshaler fills up the sizer and marshaler in the info of a field. +func (fi *marshalFieldInfo) setMarshaler(f *reflect.StructField, tags []string) { + switch f.Type.Kind() { + case reflect.Map: + // map field + fi.isPointer = true + fi.sizer, fi.marshaler = makeMapMarshaler(f) + return + case reflect.Ptr, reflect.Slice: + fi.isPointer = true + } + fi.sizer, fi.marshaler = typeMarshaler(f.Type, tags, true, false) +} + +// typeMarshaler returns the sizer and marshaler of a given field. +// t is the type of the field. +// tags is the generated "protobuf" tag of the field. +// If nozero is true, zero value is not marshaled to the wire. +// If oneof is true, it is a oneof field. +func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, marshaler) { + encoding := tags[0] + + pointer := false + slice := false + if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 { + slice = true + t = t.Elem() + } + if t.Kind() == reflect.Ptr { + pointer = true + t = t.Elem() + } + + packed := false + proto3 := false + validateUTF8 := true + for i := 2; i < len(tags); i++ { + if tags[i] == "packed" { + packed = true + } + if tags[i] == "proto3" { + proto3 = true + } + } + validateUTF8 = validateUTF8 && proto3 + + switch t.Kind() { + case reflect.Bool: + if pointer { + return sizeBoolPtr, appendBoolPtr + } + if slice { + if packed { + return sizeBoolPackedSlice, appendBoolPackedSlice + } + return sizeBoolSlice, appendBoolSlice + } + if nozero { + return sizeBoolValueNoZero, appendBoolValueNoZero + } + return sizeBoolValue, appendBoolValue + case reflect.Uint32: + switch encoding { + case "fixed32": + if pointer { + return sizeFixed32Ptr, appendFixed32Ptr + } + if slice { + if packed { + return sizeFixed32PackedSlice, appendFixed32PackedSlice + } + return sizeFixed32Slice, appendFixed32Slice + } + if nozero { + return sizeFixed32ValueNoZero, appendFixed32ValueNoZero + } + return sizeFixed32Value, appendFixed32Value + case "varint": + if pointer { + return sizeVarint32Ptr, appendVarint32Ptr + } + if slice { + if packed { + return sizeVarint32PackedSlice, appendVarint32PackedSlice + } + return sizeVarint32Slice, appendVarint32Slice + } + if nozero { + return sizeVarint32ValueNoZero, appendVarint32ValueNoZero + } + return sizeVarint32Value, appendVarint32Value + } + case reflect.Int32: + switch encoding { + case "fixed32": + if pointer { + return sizeFixedS32Ptr, appendFixedS32Ptr + } + if slice { + if packed { + return sizeFixedS32PackedSlice, appendFixedS32PackedSlice + } + return sizeFixedS32Slice, appendFixedS32Slice + } + if nozero { + return sizeFixedS32ValueNoZero, appendFixedS32ValueNoZero + } + return sizeFixedS32Value, appendFixedS32Value + case "varint": + if pointer { + return sizeVarintS32Ptr, appendVarintS32Ptr + } + if slice { + if packed { + return sizeVarintS32PackedSlice, appendVarintS32PackedSlice + } + return sizeVarintS32Slice, appendVarintS32Slice + } + if nozero { + return sizeVarintS32ValueNoZero, appendVarintS32ValueNoZero + } + return sizeVarintS32Value, appendVarintS32Value + case "zigzag32": + if pointer { + return sizeZigzag32Ptr, appendZigzag32Ptr + } + if slice { + if packed { + return sizeZigzag32PackedSlice, appendZigzag32PackedSlice + } + return sizeZigzag32Slice, appendZigzag32Slice + } + if nozero { + return sizeZigzag32ValueNoZero, appendZigzag32ValueNoZero + } + return sizeZigzag32Value, appendZigzag32Value + } + case reflect.Uint64: + switch encoding { + case "fixed64": + if pointer { + return sizeFixed64Ptr, appendFixed64Ptr + } + if slice { + if packed { + return sizeFixed64PackedSlice, appendFixed64PackedSlice + } + return sizeFixed64Slice, appendFixed64Slice + } + if nozero { + return sizeFixed64ValueNoZero, appendFixed64ValueNoZero + } + return sizeFixed64Value, appendFixed64Value + case "varint": + if pointer { + return sizeVarint64Ptr, appendVarint64Ptr + } + if slice { + if packed { + return sizeVarint64PackedSlice, appendVarint64PackedSlice + } + return sizeVarint64Slice, appendVarint64Slice + } + if nozero { + return sizeVarint64ValueNoZero, appendVarint64ValueNoZero + } + return sizeVarint64Value, appendVarint64Value + } + case reflect.Int64: + switch encoding { + case "fixed64": + if pointer { + return sizeFixedS64Ptr, appendFixedS64Ptr + } + if slice { + if packed { + return sizeFixedS64PackedSlice, appendFixedS64PackedSlice + } + return sizeFixedS64Slice, appendFixedS64Slice + } + if nozero { + return sizeFixedS64ValueNoZero, appendFixedS64ValueNoZero + } + return sizeFixedS64Value, appendFixedS64Value + case "varint": + if pointer { + return sizeVarintS64Ptr, appendVarintS64Ptr + } + if slice { + if packed { + return sizeVarintS64PackedSlice, appendVarintS64PackedSlice + } + return sizeVarintS64Slice, appendVarintS64Slice + } + if nozero { + return sizeVarintS64ValueNoZero, appendVarintS64ValueNoZero + } + return sizeVarintS64Value, appendVarintS64Value + case "zigzag64": + if pointer { + return sizeZigzag64Ptr, appendZigzag64Ptr + } + if slice { + if packed { + return sizeZigzag64PackedSlice, appendZigzag64PackedSlice + } + return sizeZigzag64Slice, appendZigzag64Slice + } + if nozero { + return sizeZigzag64ValueNoZero, appendZigzag64ValueNoZero + } + return sizeZigzag64Value, appendZigzag64Value + } + case reflect.Float32: + if pointer { + return sizeFloat32Ptr, appendFloat32Ptr + } + if slice { + if packed { + return sizeFloat32PackedSlice, appendFloat32PackedSlice + } + return sizeFloat32Slice, appendFloat32Slice + } + if nozero { + return sizeFloat32ValueNoZero, appendFloat32ValueNoZero + } + return sizeFloat32Value, appendFloat32Value + case reflect.Float64: + if pointer { + return sizeFloat64Ptr, appendFloat64Ptr + } + if slice { + if packed { + return sizeFloat64PackedSlice, appendFloat64PackedSlice + } + return sizeFloat64Slice, appendFloat64Slice + } + if nozero { + return sizeFloat64ValueNoZero, appendFloat64ValueNoZero + } + return sizeFloat64Value, appendFloat64Value + case reflect.String: + if validateUTF8 { + if pointer { + return sizeStringPtr, appendUTF8StringPtr + } + if slice { + return sizeStringSlice, appendUTF8StringSlice + } + if nozero { + return sizeStringValueNoZero, appendUTF8StringValueNoZero + } + return sizeStringValue, appendUTF8StringValue + } + if pointer { + return sizeStringPtr, appendStringPtr + } + if slice { + return sizeStringSlice, appendStringSlice + } + if nozero { + return sizeStringValueNoZero, appendStringValueNoZero + } + return sizeStringValue, appendStringValue + case reflect.Slice: + if slice { + return sizeBytesSlice, appendBytesSlice + } + if oneof { + // Oneof bytes field may also have "proto3" tag. + // We want to marshal it as a oneof field. Do this + // check before the proto3 check. + return sizeBytesOneof, appendBytesOneof + } + if proto3 { + return sizeBytes3, appendBytes3 + } + return sizeBytes, appendBytes + case reflect.Struct: + switch encoding { + case "group": + if slice { + return makeGroupSliceMarshaler(getMarshalInfo(t)) + } + return makeGroupMarshaler(getMarshalInfo(t)) + case "bytes": + if slice { + return makeMessageSliceMarshaler(getMarshalInfo(t)) + } + return makeMessageMarshaler(getMarshalInfo(t)) + } + } + panic(fmt.Sprintf("unknown or mismatched type: type: %v, wire type: %v", t, encoding)) +} + +// Below are functions to size/marshal a specific type of a field. +// They are stored in the field's info, and called by function pointers. +// They have type sizer or marshaler. + +func sizeFixed32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFixed32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFixed32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFixed32Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + return (4 + tagsize) * len(s) +} +func sizeFixed32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFixedS32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFixedS32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFixedS32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFixedS32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + return (4 + tagsize) * len(s) +} +func sizeFixedS32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFloat32Value(_ pointer, tagsize int) int { + return 4 + tagsize +} +func sizeFloat32ValueNoZero(ptr pointer, tagsize int) int { + v := math.Float32bits(*ptr.toFloat32()) + if v == 0 { + return 0 + } + return 4 + tagsize +} +func sizeFloat32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toFloat32Ptr() + if p == nil { + return 0 + } + return 4 + tagsize +} +func sizeFloat32Slice(ptr pointer, tagsize int) int { + s := *ptr.toFloat32Slice() + return (4 + tagsize) * len(s) +} +func sizeFloat32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toFloat32Slice() + if len(s) == 0 { + return 0 + } + return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize +} +func sizeFixed64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFixed64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFixed64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFixed64Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + return (8 + tagsize) * len(s) +} +func sizeFixed64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeFixedS64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFixedS64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFixedS64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFixedS64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + return (8 + tagsize) * len(s) +} +func sizeFixedS64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeFloat64Value(_ pointer, tagsize int) int { + return 8 + tagsize +} +func sizeFloat64ValueNoZero(ptr pointer, tagsize int) int { + v := math.Float64bits(*ptr.toFloat64()) + if v == 0 { + return 0 + } + return 8 + tagsize +} +func sizeFloat64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toFloat64Ptr() + if p == nil { + return 0 + } + return 8 + tagsize +} +func sizeFloat64Slice(ptr pointer, tagsize int) int { + s := *ptr.toFloat64Slice() + return (8 + tagsize) * len(s) +} +func sizeFloat64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toFloat64Slice() + if len(s) == 0 { + return 0 + } + return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize +} +func sizeVarint32Value(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarint32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint32() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarint32Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint32Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarint32Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarint32PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarintS32Value(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarintS32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarintS32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarint64Value(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + return SizeVarint(v) + tagsize +} +func sizeVarint64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toUint64() + if v == 0 { + return 0 + } + return SizeVarint(v) + tagsize +} +func sizeVarint64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toUint64Ptr() + if p == nil { + return 0 + } + return SizeVarint(*p) + tagsize +} +func sizeVarint64Slice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(v) + tagsize + } + return n +} +func sizeVarint64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(v) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeVarintS64Value(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v)) + tagsize +} +func sizeVarintS64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + return SizeVarint(uint64(*p)) + tagsize +} +func sizeVarintS64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + tagsize + } + return n +} +func sizeVarintS64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeZigzag32Value(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt32() + if v == 0 { + return 0 + } + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32Ptr(ptr pointer, tagsize int) int { + p := ptr.getInt32Ptr() + if p == nil { + return 0 + } + v := *p + return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize +} +func sizeZigzag32Slice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize + } + return n +} +func sizeZigzag32PackedSlice(ptr pointer, tagsize int) int { + s := ptr.getInt32Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31)))) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeZigzag64Value(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64ValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toInt64() + if v == 0 { + return 0 + } + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64Ptr(ptr pointer, tagsize int) int { + p := *ptr.toInt64Ptr() + if p == nil { + return 0 + } + v := *p + return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize +} +func sizeZigzag64Slice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize + } + return n +} +func sizeZigzag64PackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return 0 + } + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63))) + } + return n + SizeVarint(uint64(n)) + tagsize +} +func sizeBoolValue(_ pointer, tagsize int) int { + return 1 + tagsize +} +func sizeBoolValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toBool() + if !v { + return 0 + } + return 1 + tagsize +} +func sizeBoolPtr(ptr pointer, tagsize int) int { + p := *ptr.toBoolPtr() + if p == nil { + return 0 + } + return 1 + tagsize +} +func sizeBoolSlice(ptr pointer, tagsize int) int { + s := *ptr.toBoolSlice() + return (1 + tagsize) * len(s) +} +func sizeBoolPackedSlice(ptr pointer, tagsize int) int { + s := *ptr.toBoolSlice() + if len(s) == 0 { + return 0 + } + return len(s) + SizeVarint(uint64(len(s))) + tagsize +} +func sizeStringValue(ptr pointer, tagsize int) int { + v := *ptr.toString() + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringValueNoZero(ptr pointer, tagsize int) int { + v := *ptr.toString() + if v == "" { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringPtr(ptr pointer, tagsize int) int { + p := *ptr.toStringPtr() + if p == nil { + return 0 + } + v := *p + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeStringSlice(ptr pointer, tagsize int) int { + s := *ptr.toStringSlice() + n := 0 + for _, v := range s { + n += len(v) + SizeVarint(uint64(len(v))) + tagsize + } + return n +} +func sizeBytes(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + if v == nil { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytes3(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + if len(v) == 0 { + return 0 + } + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytesOneof(ptr pointer, tagsize int) int { + v := *ptr.toBytes() + return len(v) + SizeVarint(uint64(len(v))) + tagsize +} +func sizeBytesSlice(ptr pointer, tagsize int) int { + s := *ptr.toBytesSlice() + n := 0 + for _, v := range s { + n += len(v) + SizeVarint(uint64(len(v))) + tagsize + } + return n +} + +// appendFixed32 appends an encoded fixed32 to b. +func appendFixed32(b []byte, v uint32) []byte { + b = append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24)) + return b +} + +// appendFixed64 appends an encoded fixed64 to b. +func appendFixed64(b []byte, v uint64) []byte { + b = append(b, + byte(v), + byte(v>>8), + byte(v>>16), + byte(v>>24), + byte(v>>32), + byte(v>>40), + byte(v>>48), + byte(v>>56)) + return b +} + +// appendVarint appends an encoded varint to b. +func appendVarint(b []byte, v uint64) []byte { + // TODO: make 1-byte (maybe 2-byte) case inline-able, once we + // have non-leaf inliner. + switch { + case v < 1<<7: + b = append(b, byte(v)) + case v < 1<<14: + b = append(b, + byte(v&0x7f|0x80), + byte(v>>7)) + case v < 1<<21: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte(v>>14)) + case v < 1<<28: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte(v>>21)) + case v < 1<<35: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte(v>>28)) + case v < 1<<42: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte(v>>35)) + case v < 1<<49: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte(v>>42)) + case v < 1<<56: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte(v>>49)) + case v < 1<<63: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte((v>>49)&0x7f|0x80), + byte(v>>56)) + default: + b = append(b, + byte(v&0x7f|0x80), + byte((v>>7)&0x7f|0x80), + byte((v>>14)&0x7f|0x80), + byte((v>>21)&0x7f|0x80), + byte((v>>28)&0x7f|0x80), + byte((v>>35)&0x7f|0x80), + byte((v>>42)&0x7f|0x80), + byte((v>>49)&0x7f|0x80), + byte((v>>56)&0x7f|0x80), + 1) + } + return b +} + +func appendFixed32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFixed32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFixed32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, *p) + return b, nil +} +func appendFixed32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + } + return b, nil +} +func appendFixed32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, v) + } + return b, nil +} +func appendFixedS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + return b, nil +} +func appendFixedS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + return b, nil +} +func appendFixedS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(*p)) + return b, nil +} +func appendFixedS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, uint32(v)) + } + return b, nil +} +func appendFixedS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, uint32(v)) + } + return b, nil +} +func appendFloat32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float32bits(*ptr.toFloat32()) + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFloat32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float32bits(*ptr.toFloat32()) + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, v) + return b, nil +} +func appendFloat32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toFloat32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed32(b, math.Float32bits(*p)) + return b, nil +} +func appendFloat32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed32(b, math.Float32bits(v)) + } + return b, nil +} +func appendFloat32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(4*len(s))) + for _, v := range s { + b = appendFixed32(b, math.Float32bits(v)) + } + return b, nil +} +func appendFixed64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFixed64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFixed64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, *p) + return b, nil +} +func appendFixed64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + } + return b, nil +} +func appendFixed64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, v) + } + return b, nil +} +func appendFixedS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + return b, nil +} +func appendFixedS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + return b, nil +} +func appendFixedS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(*p)) + return b, nil +} +func appendFixedS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, uint64(v)) + } + return b, nil +} +func appendFixedS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, uint64(v)) + } + return b, nil +} +func appendFloat64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float64bits(*ptr.toFloat64()) + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFloat64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := math.Float64bits(*ptr.toFloat64()) + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, v) + return b, nil +} +func appendFloat64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toFloat64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendFixed64(b, math.Float64bits(*p)) + return b, nil +} +func appendFloat64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendFixed64(b, math.Float64bits(v)) + } + return b, nil +} +func appendFloat64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toFloat64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(8*len(s))) + for _, v := range s { + b = appendFixed64(b, math.Float64bits(v)) + } + return b, nil +} +func appendVarint32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarint32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarint32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarint32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarint32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarintS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarint64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + return b, nil +} +func appendVarint64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toUint64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + return b, nil +} +func appendVarint64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toUint64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, *p) + return b, nil +} +func appendVarint64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, v) + } + return b, nil +} +func appendVarint64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toUint64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(v) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, v) + } + return b, nil +} +func appendVarintS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + return b, nil +} +func appendVarintS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(*p)) + return b, nil +} +func appendVarintS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendVarintS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v)) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v)) + } + return b, nil +} +func appendZigzag32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt32() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := ptr.getInt32Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + v := *p + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + return b, nil +} +func appendZigzag32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + } + return b, nil +} +func appendZigzag32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := ptr.getInt32Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31)))) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + } + return b, nil +} +func appendZigzag64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toInt64() + if v == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toInt64Ptr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + v := *p + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + return b, nil +} +func appendZigzag64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + } + return b, nil +} +func appendZigzag64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toInt64Slice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + // compute size + n := 0 + for _, v := range s { + n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63))) + } + b = appendVarint(b, uint64(n)) + for _, v := range s { + b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63))) + } + return b, nil +} +func appendBoolValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBool() + b = appendVarint(b, wiretag) + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + return b, nil +} +func appendBoolValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBool() + if !v { + return b, nil + } + b = appendVarint(b, wiretag) + b = append(b, 1) + return b, nil +} + +func appendBoolPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toBoolPtr() + if p == nil { + return b, nil + } + b = appendVarint(b, wiretag) + if *p { + b = append(b, 1) + } else { + b = append(b, 0) + } + return b, nil +} +func appendBoolSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBoolSlice() + for _, v := range s { + b = appendVarint(b, wiretag) + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + } + return b, nil +} +func appendBoolPackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBoolSlice() + if len(s) == 0 { + return b, nil + } + b = appendVarint(b, wiretag&^7|WireBytes) + b = appendVarint(b, uint64(len(s))) + for _, v := range s { + if v { + b = append(b, 1) + } else { + b = append(b, 0) + } + } + return b, nil +} +func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toString() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toString() + if v == "" { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + p := *ptr.toStringPtr() + if p == nil { + return b, nil + } + v := *p + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toStringSlice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + } + return b, nil +} +func appendUTF8StringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + var invalidUTF8 bool + v := *ptr.toString() + if !utf8.ValidString(v) { + invalidUTF8 = true + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + if invalidUTF8 { + return b, errInvalidUTF8 + } + return b, nil +} +func appendUTF8StringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + var invalidUTF8 bool + v := *ptr.toString() + if v == "" { + return b, nil + } + if !utf8.ValidString(v) { + invalidUTF8 = true + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + if invalidUTF8 { + return b, errInvalidUTF8 + } + return b, nil +} +func appendUTF8StringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + var invalidUTF8 bool + p := *ptr.toStringPtr() + if p == nil { + return b, nil + } + v := *p + if !utf8.ValidString(v) { + invalidUTF8 = true + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + if invalidUTF8 { + return b, errInvalidUTF8 + } + return b, nil +} +func appendUTF8StringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + var invalidUTF8 bool + s := *ptr.toStringSlice() + for _, v := range s { + if !utf8.ValidString(v) { + invalidUTF8 = true + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + } + if invalidUTF8 { + return b, errInvalidUTF8 + } + return b, nil +} +func appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + if v == nil { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytes3(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + if len(v) == 0 { + return b, nil + } + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytesOneof(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + v := *ptr.toBytes() + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + return b, nil +} +func appendBytesSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { + s := *ptr.toBytesSlice() + for _, v := range s { + b = appendVarint(b, wiretag) + b = appendVarint(b, uint64(len(v))) + b = append(b, v...) + } + return b, nil +} + +// makeGroupMarshaler returns the sizer and marshaler for a group. +// u is the marshal info of the underlying message. +func makeGroupMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + p := ptr.getPointer() + if p.isNil() { + return 0 + } + return u.size(p) + 2*tagsize + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + p := ptr.getPointer() + if p.isNil() { + return b, nil + } + var err error + b = appendVarint(b, wiretag) // start group + b, err = u.marshal(b, p, deterministic) + b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group + return b, err + } +} + +// makeGroupSliceMarshaler returns the sizer and marshaler for a group slice. +// u is the marshal info of the underlying message. +func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getPointerSlice() + n := 0 + for _, v := range s { + if v.isNil() { + continue + } + n += u.size(v) + 2*tagsize + } + return n + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + s := ptr.getPointerSlice() + var err error + var nerr nonFatal + for _, v := range s { + if v.isNil() { + return b, errRepeatedHasNil + } + b = appendVarint(b, wiretag) // start group + b, err = u.marshal(b, v, deterministic) + b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group + if !nerr.Merge(err) { + if err == ErrNil { + err = errRepeatedHasNil + } + return b, err + } + } + return b, nerr.E + } +} + +// makeMessageMarshaler returns the sizer and marshaler for a message field. +// u is the marshal info of the message. +func makeMessageMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + p := ptr.getPointer() + if p.isNil() { + return 0 + } + siz := u.size(p) + return siz + SizeVarint(uint64(siz)) + tagsize + }, + func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { + p := ptr.getPointer() + if p.isNil() { + return b, nil + } + b = appendVarint(b, wiretag) + siz := u.cachedsize(p) + b = appendVarint(b, uint64(siz)) + return u.marshal(b, p, deterministic) + } +} + +// makeMessageSliceMarshaler returns the sizer and marshaler for a message slice. +// u is the marshal info of the message. +func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) { + return func(ptr pointer, tagsize int) int { + s := ptr.getPointerSlice() + n := 0 + for _, v := range s { + if v.isNil() { + continue + } + 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.getPointerSlice() + var err error + var nerr nonFatal + for _, v := range s { + if v.isNil() { + return b, errRepeatedHasNil + } + b = appendVarint(b, wiretag) + siz := u.cachedsize(v) + b = appendVarint(b, uint64(siz)) + b, err = u.marshal(b, v, deterministic) + + if !nerr.Merge(err) { + if err == ErrNil { + err = errRepeatedHasNil + } + return b, err + } + } + return b, nerr.E + } +} + +// makeMapMarshaler returns the sizer and marshaler for a map field. +// f is the pointer to the reflect data structure of the field. +func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) { + // figure out key and value type + t := f.Type + keyType := t.Key() + valType := t.Elem() + keyTags := strings.Split(f.Tag.Get("protobuf_key"), ",") + valTags := strings.Split(f.Tag.Get("protobuf_val"), ",") + keySizer, keyMarshaler := typeMarshaler(keyType, keyTags, false, false) // don't omit zero value in map + valSizer, valMarshaler := typeMarshaler(valType, valTags, false, false) // don't omit zero value in map + keyWireTag := 1<<3 | wiretype(keyTags[0]) + valWireTag := 2<<3 | wiretype(valTags[0]) + + // We create an interface to get the addresses of the map key and value. + // If value is pointer-typed, the interface is a direct interface, the + // idata itself is the value. Otherwise, the idata is the pointer to the + // value. + // Key cannot be pointer-typed. + valIsPtr := valType.Kind() == reflect.Ptr + + // If value is a message with nested maps, calling + // valSizer in marshal may be quadratic. We should use + // cached version in marshal (but not in size). + // If value is not message type, we don't have size cache, + // but it cannot be nested either. Just use valSizer. + valCachedSizer := valSizer + if valIsPtr && valType.Elem().Kind() == reflect.Struct { + u := getMarshalInfo(valType.Elem()) + valCachedSizer = func(ptr pointer, tagsize int) int { + // Same as message sizer, but use cache. + p := ptr.getPointer() + if p.isNil() { + return 0 + } + siz := u.cachedsize(p) + return siz + SizeVarint(uint64(siz)) + tagsize + } + } + return func(ptr pointer, tagsize int) int { + m := ptr.asPointerTo(t).Elem() // the map + n := 0 + for _, k := range m.MapKeys() { + ki := k.Interface() + vi := m.MapIndex(k).Interface() + kaddr := toAddrPointer(&ki, false, false) // pointer to key + vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value + siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1) + n += siz + SizeVarint(uint64(siz)) + tagsize + } + return n + }, + func(b []byte, ptr pointer, tag uint64, deterministic bool) ([]byte, error) { + m := ptr.asPointerTo(t).Elem() // the map + var err error + keys := m.MapKeys() + if len(keys) > 1 && deterministic { + sort.Sort(mapKeys(keys)) + } + + var nerr nonFatal + for _, k := range keys { + ki := k.Interface() + vi := m.MapIndex(k).Interface() + kaddr := toAddrPointer(&ki, false, false) // pointer to key + vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value + b = appendVarint(b, tag) + siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1) + b = appendVarint(b, uint64(siz)) + b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic) + if !nerr.Merge(err) { + return b, err + } + b, err = valMarshaler(b, vaddr, valWireTag, deterministic) + if err != ErrNil && !nerr.Merge(err) { // allow nil value in map + return b, err + } + } + return b, nerr.E + } +} + +// makeOneOfMarshaler returns the sizer and marshaler for a oneof field. +// fi is the marshal info of the field. +// f is the pointer to the reflect data structure of the field. +func makeOneOfMarshaler(fi *marshalFieldInfo, f *reflect.StructField) (sizer, marshaler) { + // Oneof field is an interface. We need to get the actual data type on the fly. + t := f.Type + return func(ptr pointer, _ int) int { + p := ptr.getInterfacePointer() + if p.isNil() { + return 0 + } + v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct + telem := v.Type() + e := fi.oneofElems[telem] + return e.sizer(p, e.tagsize) + }, + func(b []byte, ptr pointer, _ uint64, deterministic bool) ([]byte, error) { + p := ptr.getInterfacePointer() + if p.isNil() { + return b, nil + } + v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct + telem := v.Type() + if telem.Field(0).Type.Kind() == reflect.Ptr && p.getPointer().isNil() { + return b, errOneofHasNil + } + e := fi.oneofElems[telem] + return e.marshaler(b, p, e.wiretag, deterministic) + } +} + +// sizeExtensions computes the size of encoded data for a XXX_InternalExtensions field. +func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int { + m, mu := ext.extensionsRead() + if m == nil { + return 0 + } + mu.Lock() + + n := 0 + 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. + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr, ei.deref) + n += ei.sizer(p, ei.tagsize) + } + mu.Unlock() + return n +} + +// appendExtensions marshals a XXX_InternalExtensions field to the end of byte slice b. +func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) { + m, mu := ext.extensionsRead() + if m == nil { + return b, nil + } + mu.Lock() + defer mu.Unlock() + + var err error + var nerr nonFatal + + // Fast-path for common cases: zero or one extensions. + // Don't bother sorting the keys. + if len(m) <= 1 { + for _, e := range m { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, 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. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr, ei.deref) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if !nerr.Merge(err) { + return b, err + } + } + return b, nerr.E + } + + // Sort the keys to provide a deterministic encoding. + // Not sure this is required, but the old code does it. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + for _, k := range keys { + e := m[int32(k)] + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, 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. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr, ei.deref) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if !nerr.Merge(err) { + return b, err + } + } + return b, nerr.E +} + +// message set format is: +// message MessageSet { +// repeated group Item = 1 { +// required int32 type_id = 2; +// required string message = 3; +// }; +// } + +// sizeMessageSet computes the size of encoded data for a XXX_InternalExtensions field +// in message set format (above). +func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int { + m, mu := ext.extensionsRead() + if m == nil { + return 0 + } + mu.Lock() + + n := 0 + for id, e := range m { + n += 2 // start group, end group. tag = 1 (size=1) + n += SizeVarint(uint64(id)) + 1 // type_id, tag = 2 (size=1) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + siz := len(msgWithLen) + n += siz + 1 // message, tag = 3 (size=1) + 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. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr, ei.deref) + n += ei.sizer(p, 1) // message, tag = 3 (size=1) + } + mu.Unlock() + return n +} + +// appendMessageSet marshals a XXX_InternalExtensions field in message set format (above) +// to the end of byte slice b. +func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) { + m, mu := ext.extensionsRead() + if m == nil { + return b, nil + } + mu.Lock() + defer mu.Unlock() + + var err error + var nerr nonFatal + + // Fast-path for common cases: zero or one extensions. + // Don't bother sorting the keys. + if len(m) <= 1 { + for id, e := range m { + b = append(b, 1<<3|WireStartGroup) + b = append(b, 2<<3|WireVarint) + b = appendVarint(b, uint64(id)) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + b = append(b, 3<<3|WireBytes) + b = append(b, msgWithLen...) + b = append(b, 1<<3|WireEndGroup) + 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. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr, ei.deref) + b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) + if !nerr.Merge(err) { + return b, err + } + b = append(b, 1<<3|WireEndGroup) + } + return b, nerr.E + } + + // Sort the keys to provide a deterministic encoding. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + for _, id := range keys { + e := m[int32(id)] + b = append(b, 1<<3|WireStartGroup) + b = append(b, 2<<3|WireVarint) + b = appendVarint(b, uint64(id)) + + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint + b = append(b, 3<<3|WireBytes) + b = append(b, msgWithLen...) + b = append(b, 1<<3|WireEndGroup) + 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. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr, ei.deref) + b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) + b = append(b, 1<<3|WireEndGroup) + if !nerr.Merge(err) { + return b, err + } + } + return b, nerr.E +} + +// sizeV1Extensions computes the size of encoded data for a V1-API extension field. +func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int { + if m == nil { + return 0 + } + + n := 0 + 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. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr, ei.deref) + n += ei.sizer(p, ei.tagsize) + } + return n +} + +// appendV1Extensions marshals a V1-API extension field to the end of byte slice b. +func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, deterministic bool) ([]byte, error) { + if m == nil { + return b, nil + } + + // Sort the keys to provide a deterministic encoding. + keys := make([]int, 0, len(m)) + for k := range m { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + var err error + var nerr nonFatal + for _, k := range keys { + e := m[int32(k)] + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + b = append(b, 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. + + ei := u.getExtElemInfo(e.desc) + v := e.value + p := toAddrPointer(&v, ei.isptr, ei.deref) + b, err = ei.marshaler(b, p, ei.wiretag, deterministic) + if !nerr.Merge(err) { + return b, err + } + } + return b, nerr.E +} + +// newMarshaler is the interface representing objects that can marshal themselves. +// +// 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 newMarshaler interface { + XXX_Size() int + XXX_Marshal(b []byte, deterministic bool) ([]byte, error) +} + +// Size returns the encoded size of a protocol buffer message. +// This is the main entry point. +func Size(pb Message) int { + if m, ok := pb.(newMarshaler); ok { + return m.XXX_Size() + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + b, _ := m.Marshal() + return len(b) + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return 0 + } + var info InternalMessageInfo + return info.Size(pb) +} + +// Marshal takes a protocol buffer message +// and encodes it into the wire format, returning the data. +// This is the main entry point. +func Marshal(pb Message) ([]byte, error) { + if m, ok := pb.(newMarshaler); ok { + siz := m.XXX_Size() + b := make([]byte, 0, siz) + return m.XXX_Marshal(b, false) + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + return m.Marshal() + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return nil, ErrNil + } + var info InternalMessageInfo + siz := info.Size(pb) + b := make([]byte, 0, siz) + return info.Marshal(b, pb, false) +} + +// Marshal takes a protocol buffer message +// and encodes it into the wire format, writing the result to the +// Buffer. +// This is an alternative entry point. It is not necessary to use +// a Buffer for most applications. +func (p *Buffer) Marshal(pb Message) error { + var err error + if m, ok := pb.(newMarshaler); ok { + siz := m.XXX_Size() + p.grow(siz) // make sure buf has enough capacity + p.buf, err = m.XXX_Marshal(p.buf, p.deterministic) + return err + } + if m, ok := pb.(Marshaler); ok { + // If the message can marshal itself, let it do it, for compatibility. + // NOTE: This is not efficient. + b, err := m.Marshal() + p.buf = append(p.buf, b...) + return err + } + // in case somehow we didn't generate the wrapper + if pb == nil { + return ErrNil + } + var info InternalMessageInfo + siz := info.Size(pb) + p.grow(siz) // make sure buf has enough capacity + p.buf, err = info.Marshal(p.buf, pb, p.deterministic) + return err +} + +// grow grows the buffer's capacity, if necessary, to guarantee space for +// another n bytes. After grow(n), at least n bytes can be written to the +// buffer without another allocation. +func (p *Buffer) grow(n int) { + need := len(p.buf) + n + if need <= cap(p.buf) { + return + } + newCap := len(p.buf) * 2 + if newCap < need { + newCap = need + } + p.buf = append(make([]byte, 0, newCap), p.buf...) +} diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/table_merge.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/table_merge.go new file mode 100644 index 0000000..5525def --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/table_merge.go @@ -0,0 +1,654 @@ +// 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: + panic(fmt.Sprintf("message field %s without pointer", tf)) + case isSlice: // E.g., []*pb.T + mi := 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)) + mi.merge(dp, sp) + } + dps = append(dps, dp) + } + if dps == nil { + dps = []pointer{} + } + dst.setPointerSlice(dps) + } + } + default: // E.g., *pb.T + mi := 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) + } + mi.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) +} diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/table_unmarshal.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/table_unmarshal.go new file mode 100644 index 0000000..acee2fc --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/table_unmarshal.go @@ -0,0 +1,2053 @@ +// 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 ( + "errors" + "fmt" + "io" + "math" + "reflect" + "strconv" + "strings" + "sync" + "sync/atomic" + "unicode/utf8" +) + +// Unmarshal is the entry point from the generated .pb.go files. +// This function is not intended to be used by non-generated code. +// This function is not subject to any compatibility guarantee. +// msg contains a pointer to a protocol buffer struct. +// b is the data to be unmarshaled into the protocol buffer. +// a is a pointer to a place to store cached unmarshal information. +func (a *InternalMessageInfo) Unmarshal(msg Message, b []byte) error { + // Load the unmarshal information for this message type. + // The atomic load ensures memory consistency. + u := atomicLoadUnmarshalInfo(&a.unmarshal) + if u == nil { + // Slow path: find unmarshal info for msg, update a with it. + u = getUnmarshalInfo(reflect.TypeOf(msg).Elem()) + atomicStoreUnmarshalInfo(&a.unmarshal, u) + } + // Then do the unmarshaling. + err := u.unmarshal(toPointer(&msg), b) + return err +} + +type unmarshalInfo struct { + typ reflect.Type // type of the protobuf struct + + // 0 = only typ field is initialized + // 1 = completely initialized + initialized int32 + lock sync.Mutex // prevents double initialization + dense []unmarshalFieldInfo // fields indexed by tag # + sparse map[uint64]unmarshalFieldInfo // fields indexed by tag # + reqFields []string // names of required fields + reqMask uint64 // 1< 0 { + // Read tag and wire type. + // Special case 1 and 2 byte varints. + var x uint64 + if b[0] < 128 { + x = uint64(b[0]) + b = b[1:] + } else if len(b) >= 2 && b[1] < 128 { + x = uint64(b[0]&0x7f) + uint64(b[1])<<7 + b = b[2:] + } else { + var n int + x, n = decodeVarint(b) + if n == 0 { + return io.ErrUnexpectedEOF + } + b = b[n:] + } + tag := x >> 3 + wire := int(x) & 7 + + // Dispatch on the tag to one of the unmarshal* functions below. + var f unmarshalFieldInfo + if tag < uint64(len(u.dense)) { + f = u.dense[tag] + } else { + f = u.sparse[tag] + } + if fn := f.unmarshal; fn != nil { + var err error + b, err = fn(b, m.offset(f.field), wire) + if err == nil { + reqMask |= f.reqMask + continue + } + if r, ok := err.(*RequiredNotSetError); ok { + // Remember this error, but keep parsing. We need to produce + // a full parse even if a required field is missing. + if errLater == nil { + errLater = r + } + reqMask |= f.reqMask + continue + } + if err != errInternalBadWireType { + if err == errInvalidUTF8 { + if errLater == nil { + fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name + errLater = &invalidUTF8Error{fullName} + } + continue + } + return err + } + // Fragments with bad wire type are treated as unknown fields. + } + + // Unknown tag. + if !u.unrecognized.IsValid() { + // Don't keep unrecognized data; just skip it. + var err error + b, err = skipField(b, wire) + if err != nil { + return err + } + continue + } + // Keep unrecognized data around. + // maybe in extensions, maybe in the unrecognized field. + z := m.offset(u.unrecognized).toBytes() + var emap map[int32]Extension + var e Extension + for _, r := range u.extensionRanges { + if uint64(r.Start) <= tag && tag <= uint64(r.End) { + if u.extensions.IsValid() { + mp := m.offset(u.extensions).toExtensions() + emap = mp.extensionsWrite() + e = emap[int32(tag)] + z = &e.enc + break + } + if u.oldExtensions.IsValid() { + p := m.offset(u.oldExtensions).toOldExtensions() + emap = *p + if emap == nil { + emap = map[int32]Extension{} + *p = emap + } + e = emap[int32(tag)] + z = &e.enc + break + } + panic("no extensions field available") + } + } + + // Use wire type to skip data. + var err error + b0 := b + b, err = skipField(b, wire) + if err != nil { + return err + } + *z = encodeVarint(*z, tag<<3|uint64(wire)) + *z = append(*z, b0[:len(b0)-len(b)]...) + + if emap != nil { + emap[int32(tag)] = e + } + } + if reqMask != u.reqMask && errLater == nil { + // A required field of this message is missing. + for _, n := range u.reqFields { + if reqMask&1 == 0 { + errLater = &RequiredNotSetError{n} + } + reqMask >>= 1 + } + } + return errLater +} + +// computeUnmarshalInfo fills in u with information for use +// in unmarshaling protocol buffers of type u.typ. +func (u *unmarshalInfo) computeUnmarshalInfo() { + u.lock.Lock() + defer u.lock.Unlock() + if u.initialized != 0 { + return + } + t := u.typ + n := t.NumField() + + // Set up the "not found" value for the unrecognized byte buffer. + // This is the default for proto3. + u.unrecognized = invalidField + u.extensions = invalidField + u.oldExtensions = invalidField + + // List of the generated type and offset for each oneof field. + type oneofField struct { + ityp reflect.Type // interface type of oneof field + field field // offset in containing message + } + var oneofFields []oneofField + + for i := 0; i < n; i++ { + f := t.Field(i) + if f.Name == "XXX_unrecognized" { + // The byte slice used to hold unrecognized input is special. + if f.Type != reflect.TypeOf(([]byte)(nil)) { + panic("bad type for XXX_unrecognized field: " + f.Type.Name()) + } + u.unrecognized = toField(&f) + continue + } + if f.Name == "XXX_InternalExtensions" { + // Ditto here. + if f.Type != reflect.TypeOf(XXX_InternalExtensions{}) { + panic("bad type for XXX_InternalExtensions field: " + f.Type.Name()) + } + u.extensions = toField(&f) + if f.Tag.Get("protobuf_messageset") == "1" { + u.isMessageSet = true + } + continue + } + if f.Name == "XXX_extensions" { + // An older form of the extensions field. + if f.Type != reflect.TypeOf((map[int32]Extension)(nil)) { + panic("bad type for XXX_extensions field: " + f.Type.Name()) + } + u.oldExtensions = toField(&f) + continue + } + if f.Name == "XXX_NoUnkeyedLiteral" || f.Name == "XXX_sizecache" { + continue + } + + oneof := f.Tag.Get("protobuf_oneof") + if oneof != "" { + oneofFields = append(oneofFields, oneofField{f.Type, toField(&f)}) + // The rest of oneof processing happens below. + continue + } + + tags := f.Tag.Get("protobuf") + tagArray := strings.Split(tags, ",") + if len(tagArray) < 2 { + panic("protobuf tag not enough fields in " + t.Name() + "." + f.Name + ": " + tags) + } + tag, err := strconv.Atoi(tagArray[1]) + if err != nil { + panic("protobuf tag field not an integer: " + tagArray[1]) + } + + name := "" + for _, tag := range tagArray[3:] { + if strings.HasPrefix(tag, "name=") { + name = tag[5:] + } + } + + // Extract unmarshaling function from the field (its type and tags). + unmarshal := fieldUnmarshaler(&f) + + // Required field? + var reqMask uint64 + if tagArray[2] == "req" { + bit := len(u.reqFields) + u.reqFields = append(u.reqFields, name) + reqMask = uint64(1) << uint(bit) + // TODO: if we have more than 64 required fields, we end up + // not verifying that all required fields are present. + // Fix this, perhaps using a count of required fields? + } + + // Store the info in the correct slot in the message. + u.setTag(tag, toField(&f), unmarshal, reqMask, name) + } + + // Find any types associated with oneof fields. + var oneofImplementers []interface{} + switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) { + case oneofFuncsIface: + _, _, _, oneofImplementers = m.XXX_OneofFuncs() + case oneofWrappersIface: + oneofImplementers = m.XXX_OneofWrappers() + } + for _, v := range oneofImplementers { + tptr := reflect.TypeOf(v) // *Msg_X + typ := tptr.Elem() // Msg_X + + f := typ.Field(0) // oneof implementers have one field + baseUnmarshal := fieldUnmarshaler(&f) + tags := strings.Split(f.Tag.Get("protobuf"), ",") + fieldNum, err := strconv.Atoi(tags[1]) + if err != nil { + panic("protobuf tag field not an integer: " + tags[1]) + } + var name string + for _, tag := range tags { + if strings.HasPrefix(tag, "name=") { + name = strings.TrimPrefix(tag, "name=") + break + } + } + + // Find the oneof field that this struct implements. + // Might take O(n^2) to process all of the oneofs, but who cares. + for _, of := range oneofFields { + if tptr.Implements(of.ityp) { + // We have found the corresponding interface for this struct. + // That lets us know where this struct should be stored + // when we encounter it during unmarshaling. + unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal) + u.setTag(fieldNum, of.field, unmarshal, 0, name) + } + } + + } + + // Get extension ranges, if any. + fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray") + if fn.IsValid() { + if !u.extensions.IsValid() && !u.oldExtensions.IsValid() { + panic("a message with extensions, but no extensions field in " + t.Name()) + } + u.extensionRanges = fn.Call(nil)[0].Interface().([]ExtensionRange) + } + + // Explicitly disallow tag 0. This will ensure we flag an error + // when decoding a buffer of all zeros. Without this code, we + // would decode and skip an all-zero buffer of even length. + // [0 0] is [tag=0/wiretype=varint varint-encoded-0]. + u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) { + return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w) + }, 0, "") + + // Set mask for required field check. + u.reqMask = uint64(1)<= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here? + for len(u.dense) <= tag { + u.dense = append(u.dense, unmarshalFieldInfo{}) + } + u.dense[tag] = i + return + } + if u.sparse == nil { + u.sparse = map[uint64]unmarshalFieldInfo{} + } + u.sparse[uint64(tag)] = i +} + +// fieldUnmarshaler returns an unmarshaler for the given field. +func fieldUnmarshaler(f *reflect.StructField) unmarshaler { + if f.Type.Kind() == reflect.Map { + return makeUnmarshalMap(f) + } + return typeUnmarshaler(f.Type, f.Tag.Get("protobuf")) +} + +// typeUnmarshaler returns an unmarshaler for the given field type / field tag pair. +func typeUnmarshaler(t reflect.Type, tags string) unmarshaler { + tagArray := strings.Split(tags, ",") + encoding := tagArray[0] + name := "unknown" + proto3 := false + validateUTF8 := true + for _, tag := range tagArray[3:] { + if strings.HasPrefix(tag, "name=") { + name = tag[5:] + } + if tag == "proto3" { + proto3 = true + } + } + validateUTF8 = validateUTF8 && proto3 + + // Figure out packaging (pointer, slice, or both) + slice := false + pointer := false + if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 { + slice = true + t = t.Elem() + } + if t.Kind() == reflect.Ptr { + pointer = true + t = t.Elem() + } + + // We'll never have both pointer and slice for basic types. + if pointer && slice && t.Kind() != reflect.Struct { + panic("both pointer and slice for basic type in " + t.Name()) + } + + switch t.Kind() { + case reflect.Bool: + if pointer { + return unmarshalBoolPtr + } + if slice { + return unmarshalBoolSlice + } + return unmarshalBoolValue + case reflect.Int32: + switch encoding { + case "fixed32": + if pointer { + return unmarshalFixedS32Ptr + } + if slice { + return unmarshalFixedS32Slice + } + return unmarshalFixedS32Value + case "varint": + // this could be int32 or enum + if pointer { + return unmarshalInt32Ptr + } + if slice { + return unmarshalInt32Slice + } + return unmarshalInt32Value + case "zigzag32": + if pointer { + return unmarshalSint32Ptr + } + if slice { + return unmarshalSint32Slice + } + return unmarshalSint32Value + } + case reflect.Int64: + switch encoding { + case "fixed64": + if pointer { + return unmarshalFixedS64Ptr + } + if slice { + return unmarshalFixedS64Slice + } + return unmarshalFixedS64Value + case "varint": + if pointer { + return unmarshalInt64Ptr + } + if slice { + return unmarshalInt64Slice + } + return unmarshalInt64Value + case "zigzag64": + if pointer { + return unmarshalSint64Ptr + } + if slice { + return unmarshalSint64Slice + } + return unmarshalSint64Value + } + case reflect.Uint32: + switch encoding { + case "fixed32": + if pointer { + return unmarshalFixed32Ptr + } + if slice { + return unmarshalFixed32Slice + } + return unmarshalFixed32Value + case "varint": + if pointer { + return unmarshalUint32Ptr + } + if slice { + return unmarshalUint32Slice + } + return unmarshalUint32Value + } + case reflect.Uint64: + switch encoding { + case "fixed64": + if pointer { + return unmarshalFixed64Ptr + } + if slice { + return unmarshalFixed64Slice + } + return unmarshalFixed64Value + case "varint": + if pointer { + return unmarshalUint64Ptr + } + if slice { + return unmarshalUint64Slice + } + return unmarshalUint64Value + } + case reflect.Float32: + if pointer { + return unmarshalFloat32Ptr + } + if slice { + return unmarshalFloat32Slice + } + return unmarshalFloat32Value + case reflect.Float64: + if pointer { + return unmarshalFloat64Ptr + } + if slice { + return unmarshalFloat64Slice + } + return unmarshalFloat64Value + case reflect.Map: + panic("map type in typeUnmarshaler in " + t.Name()) + case reflect.Slice: + if pointer { + panic("bad pointer in slice case in " + t.Name()) + } + if slice { + return unmarshalBytesSlice + } + return unmarshalBytesValue + case reflect.String: + if validateUTF8 { + if pointer { + return unmarshalUTF8StringPtr + } + if slice { + return unmarshalUTF8StringSlice + } + return unmarshalUTF8StringValue + } + if pointer { + return unmarshalStringPtr + } + if slice { + return unmarshalStringSlice + } + return unmarshalStringValue + case reflect.Struct: + // message or group field + if !pointer { + panic(fmt.Sprintf("message/group field %s:%s without pointer", t, encoding)) + } + switch encoding { + case "bytes": + if slice { + return makeUnmarshalMessageSlicePtr(getUnmarshalInfo(t), name) + } + return makeUnmarshalMessagePtr(getUnmarshalInfo(t), name) + case "group": + if slice { + return makeUnmarshalGroupSlicePtr(getUnmarshalInfo(t), name) + } + return makeUnmarshalGroupPtr(getUnmarshalInfo(t), name) + } + } + panic(fmt.Sprintf("unmarshaler not found type:%s encoding:%s", t, encoding)) +} + +// Below are all the unmarshalers for individual fields of various types. + +func unmarshalInt64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + *f.toInt64() = v + return b, nil +} + +func unmarshalInt64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + *f.toInt64Ptr() = &v + return b, nil +} + +func unmarshalInt64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + s := f.toInt64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x) + s := f.toInt64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalSint64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + *f.toInt64() = v + return b, nil +} + +func unmarshalSint64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + *f.toInt64Ptr() = &v + return b, nil +} + +func unmarshalSint64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + s := f.toInt64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int64(x>>1) ^ int64(x)<<63>>63 + s := f.toInt64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalUint64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + *f.toUint64() = v + return b, nil +} + +func unmarshalUint64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + *f.toUint64Ptr() = &v + return b, nil +} + +func unmarshalUint64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + s := f.toUint64Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint64(x) + s := f.toUint64Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalInt32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + *f.toInt32() = v + return b, nil +} + +func unmarshalInt32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.setInt32Ptr(v) + return b, nil +} + +func unmarshalInt32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.appendInt32Slice(v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x) + f.appendInt32Slice(v) + return b, nil +} + +func unmarshalSint32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + *f.toInt32() = v + return b, nil +} + +func unmarshalSint32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.setInt32Ptr(v) + return b, nil +} + +func unmarshalSint32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.appendInt32Slice(v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := int32(x>>1) ^ int32(x)<<31>>31 + f.appendInt32Slice(v) + return b, nil +} + +func unmarshalUint32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + *f.toUint32() = v + return b, nil +} + +func unmarshalUint32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + *f.toUint32Ptr() = &v + return b, nil +} + +func unmarshalUint32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + s := f.toUint32Slice() + *s = append(*s, v) + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + v := uint32(x) + s := f.toUint32Slice() + *s = append(*s, v) + return b, nil +} + +func unmarshalFixed64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + *f.toUint64() = v + return b[8:], nil +} + +func unmarshalFixed64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + *f.toUint64Ptr() = &v + return b[8:], nil +} + +func unmarshalFixed64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + s := f.toUint64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + s := f.toUint64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFixedS64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + *f.toInt64() = v + return b[8:], nil +} + +func unmarshalFixedS64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + *f.toInt64Ptr() = &v + return b[8:], nil +} + +func unmarshalFixedS64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + s := f.toInt64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56 + s := f.toInt64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFixed32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + *f.toUint32() = v + return b[4:], nil +} + +func unmarshalFixed32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + *f.toUint32Ptr() = &v + return b[4:], nil +} + +func unmarshalFixed32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + s := f.toUint32Slice() + *s = append(*s, v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + s := f.toUint32Slice() + *s = append(*s, v) + return b[4:], nil +} + +func unmarshalFixedS32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + *f.toInt32() = v + return b[4:], nil +} + +func unmarshalFixedS32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.setInt32Ptr(v) + return b[4:], nil +} + +func unmarshalFixedS32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.appendInt32Slice(v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 + f.appendInt32Slice(v) + return b[4:], nil +} + +func unmarshalBoolValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + // Note: any length varint is allowed, even though any sane + // encoder will use one byte. + // See https://github.com/golang/protobuf/issues/76 + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + // TODO: check if x>1? Tests seem to indicate no. + v := x != 0 + *f.toBool() = v + return b[n:], nil +} + +func unmarshalBoolPtr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + *f.toBoolPtr() = &v + return b[n:], nil +} + +func unmarshalBoolSlice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + x, n = decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + s := f.toBoolSlice() + *s = append(*s, v) + b = b[n:] + } + return res, nil + } + if w != WireVarint { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + v := x != 0 + s := f.toBoolSlice() + *s = append(*s, v) + return b[n:], nil +} + +func unmarshalFloat64Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + *f.toFloat64() = v + return b[8:], nil +} + +func unmarshalFloat64Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + *f.toFloat64Ptr() = &v + return b[8:], nil +} + +func unmarshalFloat64Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + s := f.toFloat64Slice() + *s = append(*s, v) + b = b[8:] + } + return res, nil + } + if w != WireFixed64 { + return b, errInternalBadWireType + } + if len(b) < 8 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56) + s := f.toFloat64Slice() + *s = append(*s, v) + return b[8:], nil +} + +func unmarshalFloat32Value(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + *f.toFloat32() = v + return b[4:], nil +} + +func unmarshalFloat32Ptr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + *f.toFloat32Ptr() = &v + return b[4:], nil +} + +func unmarshalFloat32Slice(b []byte, f pointer, w int) ([]byte, error) { + if w == WireBytes { // packed + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + res := b[x:] + b = b[:x] + for len(b) > 0 { + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + s := f.toFloat32Slice() + *s = append(*s, v) + b = b[4:] + } + return res, nil + } + if w != WireFixed32 { + return b, errInternalBadWireType + } + if len(b) < 4 { + return nil, io.ErrUnexpectedEOF + } + v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24) + s := f.toFloat32Slice() + *s = append(*s, v) + return b[4:], nil +} + +func unmarshalStringValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, 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 := string(b[:x]) + *f.toString() = v + return b[x:], nil +} + +func unmarshalStringPtr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, 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 := string(b[:x]) + *f.toStringPtr() = &v + return b[x:], nil +} + +func unmarshalStringSlice(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, 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 := string(b[:x]) + s := f.toStringSlice() + *s = append(*s, v) + return b[x:], nil +} + +func unmarshalUTF8StringValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, 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 := string(b[:x]) + *f.toString() = v + if !utf8.ValidString(v) { + return b[x:], errInvalidUTF8 + } + return b[x:], nil +} + +func unmarshalUTF8StringPtr(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, 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 := string(b[:x]) + *f.toStringPtr() = &v + if !utf8.ValidString(v) { + return b[x:], errInvalidUTF8 + } + return b[x:], nil +} + +func unmarshalUTF8StringSlice(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, 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 := string(b[:x]) + s := f.toStringSlice() + *s = append(*s, v) + if !utf8.ValidString(v) { + return b[x:], errInvalidUTF8 + } + return b[x:], nil +} + +var emptyBuf [0]byte + +func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, errInternalBadWireType + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + // The use of append here is a trick which avoids the zeroing + // that would be required if we used a make/copy pair. + // We append to emptyBuf instead of nil because we want + // a non-nil result even when the length is 0. + v := append(emptyBuf[:], b[:x]...) + *f.toBytes() = v + return b[x:], nil +} + +func unmarshalBytesSlice(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, 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 := append(emptyBuf[:], b[:x]...) + s := f.toBytesSlice() + *s = append(*s, v) + return b[x:], nil +} + +func makeUnmarshalMessagePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, 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.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 makeUnmarshalMessageSlicePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireBytes { + return b, 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.appendPointer(v) + return b[x:], err + } +} + +func makeUnmarshalGroupPtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireStartGroup { + return b, errInternalBadWireType + } + x, y := findEndGroup(b) + if x < 0 { + return nil, io.ErrUnexpectedEOF + } + 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[y:], err + } +} + +func makeUnmarshalGroupSlicePtr(sub *unmarshalInfo, name string) unmarshaler { + return func(b []byte, f pointer, w int) ([]byte, error) { + if w != WireStartGroup { + return b, errInternalBadWireType + } + x, y := findEndGroup(b) + if x < 0 { + 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.appendPointer(v) + return b[y:], err + } +} + +func makeUnmarshalMap(f *reflect.StructField) unmarshaler { + t := f.Type + kt := t.Key() + vt := t.Elem() + unmarshalKey := typeUnmarshaler(kt, f.Tag.Get("protobuf_key")) + unmarshalVal := typeUnmarshaler(vt, f.Tag.Get("protobuf_val")) + return func(b []byte, f pointer, w int) ([]byte, error) { + // The map entry is a submessage. Figure out how big it is. + if w != WireBytes { + return nil, fmt.Errorf("proto: bad wiretype for map field: got %d want %d", w, WireBytes) + } + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + b = b[n:] + if x > uint64(len(b)) { + return nil, io.ErrUnexpectedEOF + } + r := b[x:] // unused data to return + b = b[:x] // data for map entry + + // Note: we could use #keys * #values ~= 200 functions + // to do map decoding without reflection. Probably not worth it. + // Maps will be somewhat slow. Oh well. + + // Read key and value from data. + var nerr nonFatal + k := reflect.New(kt) + v := reflect.New(vt) + for len(b) > 0 { + x, n := decodeVarint(b) + if n == 0 { + return nil, io.ErrUnexpectedEOF + } + wire := int(x) & 7 + b = b[n:] + + var err error + switch x >> 3 { + case 1: + b, err = unmarshalKey(b, valToPointer(k), wire) + case 2: + b, err = unmarshalVal(b, valToPointer(v), wire) + default: + err = errInternalBadWireType // skip unknown tag + } + + if nerr.Merge(err) { + continue + } + if err != errInternalBadWireType { + return nil, err + } + + // Skip past unknown fields. + b, err = skipField(b, wire) + if err != nil { + return nil, err + } + } + + // Get map, allocate if needed. + m := f.asPointerTo(t).Elem() // an addressable map[K]T + if m.IsNil() { + m.Set(reflect.MakeMap(t)) + } + + // Insert into map. + m.SetMapIndex(k.Elem(), v.Elem()) + + return r, nerr.E + } +} + +// makeUnmarshalOneof makes an unmarshaler for oneof fields. +// for: +// message Msg { +// oneof F { +// int64 X = 1; +// float64 Y = 2; +// } +// } +// typ is the type of the concrete entry for a oneof case (e.g. Msg_X). +// ityp is the interface type of the oneof field (e.g. isMsg_F). +// unmarshal is the unmarshaler for the base type of the oneof case (e.g. int64). +// Note that this function will be called once for each case in the oneof. +func makeUnmarshalOneof(typ, ityp reflect.Type, unmarshal unmarshaler) unmarshaler { + sf := typ.Field(0) + field0 := toField(&sf) + return func(b []byte, f pointer, w int) ([]byte, error) { + // Allocate holder for value. + v := reflect.New(typ) + + // Unmarshal data into holder. + // We unmarshal into the first field of the holder object. + var err error + var nerr nonFatal + b, err = unmarshal(b, valToPointer(v).offset(field0), w) + if !nerr.Merge(err) { + return nil, err + } + + // Write pointer to holder into target field. + f.asPointerTo(ityp).Elem().Set(v) + + return b, nerr.E + } +} + +// Error used by decode internally. +var errInternalBadWireType = errors.New("proto: internal error: bad wiretype") + +// skipField skips past a field of type wire and returns the remaining bytes. +func skipField(b []byte, wire int) ([]byte, error) { + switch wire { + case WireVarint: + _, k := decodeVarint(b) + if k == 0 { + return b, io.ErrUnexpectedEOF + } + b = b[k:] + case WireFixed32: + if len(b) < 4 { + return b, io.ErrUnexpectedEOF + } + b = b[4:] + case WireFixed64: + if len(b) < 8 { + return b, io.ErrUnexpectedEOF + } + b = b[8:] + case WireBytes: + m, k := decodeVarint(b) + if k == 0 || uint64(len(b)-k) < m { + return b, io.ErrUnexpectedEOF + } + b = b[uint64(k)+m:] + case WireStartGroup: + _, i := findEndGroup(b) + if i == -1 { + return b, io.ErrUnexpectedEOF + } + b = b[i:] + default: + return b, fmt.Errorf("proto: can't skip unknown wire type %d", wire) + } + return b, nil +} + +// findEndGroup finds the index of the next EndGroup tag. +// Groups may be nested, so the "next" EndGroup tag is the first +// unpaired EndGroup. +// findEndGroup returns the indexes of the start and end of the EndGroup tag. +// Returns (-1,-1) if it can't find one. +func findEndGroup(b []byte) (int, int) { + depth := 1 + i := 0 + for { + x, n := decodeVarint(b[i:]) + if n == 0 { + return -1, -1 + } + j := i + i += n + switch x & 7 { + case WireVarint: + _, k := decodeVarint(b[i:]) + if k == 0 { + return -1, -1 + } + i += k + case WireFixed32: + if len(b)-4 < i { + return -1, -1 + } + i += 4 + case WireFixed64: + if len(b)-8 < i { + return -1, -1 + } + i += 8 + case WireBytes: + m, k := decodeVarint(b[i:]) + if k == 0 { + return -1, -1 + } + i += k + if uint64(len(b)-i) < m { + return -1, -1 + } + i += int(m) + case WireStartGroup: + depth++ + case WireEndGroup: + depth-- + if depth == 0 { + return j, i + } + default: + return -1, -1 + } + } +} + +// encodeVarint appends a varint-encoded integer to b and returns the result. +func encodeVarint(b []byte, x uint64) []byte { + for x >= 1<<7 { + b = append(b, byte(x&0x7f|0x80)) + x >>= 7 + } + return append(b, byte(x)) +} + +// decodeVarint reads a varint-encoded integer from b. +// Returns the decoded integer and the number of bytes read. +// If there is an error, it returns 0,0. +func decodeVarint(b []byte) (uint64, int) { + var x, y uint64 + if len(b) == 0 { + goto bad + } + x = uint64(b[0]) + if x < 0x80 { + return x, 1 + } + x -= 0x80 + + if len(b) <= 1 { + goto bad + } + y = uint64(b[1]) + x += y << 7 + if y < 0x80 { + return x, 2 + } + x -= 0x80 << 7 + + if len(b) <= 2 { + goto bad + } + y = uint64(b[2]) + x += y << 14 + if y < 0x80 { + return x, 3 + } + x -= 0x80 << 14 + + if len(b) <= 3 { + goto bad + } + y = uint64(b[3]) + x += y << 21 + if y < 0x80 { + return x, 4 + } + x -= 0x80 << 21 + + if len(b) <= 4 { + goto bad + } + y = uint64(b[4]) + x += y << 28 + if y < 0x80 { + return x, 5 + } + x -= 0x80 << 28 + + if len(b) <= 5 { + goto bad + } + y = uint64(b[5]) + x += y << 35 + if y < 0x80 { + return x, 6 + } + x -= 0x80 << 35 + + if len(b) <= 6 { + goto bad + } + y = uint64(b[6]) + x += y << 42 + if y < 0x80 { + return x, 7 + } + x -= 0x80 << 42 + + if len(b) <= 7 { + goto bad + } + y = uint64(b[7]) + x += y << 49 + if y < 0x80 { + return x, 8 + } + x -= 0x80 << 49 + + if len(b) <= 8 { + goto bad + } + y = uint64(b[8]) + x += y << 56 + if y < 0x80 { + return x, 9 + } + x -= 0x80 << 56 + + if len(b) <= 9 { + goto bad + } + y = uint64(b[9]) + x += y << 63 + if y < 2 { + return x, 10 + } + +bad: + return 0, 0 +} diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/text.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/text.go new file mode 100644 index 0000000..1aaee72 --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/text.go @@ -0,0 +1,843 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +// Functions for writing the text protocol buffer format. + +import ( + "bufio" + "bytes" + "encoding" + "errors" + "fmt" + "io" + "log" + "math" + "reflect" + "sort" + "strings" +) + +var ( + newline = []byte("\n") + spaces = []byte(" ") + endBraceNewline = []byte("}\n") + backslashN = []byte{'\\', 'n'} + backslashR = []byte{'\\', 'r'} + backslashT = []byte{'\\', 't'} + backslashDQ = []byte{'\\', '"'} + backslashBS = []byte{'\\', '\\'} + posInf = []byte("inf") + negInf = []byte("-inf") + nan = []byte("nan") +) + +type writer interface { + io.Writer + WriteByte(byte) error +} + +// textWriter is an io.Writer that tracks its indentation level. +type textWriter struct { + ind int + complete bool // if the current position is a complete line + compact bool // whether to write out as a one-liner + w writer +} + +func (w *textWriter) WriteString(s string) (n int, err error) { + if !strings.Contains(s, "\n") { + if !w.compact && w.complete { + w.writeIndent() + } + w.complete = false + return io.WriteString(w.w, s) + } + // WriteString is typically called without newlines, so this + // codepath and its copy are rare. We copy to avoid + // duplicating all of Write's logic here. + return w.Write([]byte(s)) +} + +func (w *textWriter) Write(p []byte) (n int, err error) { + newlines := bytes.Count(p, newline) + if newlines == 0 { + if !w.compact && w.complete { + w.writeIndent() + } + n, err = w.w.Write(p) + w.complete = false + return n, err + } + + frags := bytes.SplitN(p, newline, newlines+1) + if w.compact { + for i, frag := range frags { + if i > 0 { + if err := w.w.WriteByte(' '); err != nil { + return n, err + } + n++ + } + nn, err := w.w.Write(frag) + n += nn + if err != nil { + return n, err + } + } + return n, nil + } + + for i, frag := range frags { + if w.complete { + w.writeIndent() + } + nn, err := w.w.Write(frag) + n += nn + if err != nil { + return n, err + } + if i+1 < len(frags) { + if err := w.w.WriteByte('\n'); err != nil { + return n, err + } + n++ + } + } + w.complete = len(frags[len(frags)-1]) == 0 + return n, nil +} + +func (w *textWriter) WriteByte(c byte) error { + if w.compact && c == '\n' { + c = ' ' + } + if !w.compact && w.complete { + w.writeIndent() + } + err := w.w.WriteByte(c) + w.complete = c == '\n' + return err +} + +func (w *textWriter) indent() { w.ind++ } + +func (w *textWriter) unindent() { + if w.ind == 0 { + log.Print("proto: textWriter unindented too far") + return + } + w.ind-- +} + +func writeName(w *textWriter, props *Properties) error { + if _, err := w.WriteString(props.OrigName); err != nil { + return err + } + if props.Wire != "group" { + return w.WriteByte(':') + } + return nil +} + +func requiresQuotes(u string) bool { + // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted. + for _, ch := range u { + switch { + case ch == '.' || ch == '/' || ch == '_': + continue + case '0' <= ch && ch <= '9': + continue + case 'A' <= ch && ch <= 'Z': + continue + case 'a' <= ch && ch <= 'z': + continue + default: + return true + } + } + return false +} + +// isAny reports whether sv is a google.protobuf.Any message +func isAny(sv reflect.Value) bool { + type wkt interface { + XXX_WellKnownType() string + } + t, ok := sv.Addr().Interface().(wkt) + return ok && t.XXX_WellKnownType() == "Any" +} + +// writeProto3Any writes an expanded google.protobuf.Any message. +// +// It returns (false, nil) if sv value can't be unmarshaled (e.g. because +// required messages are not linked in). +// +// It returns (true, error) when sv was written in expanded format or an error +// was encountered. +func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) { + turl := sv.FieldByName("TypeUrl") + val := sv.FieldByName("Value") + if !turl.IsValid() || !val.IsValid() { + return true, errors.New("proto: invalid google.protobuf.Any message") + } + + b, ok := val.Interface().([]byte) + if !ok { + return true, errors.New("proto: invalid google.protobuf.Any message") + } + + parts := strings.Split(turl.String(), "/") + mt := MessageType(parts[len(parts)-1]) + if mt == nil { + return false, nil + } + m := reflect.New(mt.Elem()) + if err := Unmarshal(b, m.Interface().(Message)); err != nil { + return false, nil + } + w.Write([]byte("[")) + u := turl.String() + if requiresQuotes(u) { + writeString(w, u) + } else { + w.Write([]byte(u)) + } + if w.compact { + w.Write([]byte("]:<")) + } else { + w.Write([]byte("]: <\n")) + w.ind++ + } + if err := tm.writeStruct(w, m.Elem()); err != nil { + return true, err + } + if w.compact { + w.Write([]byte("> ")) + } else { + w.ind-- + w.Write([]byte(">\n")) + } + return true, nil +} + +func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { + if tm.ExpandAny && isAny(sv) { + if canExpand, err := tm.writeProto3Any(w, sv); canExpand { + return err + } + } + st := sv.Type() + sprops := GetProperties(st) + for i := 0; i < sv.NumField(); i++ { + fv := sv.Field(i) + props := sprops.Prop[i] + name := st.Field(i).Name + + if name == "XXX_NoUnkeyedLiteral" { + continue + } + + if strings.HasPrefix(name, "XXX_") { + // There are two XXX_ fields: + // XXX_unrecognized []byte + // XXX_extensions map[int32]proto.Extension + // The first is handled here; + // the second is handled at the bottom of this function. + if name == "XXX_unrecognized" && !fv.IsNil() { + if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil { + return err + } + } + continue + } + if fv.Kind() == reflect.Ptr && fv.IsNil() { + // Field not filled in. This could be an optional field or + // a required field that wasn't filled in. Either way, there + // isn't anything we can show for it. + continue + } + if fv.Kind() == reflect.Slice && fv.IsNil() { + // Repeated field that is empty, or a bytes field that is unused. + continue + } + + if props.Repeated && fv.Kind() == reflect.Slice { + // Repeated field. + for j := 0; j < fv.Len(); j++ { + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + v := fv.Index(j) + if v.Kind() == reflect.Ptr && v.IsNil() { + // A nil message in a repeated field is not valid, + // but we can handle that more gracefully than panicking. + if _, err := w.Write([]byte("\n")); err != nil { + return err + } + continue + } + if err := tm.writeAny(w, v, props); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + continue + } + if fv.Kind() == reflect.Map { + // Map fields are rendered as a repeated struct with key/value fields. + keys := fv.MapKeys() + sort.Sort(mapKeys(keys)) + for _, key := range keys { + val := fv.MapIndex(key) + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + // open struct + if err := w.WriteByte('<'); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte('\n'); err != nil { + return err + } + } + w.indent() + // key + if _, err := w.WriteString("key:"); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := tm.writeAny(w, key, props.MapKeyProp); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + // nil values aren't legal, but we can avoid panicking because of them. + if val.Kind() != reflect.Ptr || !val.IsNil() { + // value + if _, err := w.WriteString("value:"); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := tm.writeAny(w, val, props.MapValProp); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + // close struct + w.unindent() + if err := w.WriteByte('>'); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + continue + } + if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 { + // empty bytes field + continue + } + if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice { + // proto3 non-repeated scalar field; skip if zero value + if isProto3Zero(fv) { + continue + } + } + + if fv.Kind() == reflect.Interface { + // Check if it is a oneof. + if st.Field(i).Tag.Get("protobuf_oneof") != "" { + // fv is nil, or holds a pointer to generated struct. + // That generated struct has exactly one field, + // which has a protobuf struct tag. + if fv.IsNil() { + continue + } + inner := fv.Elem().Elem() // interface -> *T -> T + tag := inner.Type().Field(0).Tag.Get("protobuf") + props = new(Properties) // Overwrite the outer props var, but not its pointee. + props.Parse(tag) + // Write the value in the oneof, not the oneof itself. + fv = inner.Field(0) + + // Special case to cope with malformed messages gracefully: + // If the value in the oneof is a nil pointer, don't panic + // in writeAny. + if fv.Kind() == reflect.Ptr && fv.IsNil() { + // Use errors.New so writeAny won't render quotes. + msg := errors.New("/* nil */") + fv = reflect.ValueOf(&msg).Elem() + } + } + } + + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + + // Enums have a String method, so writeAny will work fine. + if err := tm.writeAny(w, fv, props); err != nil { + return err + } + + if err := w.WriteByte('\n'); err != nil { + return err + } + } + + // Extensions (the XXX_extensions field). + pv := sv.Addr() + if _, err := extendable(pv.Interface()); err == nil { + if err := tm.writeExtensions(w, pv); err != nil { + return err + } + } + + return nil +} + +// writeAny writes an arbitrary field. +func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { + v = reflect.Indirect(v) + + // Floats have special cases. + if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 { + x := v.Float() + var b []byte + switch { + case math.IsInf(x, 1): + b = posInf + case math.IsInf(x, -1): + b = negInf + case math.IsNaN(x): + b = nan + } + if b != nil { + _, err := w.Write(b) + return err + } + // Other values are handled below. + } + + // We don't attempt to serialise every possible value type; only those + // that can occur in protocol buffers. + switch v.Kind() { + case reflect.Slice: + // Should only be a []byte; repeated fields are handled in writeStruct. + if err := writeString(w, string(v.Bytes())); err != nil { + return err + } + case reflect.String: + if err := writeString(w, v.String()); err != nil { + return err + } + case reflect.Struct: + // Required/optional group/message. + var bra, ket byte = '<', '>' + if props != nil && props.Wire == "group" { + bra, ket = '{', '}' + } + if err := w.WriteByte(bra); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte('\n'); err != nil { + return err + } + } + w.indent() + if v.CanAddr() { + // Calling v.Interface on a struct causes the reflect package to + // copy the entire struct. This is racy with the new Marshaler + // since we atomically update the XXX_sizecache. + // + // Thus, we retrieve a pointer to the struct if possible to avoid + // a race since v.Interface on the pointer doesn't copy the struct. + // + // If v is not addressable, then we are not worried about a race + // since it implies that the binary Marshaler cannot possibly be + // mutating this value. + v = v.Addr() + } + if etm, ok := v.Interface().(encoding.TextMarshaler); ok { + text, err := etm.MarshalText() + if err != nil { + return err + } + if _, err = w.Write(text); err != nil { + return err + } + } else { + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + if err := tm.writeStruct(w, v); err != nil { + return err + } + } + w.unindent() + if err := w.WriteByte(ket); err != nil { + return err + } + default: + _, err := fmt.Fprint(w, v.Interface()) + return err + } + return nil +} + +// equivalent to C's isprint. +func isprint(c byte) bool { + return c >= 0x20 && c < 0x7f +} + +// writeString writes a string in the protocol buffer text format. +// It is similar to strconv.Quote except we don't use Go escape sequences, +// we treat the string as a byte sequence, and we use octal escapes. +// These differences are to maintain interoperability with the other +// languages' implementations of the text format. +func writeString(w *textWriter, s string) error { + // use WriteByte here to get any needed indent + if err := w.WriteByte('"'); err != nil { + return err + } + // Loop over the bytes, not the runes. + for i := 0; i < len(s); i++ { + var err error + // Divergence from C++: we don't escape apostrophes. + // There's no need to escape them, and the C++ parser + // copes with a naked apostrophe. + switch c := s[i]; c { + case '\n': + _, err = w.w.Write(backslashN) + case '\r': + _, err = w.w.Write(backslashR) + case '\t': + _, err = w.w.Write(backslashT) + case '"': + _, err = w.w.Write(backslashDQ) + case '\\': + _, err = w.w.Write(backslashBS) + default: + if isprint(c) { + err = w.w.WriteByte(c) + } else { + _, err = fmt.Fprintf(w.w, "\\%03o", c) + } + } + if err != nil { + return err + } + } + return w.WriteByte('"') +} + +func writeUnknownStruct(w *textWriter, data []byte) (err error) { + if !w.compact { + if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil { + return err + } + } + b := NewBuffer(data) + for b.index < len(b.buf) { + x, err := b.DecodeVarint() + if err != nil { + _, err := fmt.Fprintf(w, "/* %v */\n", err) + return err + } + wire, tag := x&7, x>>3 + if wire == WireEndGroup { + w.unindent() + if _, err := w.Write(endBraceNewline); err != nil { + return err + } + continue + } + if _, err := fmt.Fprint(w, tag); err != nil { + return err + } + if wire != WireStartGroup { + if err := w.WriteByte(':'); err != nil { + return err + } + } + if !w.compact || wire == WireStartGroup { + if err := w.WriteByte(' '); err != nil { + return err + } + } + switch wire { + case WireBytes: + buf, e := b.DecodeRawBytes(false) + if e == nil { + _, err = fmt.Fprintf(w, "%q", buf) + } else { + _, err = fmt.Fprintf(w, "/* %v */", e) + } + case WireFixed32: + x, err = b.DecodeFixed32() + err = writeUnknownInt(w, x, err) + case WireFixed64: + x, err = b.DecodeFixed64() + err = writeUnknownInt(w, x, err) + case WireStartGroup: + err = w.WriteByte('{') + w.indent() + case WireVarint: + x, err = b.DecodeVarint() + err = writeUnknownInt(w, x, err) + default: + _, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire) + } + if err != nil { + return err + } + if err = w.WriteByte('\n'); err != nil { + return err + } + } + return nil +} + +func writeUnknownInt(w *textWriter, x uint64, err error) error { + if err == nil { + _, err = fmt.Fprint(w, x) + } else { + _, err = fmt.Fprintf(w, "/* %v */", err) + } + return err +} + +type int32Slice []int32 + +func (s int32Slice) Len() int { return len(s) } +func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// writeExtensions writes all the extensions in pv. +// pv is assumed to be a pointer to a protocol message struct that is extendable. +func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error { + emap := extensionMaps[pv.Type().Elem()] + ep, _ := extendable(pv.Interface()) + + // Order the extensions by ID. + // This isn't strictly necessary, but it will give us + // canonical output, which will also make testing easier. + m, mu := ep.extensionsRead() + if m == nil { + return nil + } + mu.Lock() + ids := make([]int32, 0, len(m)) + for id := range m { + ids = append(ids, id) + } + sort.Sort(int32Slice(ids)) + mu.Unlock() + + for _, extNum := range ids { + ext := m[extNum] + var desc *ExtensionDesc + if emap != nil { + desc = emap[extNum] + } + if desc == nil { + // Unknown extension. + if err := writeUnknownStruct(w, ext.enc); err != nil { + return err + } + continue + } + + pb, err := GetExtension(ep, desc) + if err != nil { + return fmt.Errorf("failed getting extension: %v", err) + } + + // Repeated extensions will appear as a slice. + if !desc.repeated() { + if err := tm.writeExtension(w, desc.Name, pb); err != nil { + return err + } + } else { + v := reflect.ValueOf(pb) + for i := 0; i < v.Len(); i++ { + if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil { + return err + } + } + } + } + return nil +} + +func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error { + if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + return nil +} + +func (w *textWriter) writeIndent() { + if !w.complete { + return + } + remain := w.ind * 2 + for remain > 0 { + n := remain + if n > len(spaces) { + n = len(spaces) + } + w.w.Write(spaces[:n]) + remain -= n + } + w.complete = false +} + +// TextMarshaler is a configurable text format marshaler. +type TextMarshaler struct { + Compact bool // use compact text format (one line). + ExpandAny bool // expand google.protobuf.Any messages of known types +} + +// Marshal writes a given protocol buffer in text format. +// The only errors returned are from w. +func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error { + val := reflect.ValueOf(pb) + if pb == nil || val.IsNil() { + w.Write([]byte("")) + return nil + } + var bw *bufio.Writer + ww, ok := w.(writer) + if !ok { + bw = bufio.NewWriter(w) + ww = bw + } + aw := &textWriter{ + w: ww, + complete: true, + compact: tm.Compact, + } + + if etm, ok := pb.(encoding.TextMarshaler); ok { + text, err := etm.MarshalText() + if err != nil { + return err + } + if _, err = aw.Write(text); err != nil { + return err + } + if bw != nil { + return bw.Flush() + } + return nil + } + // Dereference the received pointer so we don't have outer < and >. + v := reflect.Indirect(val) + if err := tm.writeStruct(aw, v); err != nil { + return err + } + if bw != nil { + return bw.Flush() + } + return nil +} + +// Text is the same as Marshal, but returns the string directly. +func (tm *TextMarshaler) Text(pb Message) string { + var buf bytes.Buffer + tm.Marshal(&buf, pb) + return buf.String() +} + +var ( + defaultTextMarshaler = TextMarshaler{} + compactTextMarshaler = TextMarshaler{Compact: true} +) + +// TODO: consider removing some of the Marshal functions below. + +// MarshalText writes a given protocol buffer in text format. +// The only errors returned are from w. +func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) } + +// MarshalTextString is the same as MarshalText, but returns the string directly. +func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) } + +// CompactText writes a given protocol buffer in compact text format (one line). +func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) } + +// CompactTextString is the same as CompactText, but returns the string directly. +func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) } diff --git a/go/src/themaru/vendor/github.com/golang/protobuf/proto/text_parser.go b/go/src/themaru/vendor/github.com/golang/protobuf/proto/text_parser.go new file mode 100644 index 0000000..bb55a3a --- /dev/null +++ b/go/src/themaru/vendor/github.com/golang/protobuf/proto/text_parser.go @@ -0,0 +1,880 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +// Functions for parsing the Text protocol buffer format. +// TODO: message sets. + +import ( + "encoding" + "errors" + "fmt" + "reflect" + "strconv" + "strings" + "unicode/utf8" +) + +// Error string emitted when deserializing Any and fields are already set +const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set" + +type ParseError struct { + Message string + Line int // 1-based line number + Offset int // 0-based byte offset from start of input +} + +func (p *ParseError) Error() string { + if p.Line == 1 { + // show offset only for first line + return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message) + } + return fmt.Sprintf("line %d: %v", p.Line, p.Message) +} + +type token struct { + value string + err *ParseError + line int // line number + offset int // byte number from start of input, not start of line + unquoted string // the unquoted version of value, if it was a quoted string +} + +func (t *token) String() string { + if t.err == nil { + return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset) + } + return fmt.Sprintf("parse error: %v", t.err) +} + +type textParser struct { + s string // remaining input + done bool // whether the parsing is finished (success or error) + backed bool // whether back() was called + offset, line int + cur token +} + +func newTextParser(s string) *textParser { + p := new(textParser) + p.s = s + p.line = 1 + p.cur.line = 1 + return p +} + +func (p *textParser) errorf(format string, a ...interface{}) *ParseError { + pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset} + p.cur.err = pe + p.done = true + return pe +} + +// Numbers and identifiers are matched by [-+._A-Za-z0-9] +func isIdentOrNumberChar(c byte) bool { + switch { + case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z': + return true + case '0' <= c && c <= '9': + return true + } + switch c { + case '-', '+', '.', '_': + return true + } + return false +} + +func isWhitespace(c byte) bool { + switch c { + case ' ', '\t', '\n', '\r': + return true + } + return false +} + +func isQuote(c byte) bool { + switch c { + case '"', '\'': + return true + } + return false +} + +func (p *textParser) skipWhitespace() { + i := 0 + for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') { + if p.s[i] == '#' { + // comment; skip to end of line or input + for i < len(p.s) && p.s[i] != '\n' { + i++ + } + if i == len(p.s) { + break + } + } + if p.s[i] == '\n' { + p.line++ + } + i++ + } + p.offset += i + p.s = p.s[i:len(p.s)] + if len(p.s) == 0 { + p.done = true + } +} + +func (p *textParser) advance() { + // Skip whitespace + p.skipWhitespace() + if p.done { + return + } + + // Start of non-whitespace + p.cur.err = nil + p.cur.offset, p.cur.line = p.offset, p.line + p.cur.unquoted = "" + switch p.s[0] { + case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/': + // Single symbol + p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)] + case '"', '\'': + // Quoted string + i := 1 + for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' { + if p.s[i] == '\\' && i+1 < len(p.s) { + // skip escaped char + i++ + } + i++ + } + if i >= len(p.s) || p.s[i] != p.s[0] { + p.errorf("unmatched quote") + return + } + unq, err := unquoteC(p.s[1:i], rune(p.s[0])) + if err != nil { + p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err) + return + } + p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)] + p.cur.unquoted = unq + default: + i := 0 + for i < len(p.s) && isIdentOrNumberChar(p.s[i]) { + i++ + } + if i == 0 { + p.errorf("unexpected byte %#x", p.s[0]) + return + } + p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)] + } + p.offset += len(p.cur.value) +} + +var ( + errBadUTF8 = errors.New("proto: bad UTF-8") +) + +func unquoteC(s string, quote rune) (string, error) { + // This is based on C++'s tokenizer.cc. + // Despite its name, this is *not* parsing C syntax. + // For instance, "\0" is an invalid quoted string. + + // Avoid allocation in trivial cases. + simple := true + for _, r := range s { + if r == '\\' || r == quote { + simple = false + break + } + } + if simple { + return s, nil + } + + buf := make([]byte, 0, 3*len(s)/2) + for len(s) > 0 { + r, n := utf8.DecodeRuneInString(s) + if r == utf8.RuneError && n == 1 { + return "", errBadUTF8 + } + s = s[n:] + if r != '\\' { + if r < utf8.RuneSelf { + buf = append(buf, byte(r)) + } else { + buf = append(buf, string(r)...) + } + continue + } + + ch, tail, err := unescape(s) + if err != nil { + return "", err + } + buf = append(buf, ch...) + s = tail + } + return string(buf), nil +} + +func unescape(s string) (ch string, tail string, err error) { + r, n := utf8.DecodeRuneInString(s) + if r == utf8.RuneError && n == 1 { + return "", "", errBadUTF8 + } + s = s[n:] + switch r { + case 'a': + return "\a", s, nil + case 'b': + return "\b", s, nil + case 'f': + return "\f", s, nil + case 'n': + return "\n", s, nil + case 'r': + return "\r", s, nil + case 't': + return "\t", s, nil + case 'v': + return "\v", s, nil + case '?': + return "?", s, nil // trigraph workaround + case '\'', '"', '\\': + return string(r), s, nil + case '0', '1', '2', '3', '4', '5', '6', '7': + if len(s) < 2 { + return "", "", fmt.Errorf(`\%c requires 2 following digits`, r) + } + ss := string(r) + s[:2] + s = s[2:] + i, err := strconv.ParseUint(ss, 8, 8) + if err != nil { + return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss) + } + return string([]byte{byte(i)}), s, nil + case 'x', 'X', 'u', 'U': + var n int + switch r { + case 'x', 'X': + n = 2 + case 'u': + n = 4 + case 'U': + n = 8 + } + if len(s) < n { + return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n) + } + ss := s[:n] + s = s[n:] + i, err := strconv.ParseUint(ss, 16, 64) + if err != nil { + return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss) + } + if r == 'x' || r == 'X' { + return string([]byte{byte(i)}), s, nil + } + if i > utf8.MaxRune { + return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss) + } + return string(i), s, nil + } + return "", "", fmt.Errorf(`unknown escape \%c`, r) +} + +// Back off the parser by one token. Can only be done between calls to next(). +// It makes the next advance() a no-op. +func (p *textParser) back() { p.backed = true } + +// Advances the parser and returns the new current token. +func (p *textParser) next() *token { + if p.backed || p.done { + p.backed = false + return &p.cur + } + p.advance() + if p.done { + p.cur.value = "" + } else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) { + // Look for multiple quoted strings separated by whitespace, + // and concatenate them. + cat := p.cur + for { + p.skipWhitespace() + if p.done || !isQuote(p.s[0]) { + break + } + p.advance() + if p.cur.err != nil { + return &p.cur + } + cat.value += " " + p.cur.value + cat.unquoted += p.cur.unquoted + } + p.done = false // parser may have seen EOF, but we want to return cat + p.cur = cat + } + return &p.cur +} + +func (p *textParser) consumeToken(s string) error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != s { + p.back() + return p.errorf("expected %q, found %q", s, tok.value) + } + return nil +} + +// Return a RequiredNotSetError indicating which required field was not set. +func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError { + st := sv.Type() + sprops := GetProperties(st) + for i := 0; i < st.NumField(); i++ { + if !isNil(sv.Field(i)) { + continue + } + + props := sprops.Prop[i] + if props.Required { + return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)} + } + } + return &RequiredNotSetError{fmt.Sprintf("%v.", st)} // should not happen +} + +// Returns the index in the struct for the named field, as well as the parsed tag properties. +func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) { + i, ok := sprops.decoderOrigNames[name] + if ok { + return i, sprops.Prop[i], true + } + return -1, nil, false +} + +// Consume a ':' from the input stream (if the next token is a colon), +// returning an error if a colon is needed but not present. +func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != ":" { + // Colon is optional when the field is a group or message. + needColon := true + switch props.Wire { + case "group": + needColon = false + case "bytes": + // A "bytes" field is either a message, a string, or a repeated field; + // those three become *T, *string and []T respectively, so we can check for + // this field being a pointer to a non-string. + if typ.Kind() == reflect.Ptr { + // *T or *string + if typ.Elem().Kind() == reflect.String { + break + } + } else if typ.Kind() == reflect.Slice { + // []T or []*T + if typ.Elem().Kind() != reflect.Ptr { + break + } + } else if typ.Kind() == reflect.String { + // The proto3 exception is for a string field, + // which requires a colon. + break + } + needColon = false + } + if needColon { + return p.errorf("expected ':', found %q", tok.value) + } + p.back() + } + return nil +} + +func (p *textParser) readStruct(sv reflect.Value, terminator string) error { + st := sv.Type() + sprops := GetProperties(st) + reqCount := sprops.reqCount + var reqFieldErr error + fieldSet := make(map[string]bool) + // A struct is a sequence of "name: value", terminated by one of + // '>' or '}', or the end of the input. A name may also be + // "[extension]" or "[type/url]". + // + // The whole struct can also be an expanded Any message, like: + // [type/url] < ... struct contents ... > + for { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == terminator { + break + } + if tok.value == "[" { + // Looks like an extension or an Any. + // + // TODO: Check whether we need to handle + // namespace rooted names (e.g. ".something.Foo"). + extName, err := p.consumeExtName() + if err != nil { + return err + } + + if s := strings.LastIndex(extName, "/"); s >= 0 { + // If it contains a slash, it's an Any type URL. + messageName := extName[s+1:] + mt := MessageType(messageName) + if mt == nil { + return p.errorf("unrecognized message %q in google.protobuf.Any", messageName) + } + tok = p.next() + if tok.err != nil { + return tok.err + } + // consume an optional colon + if tok.value == ":" { + tok = p.next() + if tok.err != nil { + return tok.err + } + } + var terminator string + switch tok.value { + case "<": + terminator = ">" + case "{": + terminator = "}" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + v := reflect.New(mt.Elem()) + if pe := p.readStruct(v.Elem(), terminator); pe != nil { + return pe + } + b, err := Marshal(v.Interface().(Message)) + if err != nil { + return p.errorf("failed to marshal message of type %q: %v", messageName, err) + } + if fieldSet["type_url"] { + return p.errorf(anyRepeatedlyUnpacked, "type_url") + } + if fieldSet["value"] { + return p.errorf(anyRepeatedlyUnpacked, "value") + } + sv.FieldByName("TypeUrl").SetString(extName) + sv.FieldByName("Value").SetBytes(b) + fieldSet["type_url"] = true + fieldSet["value"] = true + continue + } + + var desc *ExtensionDesc + // This could be faster, but it's functional. + // TODO: Do something smarter than a linear scan. + for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) { + if d.Name == extName { + desc = d + break + } + } + if desc == nil { + return p.errorf("unrecognized extension %q", extName) + } + + props := &Properties{} + props.Parse(desc.Tag) + + typ := reflect.TypeOf(desc.ExtensionType) + if err := p.checkForColon(props, typ); err != nil { + return err + } + + rep := desc.repeated() + + // Read the extension structure, and set it in + // the value we're constructing. + var ext reflect.Value + if !rep { + ext = reflect.New(typ).Elem() + } else { + ext = reflect.New(typ.Elem()).Elem() + } + if err := p.readAny(ext, props); err != nil { + if _, ok := err.(*RequiredNotSetError); !ok { + return err + } + reqFieldErr = err + } + ep := sv.Addr().Interface().(Message) + if !rep { + SetExtension(ep, desc, ext.Interface()) + } else { + old, err := GetExtension(ep, desc) + var sl reflect.Value + if err == nil { + sl = reflect.ValueOf(old) // existing slice + } else { + sl = reflect.MakeSlice(typ, 0, 1) + } + sl = reflect.Append(sl, ext) + SetExtension(ep, desc, sl.Interface()) + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + continue + } + + // This is a normal, non-extension field. + name := tok.value + var dst reflect.Value + fi, props, ok := structFieldByName(sprops, name) + if ok { + dst = sv.Field(fi) + } else if oop, ok := sprops.OneofTypes[name]; ok { + // It is a oneof. + props = oop.Prop + nv := reflect.New(oop.Type.Elem()) + dst = nv.Elem().Field(0) + field := sv.Field(oop.Field) + if !field.IsNil() { + return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, sv.Type().Field(oop.Field).Name) + } + field.Set(nv) + } + if !dst.IsValid() { + return p.errorf("unknown field name %q in %v", name, st) + } + + if dst.Kind() == reflect.Map { + // Consume any colon. + if err := p.checkForColon(props, dst.Type()); err != nil { + return err + } + + // Construct the map if it doesn't already exist. + if dst.IsNil() { + dst.Set(reflect.MakeMap(dst.Type())) + } + key := reflect.New(dst.Type().Key()).Elem() + val := reflect.New(dst.Type().Elem()).Elem() + + // The map entry should be this sequence of tokens: + // < key : KEY value : VALUE > + // However, implementations may omit key or value, and technically + // we should support them in any order. See b/28924776 for a time + // this went wrong. + + tok := p.next() + var terminator string + switch tok.value { + case "<": + terminator = ">" + case "{": + terminator = "}" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + for { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == terminator { + break + } + switch tok.value { + case "key": + if err := p.consumeToken(":"); err != nil { + return err + } + if err := p.readAny(key, props.MapKeyProp); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + case "value": + if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil { + return err + } + if err := p.readAny(val, props.MapValProp); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + default: + p.back() + return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value) + } + } + + dst.SetMapIndex(key, val) + continue + } + + // Check that it's not already set if it's not a repeated field. + if !props.Repeated && fieldSet[name] { + return p.errorf("non-repeated field %q was repeated", name) + } + + if err := p.checkForColon(props, dst.Type()); err != nil { + return err + } + + // Parse into the field. + fieldSet[name] = true + if err := p.readAny(dst, props); err != nil { + if _, ok := err.(*RequiredNotSetError); !ok { + return err + } + reqFieldErr = err + } + if props.Required { + reqCount-- + } + + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + + } + + if reqCount > 0 { + return p.missingRequiredFieldError(sv) + } + return reqFieldErr +} + +// consumeExtName consumes extension name or expanded Any type URL and the +// following ']'. It returns the name or URL consumed. +func (p *textParser) consumeExtName() (string, error) { + tok := p.next() + if tok.err != nil { + return "", tok.err + } + + // If extension name or type url is quoted, it's a single token. + if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] { + name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0])) + if err != nil { + return "", err + } + return name, p.consumeToken("]") + } + + // Consume everything up to "]" + var parts []string + for tok.value != "]" { + parts = append(parts, tok.value) + tok = p.next() + if tok.err != nil { + return "", p.errorf("unrecognized type_url or extension name: %s", tok.err) + } + if p.done && tok.value != "]" { + return "", p.errorf("unclosed type_url or extension name") + } + } + return strings.Join(parts, ""), nil +} + +// consumeOptionalSeparator consumes an optional semicolon or comma. +// It is used in readStruct to provide backward compatibility. +func (p *textParser) consumeOptionalSeparator() error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != ";" && tok.value != "," { + p.back() + } + return nil +} + +func (p *textParser) readAny(v reflect.Value, props *Properties) error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == "" { + return p.errorf("unexpected EOF") + } + + switch fv := v; fv.Kind() { + case reflect.Slice: + at := v.Type() + if at.Elem().Kind() == reflect.Uint8 { + // Special case for []byte + if tok.value[0] != '"' && tok.value[0] != '\'' { + // Deliberately written out here, as the error after + // this switch statement would write "invalid []byte: ...", + // which is not as user-friendly. + return p.errorf("invalid string: %v", tok.value) + } + bytes := []byte(tok.unquoted) + fv.Set(reflect.ValueOf(bytes)) + return nil + } + // Repeated field. + if tok.value == "[" { + // Repeated field with list notation, like [1,2,3]. + for { + fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) + err := p.readAny(fv.Index(fv.Len()-1), props) + if err != nil { + return err + } + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == "]" { + break + } + if tok.value != "," { + return p.errorf("Expected ']' or ',' found %q", tok.value) + } + } + return nil + } + // One value of the repeated field. + p.back() + fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) + return p.readAny(fv.Index(fv.Len()-1), props) + case reflect.Bool: + // true/1/t/True or false/f/0/False. + switch tok.value { + case "true", "1", "t", "True": + fv.SetBool(true) + return nil + case "false", "0", "f", "False": + fv.SetBool(false) + return nil + } + case reflect.Float32, reflect.Float64: + v := tok.value + // Ignore 'f' for compatibility with output generated by C++, but don't + // remove 'f' when the value is "-inf" or "inf". + if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" { + v = v[:len(v)-1] + } + if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil { + fv.SetFloat(f) + return nil + } + case reflect.Int32: + if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil { + fv.SetInt(x) + return nil + } + + if len(props.Enum) == 0 { + break + } + m, ok := enumValueMaps[props.Enum] + if !ok { + break + } + x, ok := m[tok.value] + if !ok { + break + } + fv.SetInt(int64(x)) + return nil + case reflect.Int64: + if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil { + fv.SetInt(x) + return nil + } + + case reflect.Ptr: + // A basic field (indirected through pointer), or a repeated message/group + p.back() + fv.Set(reflect.New(fv.Type().Elem())) + return p.readAny(fv.Elem(), props) + case reflect.String: + if tok.value[0] == '"' || tok.value[0] == '\'' { + fv.SetString(tok.unquoted) + return nil + } + case reflect.Struct: + var terminator string + switch tok.value { + case "{": + terminator = "}" + case "<": + terminator = ">" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + // TODO: Handle nested messages which implement encoding.TextUnmarshaler. + return p.readStruct(fv, terminator) + case reflect.Uint32: + if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil { + fv.SetUint(uint64(x)) + return nil + } + case reflect.Uint64: + if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil { + fv.SetUint(x) + return nil + } + } + return p.errorf("invalid %v: %v", v.Type(), tok.value) +} + +// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb +// before starting to unmarshal, so any existing data in pb is always removed. +// If a required field is not set and no other error occurs, +// UnmarshalText returns *RequiredNotSetError. +func UnmarshalText(s string, pb Message) error { + if um, ok := pb.(encoding.TextUnmarshaler); ok { + return um.UnmarshalText([]byte(s)) + } + pb.Reset() + v := reflect.ValueOf(pb) + return newTextParser(s).readStruct(v.Elem(), "") +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/.codecov.yml b/go/src/themaru/vendor/github.com/json-iterator/go/.codecov.yml new file mode 100644 index 0000000..955dc0b --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/.codecov.yml @@ -0,0 +1,3 @@ +ignore: + - "output_tests/.*" + diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/.gitignore b/go/src/themaru/vendor/github.com/json-iterator/go/.gitignore new file mode 100644 index 0000000..1555653 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/.gitignore @@ -0,0 +1,4 @@ +/vendor +/bug_test.go +/coverage.txt +/.idea diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/.travis.yml b/go/src/themaru/vendor/github.com/json-iterator/go/.travis.yml new file mode 100644 index 0000000..449e67c --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/.travis.yml @@ -0,0 +1,14 @@ +language: go + +go: + - 1.8.x + - 1.x + +before_install: + - go get -t -v ./... + +script: + - ./test.sh + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/Gopkg.lock b/go/src/themaru/vendor/github.com/json-iterator/go/Gopkg.lock new file mode 100644 index 0000000..c8a9fbb --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/modern-go/concurrent" + packages = ["."] + revision = "e0a39a4cb4216ea8db28e22a69f4ec25610d513a" + version = "1.0.0" + +[[projects]] + name = "github.com/modern-go/reflect2" + packages = ["."] + revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd" + version = "1.0.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "ea54a775e5a354cb015502d2e7aa4b74230fc77e894f34a838b268c25ec8eeb8" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/Gopkg.toml b/go/src/themaru/vendor/github.com/json-iterator/go/Gopkg.toml new file mode 100644 index 0000000..313a0f8 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/Gopkg.toml @@ -0,0 +1,26 @@ +# 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" + +ignored = ["github.com/davecgh/go-spew*","github.com/google/gofuzz*","github.com/stretchr/testify*"] + +[[constraint]] + name = "github.com/modern-go/reflect2" + version = "1.0.1" diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/LICENSE b/go/src/themaru/vendor/github.com/json-iterator/go/LICENSE new file mode 100644 index 0000000..2cf4f5a --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 json-iterator + +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. diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/README.md b/go/src/themaru/vendor/github.com/json-iterator/go/README.md new file mode 100644 index 0000000..50d56ff --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/README.md @@ -0,0 +1,87 @@ +[![Sourcegraph](https://sourcegraph.com/github.com/json-iterator/go/-/badge.svg)](https://sourcegraph.com/github.com/json-iterator/go?badge) +[![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/json-iterator/go) +[![Build Status](https://travis-ci.org/json-iterator/go.svg?branch=master)](https://travis-ci.org/json-iterator/go) +[![codecov](https://codecov.io/gh/json-iterator/go/branch/master/graph/badge.svg)](https://codecov.io/gh/json-iterator/go) +[![rcard](https://goreportcard.com/badge/github.com/json-iterator/go)](https://goreportcard.com/report/github.com/json-iterator/go) +[![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/json-iterator/go/master/LICENSE) +[![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/json-iterator/Lobby) + +A high-performance 100% compatible drop-in replacement of "encoding/json" + +You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go) + +# Benchmark + +![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png) + +Source code: https://github.com/json-iterator/go-benchmark/blob/master/src/github.com/json-iterator/go-benchmark/benchmark_medium_payload_test.go + +Raw Result (easyjson requires static code generation) + +| | ns/op | allocation bytes | allocation times | +| --- | --- | --- | --- | +| std decode | 35510 ns/op | 1960 B/op | 99 allocs/op | +| easyjson decode | 8499 ns/op | 160 B/op | 4 allocs/op | +| jsoniter decode | 5623 ns/op | 160 B/op | 3 allocs/op | +| std encode | 2213 ns/op | 712 B/op | 5 allocs/op | +| easyjson encode | 883 ns/op | 576 B/op | 3 allocs/op | +| jsoniter encode | 837 ns/op | 384 B/op | 4 allocs/op | + +Always benchmark with your own workload. +The result depends heavily on the data input. + +# Usage + +100% compatibility with standard lib + +Replace + +```go +import "encoding/json" +json.Marshal(&data) +``` + +with + +```go +import "github.com/json-iterator/go" + +var json = jsoniter.ConfigCompatibleWithStandardLibrary +json.Marshal(&data) +``` + +Replace + +```go +import "encoding/json" +json.Unmarshal(input, &data) +``` + +with + +```go +import "github.com/json-iterator/go" + +var json = jsoniter.ConfigCompatibleWithStandardLibrary +json.Unmarshal(input, &data) +``` + +[More documentation](http://jsoniter.com/migrate-from-go-std.html) + +# How to get + +``` +go get github.com/json-iterator/go +``` + +# Contribution Welcomed ! + +Contributors + +* [thockin](https://github.com/thockin) +* [mattn](https://github.com/mattn) +* [cch123](https://github.com/cch123) +* [Oleg Shaldybin](https://github.com/olegshaldybin) +* [Jason Toffaletti](https://github.com/toffaletti) + +Report issue or pull request, or email taowen@gmail.com, or [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/json-iterator/Lobby) diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/adapter.go b/go/src/themaru/vendor/github.com/json-iterator/go/adapter.go new file mode 100644 index 0000000..e674d0f --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/adapter.go @@ -0,0 +1,150 @@ +package jsoniter + +import ( + "bytes" + "io" +) + +// RawMessage to make replace json with jsoniter +type RawMessage []byte + +// Unmarshal adapts to json/encoding Unmarshal API +// +// Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v. +// Refer to https://godoc.org/encoding/json#Unmarshal for more information +func Unmarshal(data []byte, v interface{}) error { + return ConfigDefault.Unmarshal(data, v) +} + +// UnmarshalFromString convenient method to read from string instead of []byte +func UnmarshalFromString(str string, v interface{}) error { + return ConfigDefault.UnmarshalFromString(str, v) +} + +// Get quick method to get value from deeply nested JSON structure +func Get(data []byte, path ...interface{}) Any { + return ConfigDefault.Get(data, path...) +} + +// Marshal adapts to json/encoding Marshal API +// +// Marshal returns the JSON encoding of v, adapts to json/encoding Marshal API +// Refer to https://godoc.org/encoding/json#Marshal for more information +func Marshal(v interface{}) ([]byte, error) { + return ConfigDefault.Marshal(v) +} + +// MarshalIndent same as json.MarshalIndent. Prefix is not supported. +func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { + return ConfigDefault.MarshalIndent(v, prefix, indent) +} + +// MarshalToString convenient method to write as string instead of []byte +func MarshalToString(v interface{}) (string, error) { + return ConfigDefault.MarshalToString(v) +} + +// NewDecoder adapts to json/stream NewDecoder API. +// +// NewDecoder returns a new decoder that reads from r. +// +// Instead of a json/encoding Decoder, an Decoder is returned +// Refer to https://godoc.org/encoding/json#NewDecoder for more information +func NewDecoder(reader io.Reader) *Decoder { + return ConfigDefault.NewDecoder(reader) +} + +// Decoder reads and decodes JSON values from an input stream. +// Decoder provides identical APIs with json/stream Decoder (Token() and UseNumber() are in progress) +type Decoder struct { + iter *Iterator +} + +// Decode decode JSON into interface{} +func (adapter *Decoder) Decode(obj interface{}) error { + if adapter.iter.head == adapter.iter.tail && adapter.iter.reader != nil { + if !adapter.iter.loadMore() { + return io.EOF + } + } + adapter.iter.ReadVal(obj) + err := adapter.iter.Error + if err == io.EOF { + return nil + } + return adapter.iter.Error +} + +// More is there more? +func (adapter *Decoder) More() bool { + iter := adapter.iter + if iter.Error != nil { + return false + } + c := iter.nextToken() + if c == 0 { + return false + } + iter.unreadByte() + return c != ']' && c != '}' +} + +// Buffered remaining buffer +func (adapter *Decoder) Buffered() io.Reader { + remaining := adapter.iter.buf[adapter.iter.head:adapter.iter.tail] + return bytes.NewReader(remaining) +} + +// UseNumber causes the Decoder to unmarshal a number into an interface{} as a +// Number instead of as a float64. +func (adapter *Decoder) UseNumber() { + cfg := adapter.iter.cfg.configBeforeFrozen + cfg.UseNumber = true + adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg.extraExtensions) +} + +// DisallowUnknownFields causes the Decoder to return an error when the destination +// is a struct and the input contains object keys which do not match any +// non-ignored, exported fields in the destination. +func (adapter *Decoder) DisallowUnknownFields() { + cfg := adapter.iter.cfg.configBeforeFrozen + cfg.DisallowUnknownFields = true + adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg.extraExtensions) +} + +// NewEncoder same as json.NewEncoder +func NewEncoder(writer io.Writer) *Encoder { + return ConfigDefault.NewEncoder(writer) +} + +// Encoder same as json.Encoder +type Encoder struct { + stream *Stream +} + +// Encode encode interface{} as JSON to io.Writer +func (adapter *Encoder) Encode(val interface{}) error { + adapter.stream.WriteVal(val) + adapter.stream.WriteRaw("\n") + adapter.stream.Flush() + return adapter.stream.Error +} + +// SetIndent set the indention. Prefix is not supported +func (adapter *Encoder) SetIndent(prefix, indent string) { + config := adapter.stream.cfg.configBeforeFrozen + config.IndentionStep = len(indent) + adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg.extraExtensions) +} + +// SetEscapeHTML escape html by default, set to false to disable +func (adapter *Encoder) SetEscapeHTML(escapeHTML bool) { + config := adapter.stream.cfg.configBeforeFrozen + config.EscapeHTML = escapeHTML + adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg.extraExtensions) +} + +// Valid reports whether data is a valid JSON encoding. +func Valid(data []byte) bool { + return ConfigDefault.Valid(data) +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/any.go b/go/src/themaru/vendor/github.com/json-iterator/go/any.go new file mode 100644 index 0000000..f6b8aea --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/any.go @@ -0,0 +1,325 @@ +package jsoniter + +import ( + "errors" + "fmt" + "github.com/modern-go/reflect2" + "io" + "reflect" + "strconv" + "unsafe" +) + +// Any generic object representation. +// The lazy json implementation holds []byte and parse lazily. +type Any interface { + LastError() error + ValueType() ValueType + MustBeValid() Any + ToBool() bool + ToInt() int + ToInt32() int32 + ToInt64() int64 + ToUint() uint + ToUint32() uint32 + ToUint64() uint64 + ToFloat32() float32 + ToFloat64() float64 + ToString() string + ToVal(val interface{}) + Get(path ...interface{}) Any + Size() int + Keys() []string + GetInterface() interface{} + WriteTo(stream *Stream) +} + +type baseAny struct{} + +func (any *baseAny) Get(path ...interface{}) Any { + return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)} +} + +func (any *baseAny) Size() int { + return 0 +} + +func (any *baseAny) Keys() []string { + return []string{} +} + +func (any *baseAny) ToVal(obj interface{}) { + panic("not implemented") +} + +// WrapInt32 turn int32 into Any interface +func WrapInt32(val int32) Any { + return &int32Any{baseAny{}, val} +} + +// WrapInt64 turn int64 into Any interface +func WrapInt64(val int64) Any { + return &int64Any{baseAny{}, val} +} + +// WrapUint32 turn uint32 into Any interface +func WrapUint32(val uint32) Any { + return &uint32Any{baseAny{}, val} +} + +// WrapUint64 turn uint64 into Any interface +func WrapUint64(val uint64) Any { + return &uint64Any{baseAny{}, val} +} + +// WrapFloat64 turn float64 into Any interface +func WrapFloat64(val float64) Any { + return &floatAny{baseAny{}, val} +} + +// WrapString turn string into Any interface +func WrapString(val string) Any { + return &stringAny{baseAny{}, val} +} + +// Wrap turn a go object into Any interface +func Wrap(val interface{}) Any { + if val == nil { + return &nilAny{} + } + asAny, isAny := val.(Any) + if isAny { + return asAny + } + typ := reflect2.TypeOf(val) + switch typ.Kind() { + case reflect.Slice: + return wrapArray(val) + case reflect.Struct: + return wrapStruct(val) + case reflect.Map: + return wrapMap(val) + case reflect.String: + return WrapString(val.(string)) + case reflect.Int: + if strconv.IntSize == 32 { + return WrapInt32(int32(val.(int))) + } + return WrapInt64(int64(val.(int))) + case reflect.Int8: + return WrapInt32(int32(val.(int8))) + case reflect.Int16: + return WrapInt32(int32(val.(int16))) + case reflect.Int32: + return WrapInt32(val.(int32)) + case reflect.Int64: + return WrapInt64(val.(int64)) + case reflect.Uint: + if strconv.IntSize == 32 { + return WrapUint32(uint32(val.(uint))) + } + return WrapUint64(uint64(val.(uint))) + case reflect.Uintptr: + if ptrSize == 32 { + return WrapUint32(uint32(val.(uintptr))) + } + return WrapUint64(uint64(val.(uintptr))) + case reflect.Uint8: + return WrapUint32(uint32(val.(uint8))) + case reflect.Uint16: + return WrapUint32(uint32(val.(uint16))) + case reflect.Uint32: + return WrapUint32(uint32(val.(uint32))) + case reflect.Uint64: + return WrapUint64(val.(uint64)) + case reflect.Float32: + return WrapFloat64(float64(val.(float32))) + case reflect.Float64: + return WrapFloat64(val.(float64)) + case reflect.Bool: + if val.(bool) == true { + return &trueAny{} + } + return &falseAny{} + } + return &invalidAny{baseAny{}, fmt.Errorf("unsupported type: %v", typ)} +} + +// ReadAny read next JSON element as an Any object. It is a better json.RawMessage. +func (iter *Iterator) ReadAny() Any { + return iter.readAny() +} + +func (iter *Iterator) readAny() Any { + c := iter.nextToken() + switch c { + case '"': + iter.unreadByte() + return &stringAny{baseAny{}, iter.ReadString()} + case 'n': + iter.skipThreeBytes('u', 'l', 'l') // null + return &nilAny{} + case 't': + iter.skipThreeBytes('r', 'u', 'e') // true + return &trueAny{} + case 'f': + iter.skipFourBytes('a', 'l', 's', 'e') // false + return &falseAny{} + case '{': + return iter.readObjectAny() + case '[': + return iter.readArrayAny() + case '-': + return iter.readNumberAny(false) + case 0: + return &invalidAny{baseAny{}, errors.New("input is empty")} + default: + return iter.readNumberAny(true) + } +} + +func (iter *Iterator) readNumberAny(positive bool) Any { + iter.startCapture(iter.head - 1) + iter.skipNumber() + lazyBuf := iter.stopCapture() + return &numberLazyAny{baseAny{}, iter.cfg, lazyBuf, nil} +} + +func (iter *Iterator) readObjectAny() Any { + iter.startCapture(iter.head - 1) + iter.skipObject() + lazyBuf := iter.stopCapture() + return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil} +} + +func (iter *Iterator) readArrayAny() Any { + iter.startCapture(iter.head - 1) + iter.skipArray() + lazyBuf := iter.stopCapture() + return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil} +} + +func locateObjectField(iter *Iterator, target string) []byte { + var found []byte + iter.ReadObjectCB(func(iter *Iterator, field string) bool { + if field == target { + found = iter.SkipAndReturnBytes() + return false + } + iter.Skip() + return true + }) + return found +} + +func locateArrayElement(iter *Iterator, target int) []byte { + var found []byte + n := 0 + iter.ReadArrayCB(func(iter *Iterator) bool { + if n == target { + found = iter.SkipAndReturnBytes() + return false + } + iter.Skip() + n++ + return true + }) + return found +} + +func locatePath(iter *Iterator, path []interface{}) Any { + for i, pathKeyObj := range path { + switch pathKey := pathKeyObj.(type) { + case string: + valueBytes := locateObjectField(iter, pathKey) + if valueBytes == nil { + return newInvalidAny(path[i:]) + } + iter.ResetBytes(valueBytes) + case int: + valueBytes := locateArrayElement(iter, pathKey) + if valueBytes == nil { + return newInvalidAny(path[i:]) + } + iter.ResetBytes(valueBytes) + case int32: + if '*' == pathKey { + return iter.readAny().Get(path[i:]...) + } + return newInvalidAny(path[i:]) + default: + return newInvalidAny(path[i:]) + } + } + if iter.Error != nil && iter.Error != io.EOF { + return &invalidAny{baseAny{}, iter.Error} + } + return iter.readAny() +} + +var anyType = reflect2.TypeOfPtr((*Any)(nil)).Elem() + +func createDecoderOfAny(ctx *ctx, typ reflect2.Type) ValDecoder { + if typ == anyType { + return &directAnyCodec{} + } + if typ.Implements(anyType) { + return &anyCodec{ + valType: typ, + } + } + return nil +} + +func createEncoderOfAny(ctx *ctx, typ reflect2.Type) ValEncoder { + if typ == anyType { + return &directAnyCodec{} + } + if typ.Implements(anyType) { + return &anyCodec{ + valType: typ, + } + } + return nil +} + +type anyCodec struct { + valType reflect2.Type +} + +func (codec *anyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + panic("not implemented") +} + +func (codec *anyCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + obj := codec.valType.UnsafeIndirect(ptr) + any := obj.(Any) + any.WriteTo(stream) +} + +func (codec *anyCodec) IsEmpty(ptr unsafe.Pointer) bool { + obj := codec.valType.UnsafeIndirect(ptr) + any := obj.(Any) + return any.Size() == 0 +} + +type directAnyCodec struct { +} + +func (codec *directAnyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + *(*Any)(ptr) = iter.readAny() +} + +func (codec *directAnyCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + any := *(*Any)(ptr) + if any == nil { + stream.WriteNil() + return + } + any.WriteTo(stream) +} + +func (codec *directAnyCodec) IsEmpty(ptr unsafe.Pointer) bool { + any := *(*Any)(ptr) + return any.Size() == 0 +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/any_array.go b/go/src/themaru/vendor/github.com/json-iterator/go/any_array.go new file mode 100644 index 0000000..0449e9a --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/any_array.go @@ -0,0 +1,278 @@ +package jsoniter + +import ( + "reflect" + "unsafe" +) + +type arrayLazyAny struct { + baseAny + cfg *frozenConfig + buf []byte + err error +} + +func (any *arrayLazyAny) ValueType() ValueType { + return ArrayValue +} + +func (any *arrayLazyAny) MustBeValid() Any { + return any +} + +func (any *arrayLazyAny) LastError() error { + return any.err +} + +func (any *arrayLazyAny) ToBool() bool { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + return iter.ReadArray() +} + +func (any *arrayLazyAny) ToInt() int { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToInt32() int32 { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToInt64() int64 { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToUint() uint { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToUint32() uint32 { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToUint64() uint64 { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToFloat32() float32 { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToFloat64() float64 { + if any.ToBool() { + return 1 + } + return 0 +} + +func (any *arrayLazyAny) ToString() string { + return *(*string)(unsafe.Pointer(&any.buf)) +} + +func (any *arrayLazyAny) ToVal(val interface{}) { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + iter.ReadVal(val) +} + +func (any *arrayLazyAny) Get(path ...interface{}) Any { + if len(path) == 0 { + return any + } + switch firstPath := path[0].(type) { + case int: + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + valueBytes := locateArrayElement(iter, firstPath) + if valueBytes == nil { + return newInvalidAny(path) + } + iter.ResetBytes(valueBytes) + return locatePath(iter, path[1:]) + case int32: + if '*' == firstPath { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + arr := make([]Any, 0) + iter.ReadArrayCB(func(iter *Iterator) bool { + found := iter.readAny().Get(path[1:]...) + if found.ValueType() != InvalidValue { + arr = append(arr, found) + } + return true + }) + return wrapArray(arr) + } + return newInvalidAny(path) + default: + return newInvalidAny(path) + } +} + +func (any *arrayLazyAny) Size() int { + size := 0 + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + iter.ReadArrayCB(func(iter *Iterator) bool { + size++ + iter.Skip() + return true + }) + return size +} + +func (any *arrayLazyAny) WriteTo(stream *Stream) { + stream.Write(any.buf) +} + +func (any *arrayLazyAny) GetInterface() interface{} { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + return iter.Read() +} + +type arrayAny struct { + baseAny + val reflect.Value +} + +func wrapArray(val interface{}) *arrayAny { + return &arrayAny{baseAny{}, reflect.ValueOf(val)} +} + +func (any *arrayAny) ValueType() ValueType { + return ArrayValue +} + +func (any *arrayAny) MustBeValid() Any { + return any +} + +func (any *arrayAny) LastError() error { + return nil +} + +func (any *arrayAny) ToBool() bool { + return any.val.Len() != 0 +} + +func (any *arrayAny) ToInt() int { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToInt32() int32 { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToInt64() int64 { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToUint() uint { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToUint32() uint32 { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToUint64() uint64 { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToFloat32() float32 { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToFloat64() float64 { + if any.val.Len() == 0 { + return 0 + } + return 1 +} + +func (any *arrayAny) ToString() string { + str, _ := MarshalToString(any.val.Interface()) + return str +} + +func (any *arrayAny) Get(path ...interface{}) Any { + if len(path) == 0 { + return any + } + switch firstPath := path[0].(type) { + case int: + if firstPath < 0 || firstPath >= any.val.Len() { + return newInvalidAny(path) + } + return Wrap(any.val.Index(firstPath).Interface()) + case int32: + if '*' == firstPath { + mappedAll := make([]Any, 0) + for i := 0; i < any.val.Len(); i++ { + mapped := Wrap(any.val.Index(i).Interface()).Get(path[1:]...) + if mapped.ValueType() != InvalidValue { + mappedAll = append(mappedAll, mapped) + } + } + return wrapArray(mappedAll) + } + return newInvalidAny(path) + default: + return newInvalidAny(path) + } +} + +func (any *arrayAny) Size() int { + return any.val.Len() +} + +func (any *arrayAny) WriteTo(stream *Stream) { + stream.WriteVal(any.val) +} + +func (any *arrayAny) GetInterface() interface{} { + return any.val.Interface() +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/any_bool.go b/go/src/themaru/vendor/github.com/json-iterator/go/any_bool.go new file mode 100644 index 0000000..9452324 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/any_bool.go @@ -0,0 +1,137 @@ +package jsoniter + +type trueAny struct { + baseAny +} + +func (any *trueAny) LastError() error { + return nil +} + +func (any *trueAny) ToBool() bool { + return true +} + +func (any *trueAny) ToInt() int { + return 1 +} + +func (any *trueAny) ToInt32() int32 { + return 1 +} + +func (any *trueAny) ToInt64() int64 { + return 1 +} + +func (any *trueAny) ToUint() uint { + return 1 +} + +func (any *trueAny) ToUint32() uint32 { + return 1 +} + +func (any *trueAny) ToUint64() uint64 { + return 1 +} + +func (any *trueAny) ToFloat32() float32 { + return 1 +} + +func (any *trueAny) ToFloat64() float64 { + return 1 +} + +func (any *trueAny) ToString() string { + return "true" +} + +func (any *trueAny) WriteTo(stream *Stream) { + stream.WriteTrue() +} + +func (any *trueAny) Parse() *Iterator { + return nil +} + +func (any *trueAny) GetInterface() interface{} { + return true +} + +func (any *trueAny) ValueType() ValueType { + return BoolValue +} + +func (any *trueAny) MustBeValid() Any { + return any +} + +type falseAny struct { + baseAny +} + +func (any *falseAny) LastError() error { + return nil +} + +func (any *falseAny) ToBool() bool { + return false +} + +func (any *falseAny) ToInt() int { + return 0 +} + +func (any *falseAny) ToInt32() int32 { + return 0 +} + +func (any *falseAny) ToInt64() int64 { + return 0 +} + +func (any *falseAny) ToUint() uint { + return 0 +} + +func (any *falseAny) ToUint32() uint32 { + return 0 +} + +func (any *falseAny) ToUint64() uint64 { + return 0 +} + +func (any *falseAny) ToFloat32() float32 { + return 0 +} + +func (any *falseAny) ToFloat64() float64 { + return 0 +} + +func (any *falseAny) ToString() string { + return "false" +} + +func (any *falseAny) WriteTo(stream *Stream) { + stream.WriteFalse() +} + +func (any *falseAny) Parse() *Iterator { + return nil +} + +func (any *falseAny) GetInterface() interface{} { + return false +} + +func (any *falseAny) ValueType() ValueType { + return BoolValue +} + +func (any *falseAny) MustBeValid() Any { + return any +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/any_float.go b/go/src/themaru/vendor/github.com/json-iterator/go/any_float.go new file mode 100644 index 0000000..35fdb09 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/any_float.go @@ -0,0 +1,83 @@ +package jsoniter + +import ( + "strconv" +) + +type floatAny struct { + baseAny + val float64 +} + +func (any *floatAny) Parse() *Iterator { + return nil +} + +func (any *floatAny) ValueType() ValueType { + return NumberValue +} + +func (any *floatAny) MustBeValid() Any { + return any +} + +func (any *floatAny) LastError() error { + return nil +} + +func (any *floatAny) ToBool() bool { + return any.ToFloat64() != 0 +} + +func (any *floatAny) ToInt() int { + return int(any.val) +} + +func (any *floatAny) ToInt32() int32 { + return int32(any.val) +} + +func (any *floatAny) ToInt64() int64 { + return int64(any.val) +} + +func (any *floatAny) ToUint() uint { + if any.val > 0 { + return uint(any.val) + } + return 0 +} + +func (any *floatAny) ToUint32() uint32 { + if any.val > 0 { + return uint32(any.val) + } + return 0 +} + +func (any *floatAny) ToUint64() uint64 { + if any.val > 0 { + return uint64(any.val) + } + return 0 +} + +func (any *floatAny) ToFloat32() float32 { + return float32(any.val) +} + +func (any *floatAny) ToFloat64() float64 { + return any.val +} + +func (any *floatAny) ToString() string { + return strconv.FormatFloat(any.val, 'E', -1, 64) +} + +func (any *floatAny) WriteTo(stream *Stream) { + stream.WriteFloat64(any.val) +} + +func (any *floatAny) GetInterface() interface{} { + return any.val +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/any_int32.go b/go/src/themaru/vendor/github.com/json-iterator/go/any_int32.go new file mode 100644 index 0000000..1b56f39 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/any_int32.go @@ -0,0 +1,74 @@ +package jsoniter + +import ( + "strconv" +) + +type int32Any struct { + baseAny + val int32 +} + +func (any *int32Any) LastError() error { + return nil +} + +func (any *int32Any) ValueType() ValueType { + return NumberValue +} + +func (any *int32Any) MustBeValid() Any { + return any +} + +func (any *int32Any) ToBool() bool { + return any.val != 0 +} + +func (any *int32Any) ToInt() int { + return int(any.val) +} + +func (any *int32Any) ToInt32() int32 { + return any.val +} + +func (any *int32Any) ToInt64() int64 { + return int64(any.val) +} + +func (any *int32Any) ToUint() uint { + return uint(any.val) +} + +func (any *int32Any) ToUint32() uint32 { + return uint32(any.val) +} + +func (any *int32Any) ToUint64() uint64 { + return uint64(any.val) +} + +func (any *int32Any) ToFloat32() float32 { + return float32(any.val) +} + +func (any *int32Any) ToFloat64() float64 { + return float64(any.val) +} + +func (any *int32Any) ToString() string { + return strconv.FormatInt(int64(any.val), 10) +} + +func (any *int32Any) WriteTo(stream *Stream) { + stream.WriteInt32(any.val) +} + +func (any *int32Any) Parse() *Iterator { + return nil +} + +func (any *int32Any) GetInterface() interface{} { + return any.val +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/any_int64.go b/go/src/themaru/vendor/github.com/json-iterator/go/any_int64.go new file mode 100644 index 0000000..c440d72 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/any_int64.go @@ -0,0 +1,74 @@ +package jsoniter + +import ( + "strconv" +) + +type int64Any struct { + baseAny + val int64 +} + +func (any *int64Any) LastError() error { + return nil +} + +func (any *int64Any) ValueType() ValueType { + return NumberValue +} + +func (any *int64Any) MustBeValid() Any { + return any +} + +func (any *int64Any) ToBool() bool { + return any.val != 0 +} + +func (any *int64Any) ToInt() int { + return int(any.val) +} + +func (any *int64Any) ToInt32() int32 { + return int32(any.val) +} + +func (any *int64Any) ToInt64() int64 { + return any.val +} + +func (any *int64Any) ToUint() uint { + return uint(any.val) +} + +func (any *int64Any) ToUint32() uint32 { + return uint32(any.val) +} + +func (any *int64Any) ToUint64() uint64 { + return uint64(any.val) +} + +func (any *int64Any) ToFloat32() float32 { + return float32(any.val) +} + +func (any *int64Any) ToFloat64() float64 { + return float64(any.val) +} + +func (any *int64Any) ToString() string { + return strconv.FormatInt(any.val, 10) +} + +func (any *int64Any) WriteTo(stream *Stream) { + stream.WriteInt64(any.val) +} + +func (any *int64Any) Parse() *Iterator { + return nil +} + +func (any *int64Any) GetInterface() interface{} { + return any.val +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/any_invalid.go b/go/src/themaru/vendor/github.com/json-iterator/go/any_invalid.go new file mode 100644 index 0000000..1d859ea --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/any_invalid.go @@ -0,0 +1,82 @@ +package jsoniter + +import "fmt" + +type invalidAny struct { + baseAny + err error +} + +func newInvalidAny(path []interface{}) *invalidAny { + return &invalidAny{baseAny{}, fmt.Errorf("%v not found", path)} +} + +func (any *invalidAny) LastError() error { + return any.err +} + +func (any *invalidAny) ValueType() ValueType { + return InvalidValue +} + +func (any *invalidAny) MustBeValid() Any { + panic(any.err) +} + +func (any *invalidAny) ToBool() bool { + return false +} + +func (any *invalidAny) ToInt() int { + return 0 +} + +func (any *invalidAny) ToInt32() int32 { + return 0 +} + +func (any *invalidAny) ToInt64() int64 { + return 0 +} + +func (any *invalidAny) ToUint() uint { + return 0 +} + +func (any *invalidAny) ToUint32() uint32 { + return 0 +} + +func (any *invalidAny) ToUint64() uint64 { + return 0 +} + +func (any *invalidAny) ToFloat32() float32 { + return 0 +} + +func (any *invalidAny) ToFloat64() float64 { + return 0 +} + +func (any *invalidAny) ToString() string { + return "" +} + +func (any *invalidAny) WriteTo(stream *Stream) { +} + +func (any *invalidAny) Get(path ...interface{}) Any { + if any.err == nil { + return &invalidAny{baseAny{}, fmt.Errorf("get %v from invalid", path)} + } + return &invalidAny{baseAny{}, fmt.Errorf("%v, get %v from invalid", any.err, path)} +} + +func (any *invalidAny) Parse() *Iterator { + return nil +} + +func (any *invalidAny) GetInterface() interface{} { + return nil +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/any_nil.go b/go/src/themaru/vendor/github.com/json-iterator/go/any_nil.go new file mode 100644 index 0000000..d04cb54 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/any_nil.go @@ -0,0 +1,69 @@ +package jsoniter + +type nilAny struct { + baseAny +} + +func (any *nilAny) LastError() error { + return nil +} + +func (any *nilAny) ValueType() ValueType { + return NilValue +} + +func (any *nilAny) MustBeValid() Any { + return any +} + +func (any *nilAny) ToBool() bool { + return false +} + +func (any *nilAny) ToInt() int { + return 0 +} + +func (any *nilAny) ToInt32() int32 { + return 0 +} + +func (any *nilAny) ToInt64() int64 { + return 0 +} + +func (any *nilAny) ToUint() uint { + return 0 +} + +func (any *nilAny) ToUint32() uint32 { + return 0 +} + +func (any *nilAny) ToUint64() uint64 { + return 0 +} + +func (any *nilAny) ToFloat32() float32 { + return 0 +} + +func (any *nilAny) ToFloat64() float64 { + return 0 +} + +func (any *nilAny) ToString() string { + return "" +} + +func (any *nilAny) WriteTo(stream *Stream) { + stream.WriteNil() +} + +func (any *nilAny) Parse() *Iterator { + return nil +} + +func (any *nilAny) GetInterface() interface{} { + return nil +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/any_number.go b/go/src/themaru/vendor/github.com/json-iterator/go/any_number.go new file mode 100644 index 0000000..9d1e901 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/any_number.go @@ -0,0 +1,123 @@ +package jsoniter + +import ( + "io" + "unsafe" +) + +type numberLazyAny struct { + baseAny + cfg *frozenConfig + buf []byte + err error +} + +func (any *numberLazyAny) ValueType() ValueType { + return NumberValue +} + +func (any *numberLazyAny) MustBeValid() Any { + return any +} + +func (any *numberLazyAny) LastError() error { + return any.err +} + +func (any *numberLazyAny) ToBool() bool { + return any.ToFloat64() != 0 +} + +func (any *numberLazyAny) ToInt() int { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadInt() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToInt32() int32 { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadInt32() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToInt64() int64 { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadInt64() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToUint() uint { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadUint() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToUint32() uint32 { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadUint32() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToUint64() uint64 { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadUint64() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToFloat32() float32 { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadFloat32() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToFloat64() float64 { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + val := iter.ReadFloat64() + if iter.Error != nil && iter.Error != io.EOF { + any.err = iter.Error + } + return val +} + +func (any *numberLazyAny) ToString() string { + return *(*string)(unsafe.Pointer(&any.buf)) +} + +func (any *numberLazyAny) WriteTo(stream *Stream) { + stream.Write(any.buf) +} + +func (any *numberLazyAny) GetInterface() interface{} { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + return iter.Read() +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/any_object.go b/go/src/themaru/vendor/github.com/json-iterator/go/any_object.go new file mode 100644 index 0000000..c44ef5c --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/any_object.go @@ -0,0 +1,374 @@ +package jsoniter + +import ( + "reflect" + "unsafe" +) + +type objectLazyAny struct { + baseAny + cfg *frozenConfig + buf []byte + err error +} + +func (any *objectLazyAny) ValueType() ValueType { + return ObjectValue +} + +func (any *objectLazyAny) MustBeValid() Any { + return any +} + +func (any *objectLazyAny) LastError() error { + return any.err +} + +func (any *objectLazyAny) ToBool() bool { + return true +} + +func (any *objectLazyAny) ToInt() int { + return 0 +} + +func (any *objectLazyAny) ToInt32() int32 { + return 0 +} + +func (any *objectLazyAny) ToInt64() int64 { + return 0 +} + +func (any *objectLazyAny) ToUint() uint { + return 0 +} + +func (any *objectLazyAny) ToUint32() uint32 { + return 0 +} + +func (any *objectLazyAny) ToUint64() uint64 { + return 0 +} + +func (any *objectLazyAny) ToFloat32() float32 { + return 0 +} + +func (any *objectLazyAny) ToFloat64() float64 { + return 0 +} + +func (any *objectLazyAny) ToString() string { + return *(*string)(unsafe.Pointer(&any.buf)) +} + +func (any *objectLazyAny) ToVal(obj interface{}) { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + iter.ReadVal(obj) +} + +func (any *objectLazyAny) Get(path ...interface{}) Any { + if len(path) == 0 { + return any + } + switch firstPath := path[0].(type) { + case string: + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + valueBytes := locateObjectField(iter, firstPath) + if valueBytes == nil { + return newInvalidAny(path) + } + iter.ResetBytes(valueBytes) + return locatePath(iter, path[1:]) + case int32: + if '*' == firstPath { + mappedAll := map[string]Any{} + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + iter.ReadMapCB(func(iter *Iterator, field string) bool { + mapped := locatePath(iter, path[1:]) + if mapped.ValueType() != InvalidValue { + mappedAll[field] = mapped + } + return true + }) + return wrapMap(mappedAll) + } + return newInvalidAny(path) + default: + return newInvalidAny(path) + } +} + +func (any *objectLazyAny) Keys() []string { + keys := []string{} + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + iter.ReadMapCB(func(iter *Iterator, field string) bool { + iter.Skip() + keys = append(keys, field) + return true + }) + return keys +} + +func (any *objectLazyAny) Size() int { + size := 0 + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + iter.ReadObjectCB(func(iter *Iterator, field string) bool { + iter.Skip() + size++ + return true + }) + return size +} + +func (any *objectLazyAny) WriteTo(stream *Stream) { + stream.Write(any.buf) +} + +func (any *objectLazyAny) GetInterface() interface{} { + iter := any.cfg.BorrowIterator(any.buf) + defer any.cfg.ReturnIterator(iter) + return iter.Read() +} + +type objectAny struct { + baseAny + err error + val reflect.Value +} + +func wrapStruct(val interface{}) *objectAny { + return &objectAny{baseAny{}, nil, reflect.ValueOf(val)} +} + +func (any *objectAny) ValueType() ValueType { + return ObjectValue +} + +func (any *objectAny) MustBeValid() Any { + return any +} + +func (any *objectAny) Parse() *Iterator { + return nil +} + +func (any *objectAny) LastError() error { + return any.err +} + +func (any *objectAny) ToBool() bool { + return any.val.NumField() != 0 +} + +func (any *objectAny) ToInt() int { + return 0 +} + +func (any *objectAny) ToInt32() int32 { + return 0 +} + +func (any *objectAny) ToInt64() int64 { + return 0 +} + +func (any *objectAny) ToUint() uint { + return 0 +} + +func (any *objectAny) ToUint32() uint32 { + return 0 +} + +func (any *objectAny) ToUint64() uint64 { + return 0 +} + +func (any *objectAny) ToFloat32() float32 { + return 0 +} + +func (any *objectAny) ToFloat64() float64 { + return 0 +} + +func (any *objectAny) ToString() string { + str, err := MarshalToString(any.val.Interface()) + any.err = err + return str +} + +func (any *objectAny) Get(path ...interface{}) Any { + if len(path) == 0 { + return any + } + switch firstPath := path[0].(type) { + case string: + field := any.val.FieldByName(firstPath) + if !field.IsValid() { + return newInvalidAny(path) + } + return Wrap(field.Interface()) + case int32: + if '*' == firstPath { + mappedAll := map[string]Any{} + for i := 0; i < any.val.NumField(); i++ { + field := any.val.Field(i) + if field.CanInterface() { + mapped := Wrap(field.Interface()).Get(path[1:]...) + if mapped.ValueType() != InvalidValue { + mappedAll[any.val.Type().Field(i).Name] = mapped + } + } + } + return wrapMap(mappedAll) + } + return newInvalidAny(path) + default: + return newInvalidAny(path) + } +} + +func (any *objectAny) Keys() []string { + keys := make([]string, 0, any.val.NumField()) + for i := 0; i < any.val.NumField(); i++ { + keys = append(keys, any.val.Type().Field(i).Name) + } + return keys +} + +func (any *objectAny) Size() int { + return any.val.NumField() +} + +func (any *objectAny) WriteTo(stream *Stream) { + stream.WriteVal(any.val) +} + +func (any *objectAny) GetInterface() interface{} { + return any.val.Interface() +} + +type mapAny struct { + baseAny + err error + val reflect.Value +} + +func wrapMap(val interface{}) *mapAny { + return &mapAny{baseAny{}, nil, reflect.ValueOf(val)} +} + +func (any *mapAny) ValueType() ValueType { + return ObjectValue +} + +func (any *mapAny) MustBeValid() Any { + return any +} + +func (any *mapAny) Parse() *Iterator { + return nil +} + +func (any *mapAny) LastError() error { + return any.err +} + +func (any *mapAny) ToBool() bool { + return true +} + +func (any *mapAny) ToInt() int { + return 0 +} + +func (any *mapAny) ToInt32() int32 { + return 0 +} + +func (any *mapAny) ToInt64() int64 { + return 0 +} + +func (any *mapAny) ToUint() uint { + return 0 +} + +func (any *mapAny) ToUint32() uint32 { + return 0 +} + +func (any *mapAny) ToUint64() uint64 { + return 0 +} + +func (any *mapAny) ToFloat32() float32 { + return 0 +} + +func (any *mapAny) ToFloat64() float64 { + return 0 +} + +func (any *mapAny) ToString() string { + str, err := MarshalToString(any.val.Interface()) + any.err = err + return str +} + +func (any *mapAny) Get(path ...interface{}) Any { + if len(path) == 0 { + return any + } + switch firstPath := path[0].(type) { + case int32: + if '*' == firstPath { + mappedAll := map[string]Any{} + for _, key := range any.val.MapKeys() { + keyAsStr := key.String() + element := Wrap(any.val.MapIndex(key).Interface()) + mapped := element.Get(path[1:]...) + if mapped.ValueType() != InvalidValue { + mappedAll[keyAsStr] = mapped + } + } + return wrapMap(mappedAll) + } + return newInvalidAny(path) + default: + value := any.val.MapIndex(reflect.ValueOf(firstPath)) + if !value.IsValid() { + return newInvalidAny(path) + } + return Wrap(value.Interface()) + } +} + +func (any *mapAny) Keys() []string { + keys := make([]string, 0, any.val.Len()) + for _, key := range any.val.MapKeys() { + keys = append(keys, key.String()) + } + return keys +} + +func (any *mapAny) Size() int { + return any.val.Len() +} + +func (any *mapAny) WriteTo(stream *Stream) { + stream.WriteVal(any.val) +} + +func (any *mapAny) GetInterface() interface{} { + return any.val.Interface() +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/any_str.go b/go/src/themaru/vendor/github.com/json-iterator/go/any_str.go new file mode 100644 index 0000000..a4b93c7 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/any_str.go @@ -0,0 +1,166 @@ +package jsoniter + +import ( + "fmt" + "strconv" +) + +type stringAny struct { + baseAny + val string +} + +func (any *stringAny) Get(path ...interface{}) Any { + if len(path) == 0 { + return any + } + return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)} +} + +func (any *stringAny) Parse() *Iterator { + return nil +} + +func (any *stringAny) ValueType() ValueType { + return StringValue +} + +func (any *stringAny) MustBeValid() Any { + return any +} + +func (any *stringAny) LastError() error { + return nil +} + +func (any *stringAny) ToBool() bool { + str := any.ToString() + if str == "0" { + return false + } + for _, c := range str { + switch c { + case ' ', '\n', '\r', '\t': + default: + return true + } + } + return false +} + +func (any *stringAny) ToInt() int { + return int(any.ToInt64()) + +} + +func (any *stringAny) ToInt32() int32 { + return int32(any.ToInt64()) +} + +func (any *stringAny) ToInt64() int64 { + if any.val == "" { + return 0 + } + + flag := 1 + startPos := 0 + endPos := 0 + if any.val[0] == '+' || any.val[0] == '-' { + startPos = 1 + } + + if any.val[0] == '-' { + flag = -1 + } + + for i := startPos; i < len(any.val); i++ { + if any.val[i] >= '0' && any.val[i] <= '9' { + endPos = i + 1 + } else { + break + } + } + parsed, _ := strconv.ParseInt(any.val[startPos:endPos], 10, 64) + return int64(flag) * parsed +} + +func (any *stringAny) ToUint() uint { + return uint(any.ToUint64()) +} + +func (any *stringAny) ToUint32() uint32 { + return uint32(any.ToUint64()) +} + +func (any *stringAny) ToUint64() uint64 { + if any.val == "" { + return 0 + } + + startPos := 0 + endPos := 0 + + if any.val[0] == '-' { + return 0 + } + if any.val[0] == '+' { + startPos = 1 + } + + for i := startPos; i < len(any.val); i++ { + if any.val[i] >= '0' && any.val[i] <= '9' { + endPos = i + 1 + } else { + break + } + } + parsed, _ := strconv.ParseUint(any.val[startPos:endPos], 10, 64) + return parsed +} + +func (any *stringAny) ToFloat32() float32 { + return float32(any.ToFloat64()) +} + +func (any *stringAny) ToFloat64() float64 { + if len(any.val) == 0 { + return 0 + } + + // first char invalid + if any.val[0] != '+' && any.val[0] != '-' && (any.val[0] > '9' || any.val[0] < '0') { + return 0 + } + + // extract valid num expression from string + // eg 123true => 123, -12.12xxa => -12.12 + endPos := 1 + for i := 1; i < len(any.val); i++ { + if any.val[i] == '.' || any.val[i] == 'e' || any.val[i] == 'E' || any.val[i] == '+' || any.val[i] == '-' { + endPos = i + 1 + continue + } + + // end position is the first char which is not digit + if any.val[i] >= '0' && any.val[i] <= '9' { + endPos = i + 1 + } else { + endPos = i + break + } + } + parsed, _ := strconv.ParseFloat(any.val[:endPos], 64) + return parsed +} + +func (any *stringAny) ToString() string { + return any.val +} + +func (any *stringAny) WriteTo(stream *Stream) { + stream.WriteString(any.val) +} + +func (any *stringAny) GetInterface() interface{} { + return any.val +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/any_uint32.go b/go/src/themaru/vendor/github.com/json-iterator/go/any_uint32.go new file mode 100644 index 0000000..656bbd3 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/any_uint32.go @@ -0,0 +1,74 @@ +package jsoniter + +import ( + "strconv" +) + +type uint32Any struct { + baseAny + val uint32 +} + +func (any *uint32Any) LastError() error { + return nil +} + +func (any *uint32Any) ValueType() ValueType { + return NumberValue +} + +func (any *uint32Any) MustBeValid() Any { + return any +} + +func (any *uint32Any) ToBool() bool { + return any.val != 0 +} + +func (any *uint32Any) ToInt() int { + return int(any.val) +} + +func (any *uint32Any) ToInt32() int32 { + return int32(any.val) +} + +func (any *uint32Any) ToInt64() int64 { + return int64(any.val) +} + +func (any *uint32Any) ToUint() uint { + return uint(any.val) +} + +func (any *uint32Any) ToUint32() uint32 { + return any.val +} + +func (any *uint32Any) ToUint64() uint64 { + return uint64(any.val) +} + +func (any *uint32Any) ToFloat32() float32 { + return float32(any.val) +} + +func (any *uint32Any) ToFloat64() float64 { + return float64(any.val) +} + +func (any *uint32Any) ToString() string { + return strconv.FormatInt(int64(any.val), 10) +} + +func (any *uint32Any) WriteTo(stream *Stream) { + stream.WriteUint32(any.val) +} + +func (any *uint32Any) Parse() *Iterator { + return nil +} + +func (any *uint32Any) GetInterface() interface{} { + return any.val +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/any_uint64.go b/go/src/themaru/vendor/github.com/json-iterator/go/any_uint64.go new file mode 100644 index 0000000..7df2fce --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/any_uint64.go @@ -0,0 +1,74 @@ +package jsoniter + +import ( + "strconv" +) + +type uint64Any struct { + baseAny + val uint64 +} + +func (any *uint64Any) LastError() error { + return nil +} + +func (any *uint64Any) ValueType() ValueType { + return NumberValue +} + +func (any *uint64Any) MustBeValid() Any { + return any +} + +func (any *uint64Any) ToBool() bool { + return any.val != 0 +} + +func (any *uint64Any) ToInt() int { + return int(any.val) +} + +func (any *uint64Any) ToInt32() int32 { + return int32(any.val) +} + +func (any *uint64Any) ToInt64() int64 { + return int64(any.val) +} + +func (any *uint64Any) ToUint() uint { + return uint(any.val) +} + +func (any *uint64Any) ToUint32() uint32 { + return uint32(any.val) +} + +func (any *uint64Any) ToUint64() uint64 { + return any.val +} + +func (any *uint64Any) ToFloat32() float32 { + return float32(any.val) +} + +func (any *uint64Any) ToFloat64() float64 { + return float64(any.val) +} + +func (any *uint64Any) ToString() string { + return strconv.FormatUint(any.val, 10) +} + +func (any *uint64Any) WriteTo(stream *Stream) { + stream.WriteUint64(any.val) +} + +func (any *uint64Any) Parse() *Iterator { + return nil +} + +func (any *uint64Any) GetInterface() interface{} { + return any.val +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/build.sh b/go/src/themaru/vendor/github.com/json-iterator/go/build.sh new file mode 100755 index 0000000..b45ef68 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/build.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e +set -x + +if [ ! -d /tmp/build-golang/src/github.com/json-iterator ]; then + mkdir -p /tmp/build-golang/src/github.com/json-iterator + ln -s $PWD /tmp/build-golang/src/github.com/json-iterator/go +fi +export GOPATH=/tmp/build-golang +go get -u github.com/golang/dep/cmd/dep +cd /tmp/build-golang/src/github.com/json-iterator/go +exec $GOPATH/bin/dep ensure -update diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/config.go b/go/src/themaru/vendor/github.com/json-iterator/go/config.go new file mode 100644 index 0000000..8c58fcb --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/config.go @@ -0,0 +1,375 @@ +package jsoniter + +import ( + "encoding/json" + "io" + "reflect" + "sync" + "unsafe" + + "github.com/modern-go/concurrent" + "github.com/modern-go/reflect2" +) + +// Config customize how the API should behave. +// The API is created from Config by Froze. +type Config struct { + IndentionStep int + MarshalFloatWith6Digits bool + EscapeHTML bool + SortMapKeys bool + UseNumber bool + DisallowUnknownFields bool + TagKey string + OnlyTaggedField bool + ValidateJsonRawMessage bool + ObjectFieldMustBeSimpleString bool + CaseSensitive bool +} + +// API the public interface of this package. +// Primary Marshal and Unmarshal. +type API interface { + IteratorPool + StreamPool + MarshalToString(v interface{}) (string, error) + Marshal(v interface{}) ([]byte, error) + MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) + UnmarshalFromString(str string, v interface{}) error + Unmarshal(data []byte, v interface{}) error + Get(data []byte, path ...interface{}) Any + NewEncoder(writer io.Writer) *Encoder + NewDecoder(reader io.Reader) *Decoder + Valid(data []byte) bool + RegisterExtension(extension Extension) + DecoderOf(typ reflect2.Type) ValDecoder + EncoderOf(typ reflect2.Type) ValEncoder +} + +// ConfigDefault the default API +var ConfigDefault = Config{ + EscapeHTML: true, +}.Froze() + +// ConfigCompatibleWithStandardLibrary tries to be 100% compatible with standard library behavior +var ConfigCompatibleWithStandardLibrary = Config{ + EscapeHTML: true, + SortMapKeys: true, + ValidateJsonRawMessage: true, +}.Froze() + +// ConfigFastest marshals float with only 6 digits precision +var ConfigFastest = Config{ + EscapeHTML: false, + MarshalFloatWith6Digits: true, // will lose precession + ObjectFieldMustBeSimpleString: true, // do not unescape object field +}.Froze() + +type frozenConfig struct { + configBeforeFrozen Config + sortMapKeys bool + indentionStep int + objectFieldMustBeSimpleString bool + onlyTaggedField bool + disallowUnknownFields bool + decoderCache *concurrent.Map + encoderCache *concurrent.Map + encoderExtension Extension + decoderExtension Extension + extraExtensions []Extension + streamPool *sync.Pool + iteratorPool *sync.Pool + caseSensitive bool +} + +func (cfg *frozenConfig) initCache() { + cfg.decoderCache = concurrent.NewMap() + cfg.encoderCache = concurrent.NewMap() +} + +func (cfg *frozenConfig) addDecoderToCache(cacheKey uintptr, decoder ValDecoder) { + cfg.decoderCache.Store(cacheKey, decoder) +} + +func (cfg *frozenConfig) addEncoderToCache(cacheKey uintptr, encoder ValEncoder) { + cfg.encoderCache.Store(cacheKey, encoder) +} + +func (cfg *frozenConfig) getDecoderFromCache(cacheKey uintptr) ValDecoder { + decoder, found := cfg.decoderCache.Load(cacheKey) + if found { + return decoder.(ValDecoder) + } + return nil +} + +func (cfg *frozenConfig) getEncoderFromCache(cacheKey uintptr) ValEncoder { + encoder, found := cfg.encoderCache.Load(cacheKey) + if found { + return encoder.(ValEncoder) + } + return nil +} + +var cfgCache = concurrent.NewMap() + +func getFrozenConfigFromCache(cfg Config) *frozenConfig { + obj, found := cfgCache.Load(cfg) + if found { + return obj.(*frozenConfig) + } + return nil +} + +func addFrozenConfigToCache(cfg Config, frozenConfig *frozenConfig) { + cfgCache.Store(cfg, frozenConfig) +} + +// Froze forge API from config +func (cfg Config) Froze() API { + api := &frozenConfig{ + sortMapKeys: cfg.SortMapKeys, + indentionStep: cfg.IndentionStep, + objectFieldMustBeSimpleString: cfg.ObjectFieldMustBeSimpleString, + onlyTaggedField: cfg.OnlyTaggedField, + disallowUnknownFields: cfg.DisallowUnknownFields, + caseSensitive: cfg.CaseSensitive, + } + api.streamPool = &sync.Pool{ + New: func() interface{} { + return NewStream(api, nil, 512) + }, + } + api.iteratorPool = &sync.Pool{ + New: func() interface{} { + return NewIterator(api) + }, + } + api.initCache() + encoderExtension := EncoderExtension{} + decoderExtension := DecoderExtension{} + if cfg.MarshalFloatWith6Digits { + api.marshalFloatWith6Digits(encoderExtension) + } + if cfg.EscapeHTML { + api.escapeHTML(encoderExtension) + } + if cfg.UseNumber { + api.useNumber(decoderExtension) + } + if cfg.ValidateJsonRawMessage { + api.validateJsonRawMessage(encoderExtension) + } + api.encoderExtension = encoderExtension + api.decoderExtension = decoderExtension + api.configBeforeFrozen = cfg + return api +} + +func (cfg Config) frozeWithCacheReuse(extraExtensions []Extension) *frozenConfig { + api := getFrozenConfigFromCache(cfg) + if api != nil { + return api + } + api = cfg.Froze().(*frozenConfig) + for _, extension := range extraExtensions { + api.RegisterExtension(extension) + } + addFrozenConfigToCache(cfg, api) + return api +} + +func (cfg *frozenConfig) validateJsonRawMessage(extension EncoderExtension) { + encoder := &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) { + rawMessage := *(*json.RawMessage)(ptr) + iter := cfg.BorrowIterator([]byte(rawMessage)) + iter.Read() + if iter.Error != nil { + stream.WriteRaw("null") + } else { + cfg.ReturnIterator(iter) + stream.WriteRaw(string(rawMessage)) + } + }, func(ptr unsafe.Pointer) bool { + return len(*((*json.RawMessage)(ptr))) == 0 + }} + extension[reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem()] = encoder + extension[reflect2.TypeOfPtr((*RawMessage)(nil)).Elem()] = encoder +} + +func (cfg *frozenConfig) useNumber(extension DecoderExtension) { + extension[reflect2.TypeOfPtr((*interface{})(nil)).Elem()] = &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) { + exitingValue := *((*interface{})(ptr)) + if exitingValue != nil && reflect.TypeOf(exitingValue).Kind() == reflect.Ptr { + iter.ReadVal(exitingValue) + return + } + if iter.WhatIsNext() == NumberValue { + *((*interface{})(ptr)) = json.Number(iter.readNumberAsString()) + } else { + *((*interface{})(ptr)) = iter.Read() + } + }} +} +func (cfg *frozenConfig) getTagKey() string { + tagKey := cfg.configBeforeFrozen.TagKey + if tagKey == "" { + return "json" + } + return tagKey +} + +func (cfg *frozenConfig) RegisterExtension(extension Extension) { + cfg.extraExtensions = append(cfg.extraExtensions, extension) + copied := cfg.configBeforeFrozen + cfg.configBeforeFrozen = copied +} + +type lossyFloat32Encoder struct { +} + +func (encoder *lossyFloat32Encoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteFloat32Lossy(*((*float32)(ptr))) +} + +func (encoder *lossyFloat32Encoder) IsEmpty(ptr unsafe.Pointer) bool { + return *((*float32)(ptr)) == 0 +} + +type lossyFloat64Encoder struct { +} + +func (encoder *lossyFloat64Encoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteFloat64Lossy(*((*float64)(ptr))) +} + +func (encoder *lossyFloat64Encoder) IsEmpty(ptr unsafe.Pointer) bool { + return *((*float64)(ptr)) == 0 +} + +// EnableLossyFloatMarshalling keeps 10**(-6) precision +// for float variables for better performance. +func (cfg *frozenConfig) marshalFloatWith6Digits(extension EncoderExtension) { + // for better performance + extension[reflect2.TypeOfPtr((*float32)(nil)).Elem()] = &lossyFloat32Encoder{} + extension[reflect2.TypeOfPtr((*float64)(nil)).Elem()] = &lossyFloat64Encoder{} +} + +type htmlEscapedStringEncoder struct { +} + +func (encoder *htmlEscapedStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + str := *((*string)(ptr)) + stream.WriteStringWithHTMLEscaped(str) +} + +func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return *((*string)(ptr)) == "" +} + +func (cfg *frozenConfig) escapeHTML(encoderExtension EncoderExtension) { + encoderExtension[reflect2.TypeOfPtr((*string)(nil)).Elem()] = &htmlEscapedStringEncoder{} +} + +func (cfg *frozenConfig) cleanDecoders() { + typeDecoders = map[string]ValDecoder{} + fieldDecoders = map[string]ValDecoder{} + *cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig)) +} + +func (cfg *frozenConfig) cleanEncoders() { + typeEncoders = map[string]ValEncoder{} + fieldEncoders = map[string]ValEncoder{} + *cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig)) +} + +func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) { + stream := cfg.BorrowStream(nil) + defer cfg.ReturnStream(stream) + stream.WriteVal(v) + if stream.Error != nil { + return "", stream.Error + } + return string(stream.Buffer()), nil +} + +func (cfg *frozenConfig) Marshal(v interface{}) ([]byte, error) { + stream := cfg.BorrowStream(nil) + defer cfg.ReturnStream(stream) + stream.WriteVal(v) + if stream.Error != nil { + return nil, stream.Error + } + result := stream.Buffer() + copied := make([]byte, len(result)) + copy(copied, result) + return copied, nil +} + +func (cfg *frozenConfig) MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { + if prefix != "" { + panic("prefix is not supported") + } + for _, r := range indent { + if r != ' ' { + panic("indent can only be space") + } + } + newCfg := cfg.configBeforeFrozen + newCfg.IndentionStep = len(indent) + return newCfg.frozeWithCacheReuse(cfg.extraExtensions).Marshal(v) +} + +func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error { + data := []byte(str) + iter := cfg.BorrowIterator(data) + defer cfg.ReturnIterator(iter) + iter.ReadVal(v) + c := iter.nextToken() + if c == 0 { + if iter.Error == io.EOF { + return nil + } + return iter.Error + } + iter.ReportError("Unmarshal", "there are bytes left after unmarshal") + return iter.Error +} + +func (cfg *frozenConfig) Get(data []byte, path ...interface{}) Any { + iter := cfg.BorrowIterator(data) + defer cfg.ReturnIterator(iter) + return locatePath(iter, path) +} + +func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error { + iter := cfg.BorrowIterator(data) + defer cfg.ReturnIterator(iter) + iter.ReadVal(v) + c := iter.nextToken() + if c == 0 { + if iter.Error == io.EOF { + return nil + } + return iter.Error + } + iter.ReportError("Unmarshal", "there are bytes left after unmarshal") + return iter.Error +} + +func (cfg *frozenConfig) NewEncoder(writer io.Writer) *Encoder { + stream := NewStream(cfg, writer, 512) + return &Encoder{stream} +} + +func (cfg *frozenConfig) NewDecoder(reader io.Reader) *Decoder { + iter := Parse(cfg, reader, 512) + return &Decoder{iter} +} + +func (cfg *frozenConfig) Valid(data []byte) bool { + iter := cfg.BorrowIterator(data) + defer cfg.ReturnIterator(iter) + iter.Skip() + return iter.Error == nil +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/fuzzy_mode_convert_table.md b/go/src/themaru/vendor/github.com/json-iterator/go/fuzzy_mode_convert_table.md new file mode 100644 index 0000000..3095662 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/fuzzy_mode_convert_table.md @@ -0,0 +1,7 @@ +| json type \ dest type | bool | int | uint | float |string| +| --- | --- | --- | --- |--|--| +| number | positive => true
negative => true
zero => false| 23.2 => 23
-32.1 => -32| 12.1 => 12
-12.1 => 0|as normal|same as origin| +| string | empty string => false
string "0" => false
other strings => true | "123.32" => 123
"-123.4" => -123
"123.23xxxw" => 123
"abcde12" => 0
"-32.1" => -32| 13.2 => 13
-1.1 => 0 |12.1 => 12.1
-12.3 => -12.3
12.4xxa => 12.4
+1.1e2 =>110 |same as origin| +| bool | true => true
false => false| true => 1
false => 0 | true => 1
false => 0 |true => 1
false => 0|true => "true"
false => "false"| +| object | true | 0 | 0 |0|originnal json| +| array | empty array => false
nonempty array => true| [] => 0
[1,2] => 1 | [] => 0
[1,2] => 1 |[] => 0
[1,2] => 1|original json| \ No newline at end of file diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/iter.go b/go/src/themaru/vendor/github.com/json-iterator/go/iter.go new file mode 100644 index 0000000..95ae54f --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/iter.go @@ -0,0 +1,322 @@ +package jsoniter + +import ( + "encoding/json" + "fmt" + "io" +) + +// ValueType the type for JSON element +type ValueType int + +const ( + // InvalidValue invalid JSON element + InvalidValue ValueType = iota + // StringValue JSON element "string" + StringValue + // NumberValue JSON element 100 or 0.10 + NumberValue + // NilValue JSON element null + NilValue + // BoolValue JSON element true or false + BoolValue + // ArrayValue JSON element [] + ArrayValue + // ObjectValue JSON element {} + ObjectValue +) + +var hexDigits []byte +var valueTypes []ValueType + +func init() { + hexDigits = make([]byte, 256) + for i := 0; i < len(hexDigits); i++ { + hexDigits[i] = 255 + } + for i := '0'; i <= '9'; i++ { + hexDigits[i] = byte(i - '0') + } + for i := 'a'; i <= 'f'; i++ { + hexDigits[i] = byte((i - 'a') + 10) + } + for i := 'A'; i <= 'F'; i++ { + hexDigits[i] = byte((i - 'A') + 10) + } + valueTypes = make([]ValueType, 256) + for i := 0; i < len(valueTypes); i++ { + valueTypes[i] = InvalidValue + } + valueTypes['"'] = StringValue + valueTypes['-'] = NumberValue + valueTypes['0'] = NumberValue + valueTypes['1'] = NumberValue + valueTypes['2'] = NumberValue + valueTypes['3'] = NumberValue + valueTypes['4'] = NumberValue + valueTypes['5'] = NumberValue + valueTypes['6'] = NumberValue + valueTypes['7'] = NumberValue + valueTypes['8'] = NumberValue + valueTypes['9'] = NumberValue + valueTypes['t'] = BoolValue + valueTypes['f'] = BoolValue + valueTypes['n'] = NilValue + valueTypes['['] = ArrayValue + valueTypes['{'] = ObjectValue +} + +// Iterator is a io.Reader like object, with JSON specific read functions. +// Error is not returned as return value, but stored as Error member on this iterator instance. +type Iterator struct { + cfg *frozenConfig + reader io.Reader + buf []byte + head int + tail int + captureStartedAt int + captured []byte + Error error + Attachment interface{} // open for customized decoder +} + +// NewIterator creates an empty Iterator instance +func NewIterator(cfg API) *Iterator { + return &Iterator{ + cfg: cfg.(*frozenConfig), + reader: nil, + buf: nil, + head: 0, + tail: 0, + } +} + +// Parse creates an Iterator instance from io.Reader +func Parse(cfg API, reader io.Reader, bufSize int) *Iterator { + return &Iterator{ + cfg: cfg.(*frozenConfig), + reader: reader, + buf: make([]byte, bufSize), + head: 0, + tail: 0, + } +} + +// ParseBytes creates an Iterator instance from byte array +func ParseBytes(cfg API, input []byte) *Iterator { + return &Iterator{ + cfg: cfg.(*frozenConfig), + reader: nil, + buf: input, + head: 0, + tail: len(input), + } +} + +// ParseString creates an Iterator instance from string +func ParseString(cfg API, input string) *Iterator { + return ParseBytes(cfg, []byte(input)) +} + +// Pool returns a pool can provide more iterator with same configuration +func (iter *Iterator) Pool() IteratorPool { + return iter.cfg +} + +// Reset reuse iterator instance by specifying another reader +func (iter *Iterator) Reset(reader io.Reader) *Iterator { + iter.reader = reader + iter.head = 0 + iter.tail = 0 + return iter +} + +// ResetBytes reuse iterator instance by specifying another byte array as input +func (iter *Iterator) ResetBytes(input []byte) *Iterator { + iter.reader = nil + iter.buf = input + iter.head = 0 + iter.tail = len(input) + return iter +} + +// WhatIsNext gets ValueType of relatively next json element +func (iter *Iterator) WhatIsNext() ValueType { + valueType := valueTypes[iter.nextToken()] + iter.unreadByte() + return valueType +} + +func (iter *Iterator) skipWhitespacesWithoutLoadMore() bool { + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + switch c { + case ' ', '\n', '\t', '\r': + continue + } + iter.head = i + return false + } + return true +} + +func (iter *Iterator) isObjectEnd() bool { + c := iter.nextToken() + if c == ',' { + return false + } + if c == '}' { + return true + } + iter.ReportError("isObjectEnd", "object ended prematurely, unexpected char "+string([]byte{c})) + return true +} + +func (iter *Iterator) nextToken() byte { + // a variation of skip whitespaces, returning the next non-whitespace token + for { + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + switch c { + case ' ', '\n', '\t', '\r': + continue + } + iter.head = i + 1 + return c + } + if !iter.loadMore() { + return 0 + } + } +} + +// ReportError record a error in iterator instance with current position. +func (iter *Iterator) ReportError(operation string, msg string) { + if iter.Error != nil { + if iter.Error != io.EOF { + return + } + } + peekStart := iter.head - 10 + if peekStart < 0 { + peekStart = 0 + } + peekEnd := iter.head + 10 + if peekEnd > iter.tail { + peekEnd = iter.tail + } + parsing := string(iter.buf[peekStart:peekEnd]) + contextStart := iter.head - 50 + if contextStart < 0 { + contextStart = 0 + } + contextEnd := iter.head + 50 + if contextEnd > iter.tail { + contextEnd = iter.tail + } + context := string(iter.buf[contextStart:contextEnd]) + iter.Error = fmt.Errorf("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|...", + operation, msg, iter.head-peekStart, parsing, context) +} + +// CurrentBuffer gets current buffer as string for debugging purpose +func (iter *Iterator) CurrentBuffer() string { + peekStart := iter.head - 10 + if peekStart < 0 { + peekStart = 0 + } + return fmt.Sprintf("parsing #%v byte, around ...|%s|..., whole buffer ...|%s|...", iter.head, + string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail])) +} + +func (iter *Iterator) readByte() (ret byte) { + if iter.head == iter.tail { + if iter.loadMore() { + ret = iter.buf[iter.head] + iter.head++ + return ret + } + return 0 + } + ret = iter.buf[iter.head] + iter.head++ + return ret +} + +func (iter *Iterator) loadMore() bool { + if iter.reader == nil { + if iter.Error == nil { + iter.head = iter.tail + iter.Error = io.EOF + } + return false + } + if iter.captured != nil { + iter.captured = append(iter.captured, + iter.buf[iter.captureStartedAt:iter.tail]...) + iter.captureStartedAt = 0 + } + for { + n, err := iter.reader.Read(iter.buf) + if n == 0 { + if err != nil { + if iter.Error == nil { + iter.Error = err + } + return false + } + } else { + iter.head = 0 + iter.tail = n + return true + } + } +} + +func (iter *Iterator) unreadByte() { + if iter.Error != nil { + return + } + iter.head-- + return +} + +// Read read the next JSON element as generic interface{}. +func (iter *Iterator) Read() interface{} { + valueType := iter.WhatIsNext() + switch valueType { + case StringValue: + return iter.ReadString() + case NumberValue: + if iter.cfg.configBeforeFrozen.UseNumber { + return json.Number(iter.readNumberAsString()) + } + return iter.ReadFloat64() + case NilValue: + iter.skipFourBytes('n', 'u', 'l', 'l') + return nil + case BoolValue: + return iter.ReadBool() + case ArrayValue: + arr := []interface{}{} + iter.ReadArrayCB(func(iter *Iterator) bool { + var elem interface{} + iter.ReadVal(&elem) + arr = append(arr, elem) + return true + }) + return arr + case ObjectValue: + obj := map[string]interface{}{} + iter.ReadMapCB(func(Iter *Iterator, field string) bool { + var elem interface{} + iter.ReadVal(&elem) + obj[field] = elem + return true + }) + return obj + default: + iter.ReportError("Read", fmt.Sprintf("unexpected value type: %v", valueType)) + return nil + } +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/iter_array.go b/go/src/themaru/vendor/github.com/json-iterator/go/iter_array.go new file mode 100644 index 0000000..6188cb4 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/iter_array.go @@ -0,0 +1,58 @@ +package jsoniter + +// ReadArray read array element, tells if the array has more element to read. +func (iter *Iterator) ReadArray() (ret bool) { + c := iter.nextToken() + switch c { + case 'n': + iter.skipThreeBytes('u', 'l', 'l') + return false // null + case '[': + c = iter.nextToken() + if c != ']' { + iter.unreadByte() + return true + } + return false + case ']': + return false + case ',': + return true + default: + iter.ReportError("ReadArray", "expect [ or , or ] or n, but found "+string([]byte{c})) + return + } +} + +// ReadArrayCB read array with callback +func (iter *Iterator) ReadArrayCB(callback func(*Iterator) bool) (ret bool) { + c := iter.nextToken() + if c == '[' { + c = iter.nextToken() + if c != ']' { + iter.unreadByte() + if !callback(iter) { + return false + } + c = iter.nextToken() + for c == ',' { + if !callback(iter) { + return false + } + c = iter.nextToken() + } + if c != ']' { + iter.ReportError("ReadArrayCB", "expect ] in the end, but found "+string([]byte{c})) + return false + } + return true + } + return true + } + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + return true // null + } + iter.ReportError("ReadArrayCB", "expect [ or n, but found "+string([]byte{c})) + return false +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/iter_float.go b/go/src/themaru/vendor/github.com/json-iterator/go/iter_float.go new file mode 100644 index 0000000..b975463 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/iter_float.go @@ -0,0 +1,339 @@ +package jsoniter + +import ( + "encoding/json" + "io" + "math/big" + "strconv" + "strings" + "unsafe" +) + +var floatDigits []int8 + +const invalidCharForNumber = int8(-1) +const endOfNumber = int8(-2) +const dotInNumber = int8(-3) + +func init() { + floatDigits = make([]int8, 256) + for i := 0; i < len(floatDigits); i++ { + floatDigits[i] = invalidCharForNumber + } + for i := int8('0'); i <= int8('9'); i++ { + floatDigits[i] = i - int8('0') + } + floatDigits[','] = endOfNumber + floatDigits[']'] = endOfNumber + floatDigits['}'] = endOfNumber + floatDigits[' '] = endOfNumber + floatDigits['\t'] = endOfNumber + floatDigits['\n'] = endOfNumber + floatDigits['.'] = dotInNumber +} + +// ReadBigFloat read big.Float +func (iter *Iterator) ReadBigFloat() (ret *big.Float) { + str := iter.readNumberAsString() + if iter.Error != nil && iter.Error != io.EOF { + return nil + } + prec := 64 + if len(str) > prec { + prec = len(str) + } + val, _, err := big.ParseFloat(str, 10, uint(prec), big.ToZero) + if err != nil { + iter.Error = err + return nil + } + return val +} + +// ReadBigInt read big.Int +func (iter *Iterator) ReadBigInt() (ret *big.Int) { + str := iter.readNumberAsString() + if iter.Error != nil && iter.Error != io.EOF { + return nil + } + ret = big.NewInt(0) + var success bool + ret, success = ret.SetString(str, 10) + if !success { + iter.ReportError("ReadBigInt", "invalid big int") + return nil + } + return ret +} + +//ReadFloat32 read float32 +func (iter *Iterator) ReadFloat32() (ret float32) { + c := iter.nextToken() + if c == '-' { + return -iter.readPositiveFloat32() + } + iter.unreadByte() + return iter.readPositiveFloat32() +} + +func (iter *Iterator) readPositiveFloat32() (ret float32) { + i := iter.head + // first char + if i == iter.tail { + return iter.readFloat32SlowPath() + } + c := iter.buf[i] + i++ + ind := floatDigits[c] + switch ind { + case invalidCharForNumber: + return iter.readFloat32SlowPath() + case endOfNumber: + iter.ReportError("readFloat32", "empty number") + return + case dotInNumber: + iter.ReportError("readFloat32", "leading dot is invalid") + return + case 0: + if i == iter.tail { + return iter.readFloat32SlowPath() + } + c = iter.buf[i] + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + iter.ReportError("readFloat32", "leading zero is invalid") + return + } + } + value := uint64(ind) + // chars before dot +non_decimal_loop: + for ; i < iter.tail; i++ { + c = iter.buf[i] + ind := floatDigits[c] + switch ind { + case invalidCharForNumber: + return iter.readFloat32SlowPath() + case endOfNumber: + iter.head = i + return float32(value) + case dotInNumber: + break non_decimal_loop + } + if value > uint64SafeToMultiple10 { + return iter.readFloat32SlowPath() + } + value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind; + } + // chars after dot + if c == '.' { + i++ + decimalPlaces := 0 + if i == iter.tail { + return iter.readFloat32SlowPath() + } + for ; i < iter.tail; i++ { + c = iter.buf[i] + ind := floatDigits[c] + switch ind { + case endOfNumber: + if decimalPlaces > 0 && decimalPlaces < len(pow10) { + iter.head = i + return float32(float64(value) / float64(pow10[decimalPlaces])) + } + // too many decimal places + return iter.readFloat32SlowPath() + case invalidCharForNumber, dotInNumber: + return iter.readFloat32SlowPath() + } + decimalPlaces++ + if value > uint64SafeToMultiple10 { + return iter.readFloat32SlowPath() + } + value = (value << 3) + (value << 1) + uint64(ind) + } + } + return iter.readFloat32SlowPath() +} + +func (iter *Iterator) readNumberAsString() (ret string) { + strBuf := [16]byte{} + str := strBuf[0:0] +load_loop: + for { + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + switch c { + case '+', '-', '.', 'e', 'E', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + str = append(str, c) + continue + default: + iter.head = i + break load_loop + } + } + if !iter.loadMore() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + return + } + if len(str) == 0 { + iter.ReportError("readNumberAsString", "invalid number") + } + return *(*string)(unsafe.Pointer(&str)) +} + +func (iter *Iterator) readFloat32SlowPath() (ret float32) { + str := iter.readNumberAsString() + if iter.Error != nil && iter.Error != io.EOF { + return + } + errMsg := validateFloat(str) + if errMsg != "" { + iter.ReportError("readFloat32SlowPath", errMsg) + return + } + val, err := strconv.ParseFloat(str, 32) + if err != nil { + iter.Error = err + return + } + return float32(val) +} + +// ReadFloat64 read float64 +func (iter *Iterator) ReadFloat64() (ret float64) { + c := iter.nextToken() + if c == '-' { + return -iter.readPositiveFloat64() + } + iter.unreadByte() + return iter.readPositiveFloat64() +} + +func (iter *Iterator) readPositiveFloat64() (ret float64) { + i := iter.head + // first char + if i == iter.tail { + return iter.readFloat64SlowPath() + } + c := iter.buf[i] + i++ + ind := floatDigits[c] + switch ind { + case invalidCharForNumber: + return iter.readFloat64SlowPath() + case endOfNumber: + iter.ReportError("readFloat64", "empty number") + return + case dotInNumber: + iter.ReportError("readFloat64", "leading dot is invalid") + return + case 0: + if i == iter.tail { + return iter.readFloat64SlowPath() + } + c = iter.buf[i] + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + iter.ReportError("readFloat64", "leading zero is invalid") + return + } + } + value := uint64(ind) + // chars before dot +non_decimal_loop: + for ; i < iter.tail; i++ { + c = iter.buf[i] + ind := floatDigits[c] + switch ind { + case invalidCharForNumber: + return iter.readFloat64SlowPath() + case endOfNumber: + iter.head = i + return float64(value) + case dotInNumber: + break non_decimal_loop + } + if value > uint64SafeToMultiple10 { + return iter.readFloat64SlowPath() + } + value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind; + } + // chars after dot + if c == '.' { + i++ + decimalPlaces := 0 + if i == iter.tail { + return iter.readFloat64SlowPath() + } + for ; i < iter.tail; i++ { + c = iter.buf[i] + ind := floatDigits[c] + switch ind { + case endOfNumber: + if decimalPlaces > 0 && decimalPlaces < len(pow10) { + iter.head = i + return float64(value) / float64(pow10[decimalPlaces]) + } + // too many decimal places + return iter.readFloat64SlowPath() + case invalidCharForNumber, dotInNumber: + return iter.readFloat64SlowPath() + } + decimalPlaces++ + if value > uint64SafeToMultiple10 { + return iter.readFloat64SlowPath() + } + value = (value << 3) + (value << 1) + uint64(ind) + } + } + return iter.readFloat64SlowPath() +} + +func (iter *Iterator) readFloat64SlowPath() (ret float64) { + str := iter.readNumberAsString() + if iter.Error != nil && iter.Error != io.EOF { + return + } + errMsg := validateFloat(str) + if errMsg != "" { + iter.ReportError("readFloat64SlowPath", errMsg) + return + } + val, err := strconv.ParseFloat(str, 64) + if err != nil { + iter.Error = err + return + } + return val +} + +func validateFloat(str string) string { + // strconv.ParseFloat is not validating `1.` or `1.e1` + if len(str) == 0 { + return "empty number" + } + if str[0] == '-' { + return "-- is not valid" + } + dotPos := strings.IndexByte(str, '.') + if dotPos != -1 { + if dotPos == len(str)-1 { + return "dot can not be last character" + } + switch str[dotPos+1] { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + default: + return "missing digit after dot" + } + } + return "" +} + +// ReadNumber read json.Number +func (iter *Iterator) ReadNumber() (ret json.Number) { + return json.Number(iter.readNumberAsString()) +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/iter_int.go b/go/src/themaru/vendor/github.com/json-iterator/go/iter_int.go new file mode 100644 index 0000000..2142320 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/iter_int.go @@ -0,0 +1,345 @@ +package jsoniter + +import ( + "math" + "strconv" +) + +var intDigits []int8 + +const uint32SafeToMultiply10 = uint32(0xffffffff)/10 - 1 +const uint64SafeToMultiple10 = uint64(0xffffffffffffffff)/10 - 1 + +func init() { + intDigits = make([]int8, 256) + for i := 0; i < len(intDigits); i++ { + intDigits[i] = invalidCharForNumber + } + for i := int8('0'); i <= int8('9'); i++ { + intDigits[i] = i - int8('0') + } +} + +// ReadUint read uint +func (iter *Iterator) ReadUint() uint { + if strconv.IntSize == 32 { + return uint(iter.ReadUint32()) + } + return uint(iter.ReadUint64()) +} + +// ReadInt read int +func (iter *Iterator) ReadInt() int { + if strconv.IntSize == 32 { + return int(iter.ReadInt32()) + } + return int(iter.ReadInt64()) +} + +// ReadInt8 read int8 +func (iter *Iterator) ReadInt8() (ret int8) { + c := iter.nextToken() + if c == '-' { + val := iter.readUint32(iter.readByte()) + if val > math.MaxInt8+1 { + iter.ReportError("ReadInt8", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return -int8(val) + } + val := iter.readUint32(c) + if val > math.MaxInt8 { + iter.ReportError("ReadInt8", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return int8(val) +} + +// ReadUint8 read uint8 +func (iter *Iterator) ReadUint8() (ret uint8) { + val := iter.readUint32(iter.nextToken()) + if val > math.MaxUint8 { + iter.ReportError("ReadUint8", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return uint8(val) +} + +// ReadInt16 read int16 +func (iter *Iterator) ReadInt16() (ret int16) { + c := iter.nextToken() + if c == '-' { + val := iter.readUint32(iter.readByte()) + if val > math.MaxInt16+1 { + iter.ReportError("ReadInt16", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return -int16(val) + } + val := iter.readUint32(c) + if val > math.MaxInt16 { + iter.ReportError("ReadInt16", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return int16(val) +} + +// ReadUint16 read uint16 +func (iter *Iterator) ReadUint16() (ret uint16) { + val := iter.readUint32(iter.nextToken()) + if val > math.MaxUint16 { + iter.ReportError("ReadUint16", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return uint16(val) +} + +// ReadInt32 read int32 +func (iter *Iterator) ReadInt32() (ret int32) { + c := iter.nextToken() + if c == '-' { + val := iter.readUint32(iter.readByte()) + if val > math.MaxInt32+1 { + iter.ReportError("ReadInt32", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return -int32(val) + } + val := iter.readUint32(c) + if val > math.MaxInt32 { + iter.ReportError("ReadInt32", "overflow: "+strconv.FormatInt(int64(val), 10)) + return + } + return int32(val) +} + +// ReadUint32 read uint32 +func (iter *Iterator) ReadUint32() (ret uint32) { + return iter.readUint32(iter.nextToken()) +} + +func (iter *Iterator) readUint32(c byte) (ret uint32) { + ind := intDigits[c] + if ind == 0 { + iter.assertInteger() + return 0 // single zero + } + if ind == invalidCharForNumber { + iter.ReportError("readUint32", "unexpected character: "+string([]byte{byte(ind)})) + return + } + value := uint32(ind) + if iter.tail-iter.head > 10 { + i := iter.head + ind2 := intDigits[iter.buf[i]] + if ind2 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value + } + i++ + ind3 := intDigits[iter.buf[i]] + if ind3 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*10 + uint32(ind2) + } + //iter.head = i + 1 + //value = value * 100 + uint32(ind2) * 10 + uint32(ind3) + i++ + ind4 := intDigits[iter.buf[i]] + if ind4 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*100 + uint32(ind2)*10 + uint32(ind3) + } + i++ + ind5 := intDigits[iter.buf[i]] + if ind5 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*1000 + uint32(ind2)*100 + uint32(ind3)*10 + uint32(ind4) + } + i++ + ind6 := intDigits[iter.buf[i]] + if ind6 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*10000 + uint32(ind2)*1000 + uint32(ind3)*100 + uint32(ind4)*10 + uint32(ind5) + } + i++ + ind7 := intDigits[iter.buf[i]] + if ind7 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*100000 + uint32(ind2)*10000 + uint32(ind3)*1000 + uint32(ind4)*100 + uint32(ind5)*10 + uint32(ind6) + } + i++ + ind8 := intDigits[iter.buf[i]] + if ind8 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*1000000 + uint32(ind2)*100000 + uint32(ind3)*10000 + uint32(ind4)*1000 + uint32(ind5)*100 + uint32(ind6)*10 + uint32(ind7) + } + i++ + ind9 := intDigits[iter.buf[i]] + value = value*10000000 + uint32(ind2)*1000000 + uint32(ind3)*100000 + uint32(ind4)*10000 + uint32(ind5)*1000 + uint32(ind6)*100 + uint32(ind7)*10 + uint32(ind8) + iter.head = i + if ind9 == invalidCharForNumber { + iter.assertInteger() + return value + } + } + for { + for i := iter.head; i < iter.tail; i++ { + ind = intDigits[iter.buf[i]] + if ind == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value + } + if value > uint32SafeToMultiply10 { + value2 := (value << 3) + (value << 1) + uint32(ind) + if value2 < value { + iter.ReportError("readUint32", "overflow") + return + } + value = value2 + continue + } + value = (value << 3) + (value << 1) + uint32(ind) + } + if !iter.loadMore() { + iter.assertInteger() + return value + } + } +} + +// ReadInt64 read int64 +func (iter *Iterator) ReadInt64() (ret int64) { + c := iter.nextToken() + if c == '-' { + val := iter.readUint64(iter.readByte()) + if val > math.MaxInt64+1 { + iter.ReportError("ReadInt64", "overflow: "+strconv.FormatUint(uint64(val), 10)) + return + } + return -int64(val) + } + val := iter.readUint64(c) + if val > math.MaxInt64 { + iter.ReportError("ReadInt64", "overflow: "+strconv.FormatUint(uint64(val), 10)) + return + } + return int64(val) +} + +// ReadUint64 read uint64 +func (iter *Iterator) ReadUint64() uint64 { + return iter.readUint64(iter.nextToken()) +} + +func (iter *Iterator) readUint64(c byte) (ret uint64) { + ind := intDigits[c] + if ind == 0 { + iter.assertInteger() + return 0 // single zero + } + if ind == invalidCharForNumber { + iter.ReportError("readUint64", "unexpected character: "+string([]byte{byte(ind)})) + return + } + value := uint64(ind) + if iter.tail-iter.head > 10 { + i := iter.head + ind2 := intDigits[iter.buf[i]] + if ind2 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value + } + i++ + ind3 := intDigits[iter.buf[i]] + if ind3 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*10 + uint64(ind2) + } + //iter.head = i + 1 + //value = value * 100 + uint32(ind2) * 10 + uint32(ind3) + i++ + ind4 := intDigits[iter.buf[i]] + if ind4 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*100 + uint64(ind2)*10 + uint64(ind3) + } + i++ + ind5 := intDigits[iter.buf[i]] + if ind5 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*1000 + uint64(ind2)*100 + uint64(ind3)*10 + uint64(ind4) + } + i++ + ind6 := intDigits[iter.buf[i]] + if ind6 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*10000 + uint64(ind2)*1000 + uint64(ind3)*100 + uint64(ind4)*10 + uint64(ind5) + } + i++ + ind7 := intDigits[iter.buf[i]] + if ind7 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*100000 + uint64(ind2)*10000 + uint64(ind3)*1000 + uint64(ind4)*100 + uint64(ind5)*10 + uint64(ind6) + } + i++ + ind8 := intDigits[iter.buf[i]] + if ind8 == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value*1000000 + uint64(ind2)*100000 + uint64(ind3)*10000 + uint64(ind4)*1000 + uint64(ind5)*100 + uint64(ind6)*10 + uint64(ind7) + } + i++ + ind9 := intDigits[iter.buf[i]] + value = value*10000000 + uint64(ind2)*1000000 + uint64(ind3)*100000 + uint64(ind4)*10000 + uint64(ind5)*1000 + uint64(ind6)*100 + uint64(ind7)*10 + uint64(ind8) + iter.head = i + if ind9 == invalidCharForNumber { + iter.assertInteger() + return value + } + } + for { + for i := iter.head; i < iter.tail; i++ { + ind = intDigits[iter.buf[i]] + if ind == invalidCharForNumber { + iter.head = i + iter.assertInteger() + return value + } + if value > uint64SafeToMultiple10 { + value2 := (value << 3) + (value << 1) + uint64(ind) + if value2 < value { + iter.ReportError("readUint64", "overflow") + return + } + value = value2 + continue + } + value = (value << 3) + (value << 1) + uint64(ind) + } + if !iter.loadMore() { + iter.assertInteger() + return value + } + } +} + +func (iter *Iterator) assertInteger() { + if iter.head < len(iter.buf) && iter.buf[iter.head] == '.' { + iter.ReportError("assertInteger", "can not decode float as int") + } +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/iter_object.go b/go/src/themaru/vendor/github.com/json-iterator/go/iter_object.go new file mode 100644 index 0000000..1c57576 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/iter_object.go @@ -0,0 +1,251 @@ +package jsoniter + +import ( + "fmt" + "strings" +) + +// ReadObject read one field from object. +// If object ended, returns empty string. +// Otherwise, returns the field name. +func (iter *Iterator) ReadObject() (ret string) { + c := iter.nextToken() + switch c { + case 'n': + iter.skipThreeBytes('u', 'l', 'l') + return "" // null + case '{': + c = iter.nextToken() + if c == '"' { + iter.unreadByte() + field := iter.ReadString() + c = iter.nextToken() + if c != ':' { + iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) + } + return field + } + if c == '}' { + return "" // end of object + } + iter.ReportError("ReadObject", `expect " after {, but found `+string([]byte{c})) + return + case ',': + field := iter.ReadString() + c = iter.nextToken() + if c != ':' { + iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) + } + return field + case '}': + return "" // end of object + default: + iter.ReportError("ReadObject", fmt.Sprintf(`expect { or , or } or n, but found %s`, string([]byte{c}))) + return + } +} + +// CaseInsensitive +func (iter *Iterator) readFieldHash() int64 { + hash := int64(0x811c9dc5) + c := iter.nextToken() + if c != '"' { + iter.ReportError("readFieldHash", `expect ", but found `+string([]byte{c})) + return 0 + } + for { + for i := iter.head; i < iter.tail; i++ { + // require ascii string and no escape + b := iter.buf[i] + if b == '\\' { + iter.head = i + for _, b := range iter.readStringSlowPath() { + if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive { + b += 'a' - 'A' + } + hash ^= int64(b) + hash *= 0x1000193 + } + c = iter.nextToken() + if c != ':' { + iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c})) + return 0 + } + return hash + } + if b == '"' { + iter.head = i + 1 + c = iter.nextToken() + if c != ':' { + iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c})) + return 0 + } + return hash + } + if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive { + b += 'a' - 'A' + } + hash ^= int64(b) + hash *= 0x1000193 + } + if !iter.loadMore() { + iter.ReportError("readFieldHash", `incomplete field name`) + return 0 + } + } +} + +func calcHash(str string, caseSensitive bool) int64 { + if !caseSensitive { + str = strings.ToLower(str) + } + hash := int64(0x811c9dc5) + for _, b := range []byte(str) { + hash ^= int64(b) + hash *= 0x1000193 + } + return int64(hash) +} + +// ReadObjectCB read object with callback, the key is ascii only and field name not copied +func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool { + c := iter.nextToken() + var field string + if c == '{' { + c = iter.nextToken() + if c == '"' { + iter.unreadByte() + field = iter.ReadString() + c = iter.nextToken() + if c != ':' { + iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) + } + if !callback(iter, field) { + return false + } + c = iter.nextToken() + for c == ',' { + field = iter.ReadString() + c = iter.nextToken() + if c != ':' { + iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) + } + if !callback(iter, field) { + return false + } + c = iter.nextToken() + } + if c != '}' { + iter.ReportError("ReadObjectCB", `object not ended with }`) + return false + } + return true + } + if c == '}' { + return true + } + iter.ReportError("ReadObjectCB", `expect " after }, but found `+string([]byte{c})) + return false + } + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + return true // null + } + iter.ReportError("ReadObjectCB", `expect { or n, but found `+string([]byte{c})) + return false +} + +// ReadMapCB read map with callback, the key can be any string +func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool { + c := iter.nextToken() + if c == '{' { + c = iter.nextToken() + if c == '"' { + iter.unreadByte() + field := iter.ReadString() + if iter.nextToken() != ':' { + iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c})) + return false + } + if !callback(iter, field) { + return false + } + c = iter.nextToken() + for c == ',' { + field = iter.ReadString() + if iter.nextToken() != ':' { + iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c})) + return false + } + if !callback(iter, field) { + return false + } + c = iter.nextToken() + } + if c != '}' { + iter.ReportError("ReadMapCB", `object not ended with }`) + return false + } + return true + } + if c == '}' { + return true + } + iter.ReportError("ReadMapCB", `expect " after }, but found `+string([]byte{c})) + return false + } + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + return true // null + } + iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c})) + return false +} + +func (iter *Iterator) readObjectStart() bool { + c := iter.nextToken() + if c == '{' { + c = iter.nextToken() + if c == '}' { + return false + } + iter.unreadByte() + return true + } else if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + return false + } + iter.ReportError("readObjectStart", "expect { or n, but found "+string([]byte{c})) + return false +} + +func (iter *Iterator) readObjectFieldAsBytes() (ret []byte) { + str := iter.ReadStringAsSlice() + if iter.skipWhitespacesWithoutLoadMore() { + if ret == nil { + ret = make([]byte, len(str)) + copy(ret, str) + } + if !iter.loadMore() { + return + } + } + if iter.buf[iter.head] != ':' { + iter.ReportError("readObjectFieldAsBytes", "expect : after object field, but found "+string([]byte{iter.buf[iter.head]})) + return + } + iter.head++ + if iter.skipWhitespacesWithoutLoadMore() { + if ret == nil { + ret = make([]byte, len(str)) + copy(ret, str) + } + if !iter.loadMore() { + return + } + } + if ret == nil { + return str + } + return ret +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/iter_skip.go b/go/src/themaru/vendor/github.com/json-iterator/go/iter_skip.go new file mode 100644 index 0000000..f58beb9 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/iter_skip.go @@ -0,0 +1,129 @@ +package jsoniter + +import "fmt" + +// ReadNil reads a json object as nil and +// returns whether it's a nil or not +func (iter *Iterator) ReadNil() (ret bool) { + c := iter.nextToken() + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') // null + return true + } + iter.unreadByte() + return false +} + +// ReadBool reads a json object as BoolValue +func (iter *Iterator) ReadBool() (ret bool) { + c := iter.nextToken() + if c == 't' { + iter.skipThreeBytes('r', 'u', 'e') + return true + } + if c == 'f' { + iter.skipFourBytes('a', 'l', 's', 'e') + return false + } + iter.ReportError("ReadBool", "expect t or f, but found "+string([]byte{c})) + return +} + +// SkipAndReturnBytes skip next JSON element, and return its content as []byte. +// The []byte can be kept, it is a copy of data. +func (iter *Iterator) SkipAndReturnBytes() []byte { + iter.startCapture(iter.head) + iter.Skip() + return iter.stopCapture() +} + +type captureBuffer struct { + startedAt int + captured []byte +} + +func (iter *Iterator) startCapture(captureStartedAt int) { + if iter.captured != nil { + panic("already in capture mode") + } + iter.captureStartedAt = captureStartedAt + iter.captured = make([]byte, 0, 32) +} + +func (iter *Iterator) stopCapture() []byte { + if iter.captured == nil { + panic("not in capture mode") + } + captured := iter.captured + remaining := iter.buf[iter.captureStartedAt:iter.head] + iter.captureStartedAt = -1 + iter.captured = nil + if len(captured) == 0 { + copied := make([]byte, len(remaining)) + copy(copied, remaining) + return copied + } + captured = append(captured, remaining...) + return captured +} + +// Skip skips a json object and positions to relatively the next json object +func (iter *Iterator) Skip() { + c := iter.nextToken() + switch c { + case '"': + iter.skipString() + case 'n': + iter.skipThreeBytes('u', 'l', 'l') // null + case 't': + iter.skipThreeBytes('r', 'u', 'e') // true + case 'f': + iter.skipFourBytes('a', 'l', 's', 'e') // false + case '0': + iter.unreadByte() + iter.ReadFloat32() + case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9': + iter.skipNumber() + case '[': + iter.skipArray() + case '{': + iter.skipObject() + default: + iter.ReportError("Skip", fmt.Sprintf("do not know how to skip: %v", c)) + return + } +} + +func (iter *Iterator) skipFourBytes(b1, b2, b3, b4 byte) { + if iter.readByte() != b1 { + iter.ReportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) + return + } + if iter.readByte() != b2 { + iter.ReportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) + return + } + if iter.readByte() != b3 { + iter.ReportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) + return + } + if iter.readByte() != b4 { + iter.ReportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4}))) + return + } +} + +func (iter *Iterator) skipThreeBytes(b1, b2, b3 byte) { + if iter.readByte() != b1 { + iter.ReportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3}))) + return + } + if iter.readByte() != b2 { + iter.ReportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3}))) + return + } + if iter.readByte() != b3 { + iter.ReportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3}))) + return + } +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/iter_skip_sloppy.go b/go/src/themaru/vendor/github.com/json-iterator/go/iter_skip_sloppy.go new file mode 100644 index 0000000..8fcdc3b --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/iter_skip_sloppy.go @@ -0,0 +1,144 @@ +//+build jsoniter_sloppy + +package jsoniter + +// sloppy but faster implementation, do not validate the input json + +func (iter *Iterator) skipNumber() { + for { + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + switch c { + case ' ', '\n', '\r', '\t', ',', '}', ']': + iter.head = i + return + } + } + if !iter.loadMore() { + return + } + } +} + +func (iter *Iterator) skipArray() { + level := 1 + for { + for i := iter.head; i < iter.tail; i++ { + switch iter.buf[i] { + case '"': // If inside string, skip it + iter.head = i + 1 + iter.skipString() + i = iter.head - 1 // it will be i++ soon + case '[': // If open symbol, increase level + level++ + case ']': // If close symbol, increase level + level-- + + // If we have returned to the original level, we're done + if level == 0 { + iter.head = i + 1 + return + } + } + } + if !iter.loadMore() { + iter.ReportError("skipObject", "incomplete array") + return + } + } +} + +func (iter *Iterator) skipObject() { + level := 1 + for { + for i := iter.head; i < iter.tail; i++ { + switch iter.buf[i] { + case '"': // If inside string, skip it + iter.head = i + 1 + iter.skipString() + i = iter.head - 1 // it will be i++ soon + case '{': // If open symbol, increase level + level++ + case '}': // If close symbol, increase level + level-- + + // If we have returned to the original level, we're done + if level == 0 { + iter.head = i + 1 + return + } + } + } + if !iter.loadMore() { + iter.ReportError("skipObject", "incomplete object") + return + } + } +} + +func (iter *Iterator) skipString() { + for { + end, escaped := iter.findStringEnd() + if end == -1 { + if !iter.loadMore() { + iter.ReportError("skipString", "incomplete string") + return + } + if escaped { + iter.head = 1 // skip the first char as last char read is \ + } + } else { + iter.head = end + return + } + } +} + +// adapted from: https://github.com/buger/jsonparser/blob/master/parser.go +// Tries to find the end of string +// Support if string contains escaped quote symbols. +func (iter *Iterator) findStringEnd() (int, bool) { + escaped := false + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + if c == '"' { + if !escaped { + return i + 1, false + } + j := i - 1 + for { + if j < iter.head || iter.buf[j] != '\\' { + // even number of backslashes + // either end of buffer, or " found + return i + 1, true + } + j-- + if j < iter.head || iter.buf[j] != '\\' { + // odd number of backslashes + // it is \" or \\\" + break + } + j-- + } + } else if c == '\\' { + escaped = true + } + } + j := iter.tail - 1 + for { + if j < iter.head || iter.buf[j] != '\\' { + // even number of backslashes + // either end of buffer, or " found + return -1, false // do not end with \ + } + j-- + if j < iter.head || iter.buf[j] != '\\' { + // odd number of backslashes + // it is \" or \\\" + break + } + j-- + + } + return -1, true // end with \ +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/iter_skip_strict.go b/go/src/themaru/vendor/github.com/json-iterator/go/iter_skip_strict.go new file mode 100644 index 0000000..6cf66d0 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/iter_skip_strict.go @@ -0,0 +1,99 @@ +//+build !jsoniter_sloppy + +package jsoniter + +import ( + "fmt" + "io" +) + +func (iter *Iterator) skipNumber() { + if !iter.trySkipNumber() { + iter.unreadByte() + if iter.Error != nil && iter.Error != io.EOF { + return + } + iter.ReadFloat64() + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = nil + iter.ReadBigFloat() + } + } +} + +func (iter *Iterator) trySkipNumber() bool { + dotFound := false + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + case '.': + if dotFound { + iter.ReportError("validateNumber", `more than one dot found in number`) + return true // already failed + } + if i+1 == iter.tail { + return false + } + c = iter.buf[i+1] + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + default: + iter.ReportError("validateNumber", `missing digit after dot`) + return true // already failed + } + dotFound = true + default: + switch c { + case ',', ']', '}', ' ', '\t', '\n', '\r': + if iter.head == i { + return false // if - without following digits + } + iter.head = i + return true // must be valid + } + return false // may be invalid + } + } + return false +} + +func (iter *Iterator) skipString() { + if !iter.trySkipString() { + iter.unreadByte() + iter.ReadString() + } +} + +func (iter *Iterator) trySkipString() bool { + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + if c == '"' { + iter.head = i + 1 + return true // valid + } else if c == '\\' { + return false + } else if c < ' ' { + iter.ReportError("trySkipString", + fmt.Sprintf(`invalid control character found: %d`, c)) + return true // already failed + } + } + return false +} + +func (iter *Iterator) skipObject() { + iter.unreadByte() + iter.ReadObjectCB(func(iter *Iterator, field string) bool { + iter.Skip() + return true + }) +} + +func (iter *Iterator) skipArray() { + iter.unreadByte() + iter.ReadArrayCB(func(iter *Iterator) bool { + iter.Skip() + return true + }) +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/iter_str.go b/go/src/themaru/vendor/github.com/json-iterator/go/iter_str.go new file mode 100644 index 0000000..adc487e --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/iter_str.go @@ -0,0 +1,215 @@ +package jsoniter + +import ( + "fmt" + "unicode/utf16" +) + +// ReadString read string from iterator +func (iter *Iterator) ReadString() (ret string) { + c := iter.nextToken() + if c == '"' { + for i := iter.head; i < iter.tail; i++ { + c := iter.buf[i] + if c == '"' { + ret = string(iter.buf[iter.head:i]) + iter.head = i + 1 + return ret + } else if c == '\\' { + break + } else if c < ' ' { + iter.ReportError("ReadString", + fmt.Sprintf(`invalid control character found: %d`, c)) + return + } + } + return iter.readStringSlowPath() + } else if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + return "" + } + iter.ReportError("ReadString", `expects " or n, but found `+string([]byte{c})) + return +} + +func (iter *Iterator) readStringSlowPath() (ret string) { + var str []byte + var c byte + for iter.Error == nil { + c = iter.readByte() + if c == '"' { + return string(str) + } + if c == '\\' { + c = iter.readByte() + str = iter.readEscapedChar(c, str) + } else { + str = append(str, c) + } + } + iter.ReportError("readStringSlowPath", "unexpected end of input") + return +} + +func (iter *Iterator) readEscapedChar(c byte, str []byte) []byte { + switch c { + case 'u': + r := iter.readU4() + if utf16.IsSurrogate(r) { + c = iter.readByte() + if iter.Error != nil { + return nil + } + if c != '\\' { + iter.unreadByte() + str = appendRune(str, r) + return str + } + c = iter.readByte() + if iter.Error != nil { + return nil + } + if c != 'u' { + str = appendRune(str, r) + return iter.readEscapedChar(c, str) + } + r2 := iter.readU4() + if iter.Error != nil { + return nil + } + combined := utf16.DecodeRune(r, r2) + if combined == '\uFFFD' { + str = appendRune(str, r) + str = appendRune(str, r2) + } else { + str = appendRune(str, combined) + } + } else { + str = appendRune(str, r) + } + case '"': + str = append(str, '"') + case '\\': + str = append(str, '\\') + case '/': + str = append(str, '/') + case 'b': + str = append(str, '\b') + case 'f': + str = append(str, '\f') + case 'n': + str = append(str, '\n') + case 'r': + str = append(str, '\r') + case 't': + str = append(str, '\t') + default: + iter.ReportError("readEscapedChar", + `invalid escape char after \`) + return nil + } + return str +} + +// ReadStringAsSlice read string from iterator without copying into string form. +// The []byte can not be kept, as it will change after next iterator call. +func (iter *Iterator) ReadStringAsSlice() (ret []byte) { + c := iter.nextToken() + if c == '"' { + for i := iter.head; i < iter.tail; i++ { + // require ascii string and no escape + // for: field name, base64, number + if iter.buf[i] == '"' { + // fast path: reuse the underlying buffer + ret = iter.buf[iter.head:i] + iter.head = i + 1 + return ret + } + } + readLen := iter.tail - iter.head + copied := make([]byte, readLen, readLen*2) + copy(copied, iter.buf[iter.head:iter.tail]) + iter.head = iter.tail + for iter.Error == nil { + c := iter.readByte() + if c == '"' { + return copied + } + copied = append(copied, c) + } + return copied + } + iter.ReportError("ReadStringAsSlice", `expects " or n, but found `+string([]byte{c})) + return +} + +func (iter *Iterator) readU4() (ret rune) { + for i := 0; i < 4; i++ { + c := iter.readByte() + if iter.Error != nil { + return + } + if c >= '0' && c <= '9' { + ret = ret*16 + rune(c-'0') + } else if c >= 'a' && c <= 'f' { + ret = ret*16 + rune(c-'a'+10) + } else if c >= 'A' && c <= 'F' { + ret = ret*16 + rune(c-'A'+10) + } else { + iter.ReportError("readU4", "expects 0~9 or a~f, but found "+string([]byte{c})) + return + } + } + return ret +} + +const ( + t1 = 0x00 // 0000 0000 + tx = 0x80 // 1000 0000 + t2 = 0xC0 // 1100 0000 + t3 = 0xE0 // 1110 0000 + t4 = 0xF0 // 1111 0000 + t5 = 0xF8 // 1111 1000 + + maskx = 0x3F // 0011 1111 + mask2 = 0x1F // 0001 1111 + mask3 = 0x0F // 0000 1111 + mask4 = 0x07 // 0000 0111 + + rune1Max = 1<<7 - 1 + rune2Max = 1<<11 - 1 + rune3Max = 1<<16 - 1 + + surrogateMin = 0xD800 + surrogateMax = 0xDFFF + + maxRune = '\U0010FFFF' // Maximum valid Unicode code point. + runeError = '\uFFFD' // the "error" Rune or "Unicode replacement character" +) + +func appendRune(p []byte, r rune) []byte { + // Negative values are erroneous. Making it unsigned addresses the problem. + switch i := uint32(r); { + case i <= rune1Max: + p = append(p, byte(r)) + return p + case i <= rune2Max: + p = append(p, t2|byte(r>>6)) + p = append(p, tx|byte(r)&maskx) + return p + case i > maxRune, surrogateMin <= i && i <= surrogateMax: + r = runeError + fallthrough + case i <= rune3Max: + p = append(p, t3|byte(r>>12)) + p = append(p, tx|byte(r>>6)&maskx) + p = append(p, tx|byte(r)&maskx) + return p + default: + p = append(p, t4|byte(r>>18)) + p = append(p, tx|byte(r>>12)&maskx) + p = append(p, tx|byte(r>>6)&maskx) + p = append(p, tx|byte(r)&maskx) + return p + } +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/jsoniter.go b/go/src/themaru/vendor/github.com/json-iterator/go/jsoniter.go new file mode 100644 index 0000000..c2934f9 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/jsoniter.go @@ -0,0 +1,18 @@ +// Package jsoniter implements encoding and decoding of JSON as defined in +// RFC 4627 and provides interfaces with identical syntax of standard lib encoding/json. +// Converting from encoding/json to jsoniter is no more than replacing the package with jsoniter +// and variable type declarations (if any). +// jsoniter interfaces gives 100% compatibility with code using standard lib. +// +// "JSON and Go" +// (https://golang.org/doc/articles/json_and_go.html) +// gives a description of how Marshal/Unmarshal operate +// between arbitrary or predefined json objects and bytes, +// and it applies to jsoniter.Marshal/Unmarshal as well. +// +// Besides, jsoniter.Iterator provides a different set of interfaces +// iterating given bytes/string/reader +// and yielding parsed elements one by one. +// This set of interfaces reads input as required and gives +// better performance. +package jsoniter diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/pool.go b/go/src/themaru/vendor/github.com/json-iterator/go/pool.go new file mode 100644 index 0000000..e2389b5 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/pool.go @@ -0,0 +1,42 @@ +package jsoniter + +import ( + "io" +) + +// IteratorPool a thread safe pool of iterators with same configuration +type IteratorPool interface { + BorrowIterator(data []byte) *Iterator + ReturnIterator(iter *Iterator) +} + +// StreamPool a thread safe pool of streams with same configuration +type StreamPool interface { + BorrowStream(writer io.Writer) *Stream + ReturnStream(stream *Stream) +} + +func (cfg *frozenConfig) BorrowStream(writer io.Writer) *Stream { + stream := cfg.streamPool.Get().(*Stream) + stream.Reset(writer) + return stream +} + +func (cfg *frozenConfig) ReturnStream(stream *Stream) { + stream.out = nil + stream.Error = nil + stream.Attachment = nil + cfg.streamPool.Put(stream) +} + +func (cfg *frozenConfig) BorrowIterator(data []byte) *Iterator { + iter := cfg.iteratorPool.Get().(*Iterator) + iter.ResetBytes(data) + return iter +} + +func (cfg *frozenConfig) ReturnIterator(iter *Iterator) { + iter.Error = nil + iter.Attachment = nil + cfg.iteratorPool.Put(iter) +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/reflect.go b/go/src/themaru/vendor/github.com/json-iterator/go/reflect.go new file mode 100644 index 0000000..4459e20 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/reflect.go @@ -0,0 +1,332 @@ +package jsoniter + +import ( + "fmt" + "reflect" + "unsafe" + + "github.com/modern-go/reflect2" +) + +// ValDecoder is an internal type registered to cache as needed. +// Don't confuse jsoniter.ValDecoder with json.Decoder. +// For json.Decoder's adapter, refer to jsoniter.AdapterDecoder(todo link). +// +// Reflection on type to create decoders, which is then cached +// Reflection on value is avoided as we can, as the reflect.Value itself will allocate, with following exceptions +// 1. create instance of new value, for example *int will need a int to be allocated +// 2. append to slice, if the existing cap is not enough, allocate will be done using Reflect.New +// 3. assignment to map, both key and value will be reflect.Value +// For a simple struct binding, it will be reflect.Value free and allocation free +type ValDecoder interface { + Decode(ptr unsafe.Pointer, iter *Iterator) +} + +// ValEncoder is an internal type registered to cache as needed. +// Don't confuse jsoniter.ValEncoder with json.Encoder. +// For json.Encoder's adapter, refer to jsoniter.AdapterEncoder(todo godoc link). +type ValEncoder interface { + IsEmpty(ptr unsafe.Pointer) bool + Encode(ptr unsafe.Pointer, stream *Stream) +} + +type checkIsEmpty interface { + IsEmpty(ptr unsafe.Pointer) bool +} + +type ctx struct { + *frozenConfig + prefix string + encoders map[reflect2.Type]ValEncoder + decoders map[reflect2.Type]ValDecoder +} + +func (b *ctx) caseSensitive() bool { + if b.frozenConfig == nil { + // default is case-insensitive + return false + } + return b.frozenConfig.caseSensitive +} + +func (b *ctx) append(prefix string) *ctx { + return &ctx{ + frozenConfig: b.frozenConfig, + prefix: b.prefix + " " + prefix, + encoders: b.encoders, + decoders: b.decoders, + } +} + +// ReadVal copy the underlying JSON into go interface, same as json.Unmarshal +func (iter *Iterator) ReadVal(obj interface{}) { + cacheKey := reflect2.RTypeOf(obj) + decoder := iter.cfg.getDecoderFromCache(cacheKey) + if decoder == nil { + typ := reflect2.TypeOf(obj) + if typ.Kind() != reflect.Ptr { + iter.ReportError("ReadVal", "can only unmarshal into pointer") + return + } + decoder = iter.cfg.DecoderOf(typ) + } + ptr := reflect2.PtrOf(obj) + if ptr == nil { + iter.ReportError("ReadVal", "can not read into nil pointer") + return + } + decoder.Decode(ptr, iter) +} + +// WriteVal copy the go interface into underlying JSON, same as json.Marshal +func (stream *Stream) WriteVal(val interface{}) { + if nil == val { + stream.WriteNil() + return + } + cacheKey := reflect2.RTypeOf(val) + encoder := stream.cfg.getEncoderFromCache(cacheKey) + if encoder == nil { + typ := reflect2.TypeOf(val) + encoder = stream.cfg.EncoderOf(typ) + } + encoder.Encode(reflect2.PtrOf(val), stream) +} + +func (cfg *frozenConfig) DecoderOf(typ reflect2.Type) ValDecoder { + cacheKey := typ.RType() + decoder := cfg.getDecoderFromCache(cacheKey) + if decoder != nil { + return decoder + } + ctx := &ctx{ + frozenConfig: cfg, + prefix: "", + decoders: map[reflect2.Type]ValDecoder{}, + encoders: map[reflect2.Type]ValEncoder{}, + } + ptrType := typ.(*reflect2.UnsafePtrType) + decoder = decoderOfType(ctx, ptrType.Elem()) + cfg.addDecoderToCache(cacheKey, decoder) + return decoder +} + +func decoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder { + decoder := getTypeDecoderFromExtension(ctx, typ) + if decoder != nil { + return decoder + } + decoder = createDecoderOfType(ctx, typ) + for _, extension := range extensions { + decoder = extension.DecorateDecoder(typ, decoder) + } + decoder = ctx.decoderExtension.DecorateDecoder(typ, decoder) + for _, extension := range ctx.extraExtensions { + decoder = extension.DecorateDecoder(typ, decoder) + } + return decoder +} + +func createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder { + decoder := ctx.decoders[typ] + if decoder != nil { + return decoder + } + placeholder := &placeholderDecoder{} + ctx.decoders[typ] = placeholder + decoder = _createDecoderOfType(ctx, typ) + placeholder.decoder = decoder + return decoder +} + +func _createDecoderOfType(ctx *ctx, typ reflect2.Type) ValDecoder { + decoder := createDecoderOfJsonRawMessage(ctx, typ) + if decoder != nil { + return decoder + } + decoder = createDecoderOfJsonNumber(ctx, typ) + if decoder != nil { + return decoder + } + decoder = createDecoderOfMarshaler(ctx, typ) + if decoder != nil { + return decoder + } + decoder = createDecoderOfAny(ctx, typ) + if decoder != nil { + return decoder + } + decoder = createDecoderOfNative(ctx, typ) + if decoder != nil { + return decoder + } + switch typ.Kind() { + case reflect.Interface: + ifaceType, isIFace := typ.(*reflect2.UnsafeIFaceType) + if isIFace { + return &ifaceDecoder{valType: ifaceType} + } + return &efaceDecoder{} + case reflect.Struct: + return decoderOfStruct(ctx, typ) + case reflect.Array: + return decoderOfArray(ctx, typ) + case reflect.Slice: + return decoderOfSlice(ctx, typ) + case reflect.Map: + return decoderOfMap(ctx, typ) + case reflect.Ptr: + return decoderOfOptional(ctx, typ) + default: + return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())} + } +} + +func (cfg *frozenConfig) EncoderOf(typ reflect2.Type) ValEncoder { + cacheKey := typ.RType() + encoder := cfg.getEncoderFromCache(cacheKey) + if encoder != nil { + return encoder + } + ctx := &ctx{ + frozenConfig: cfg, + prefix: "", + decoders: map[reflect2.Type]ValDecoder{}, + encoders: map[reflect2.Type]ValEncoder{}, + } + encoder = encoderOfType(ctx, typ) + if typ.LikePtr() { + encoder = &onePtrEncoder{encoder} + } + cfg.addEncoderToCache(cacheKey, encoder) + return encoder +} + +type onePtrEncoder struct { + encoder ValEncoder +} + +func (encoder *onePtrEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr)) +} + +func (encoder *onePtrEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + encoder.encoder.Encode(unsafe.Pointer(&ptr), stream) +} + +func encoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder { + encoder := getTypeEncoderFromExtension(ctx, typ) + if encoder != nil { + return encoder + } + encoder = createEncoderOfType(ctx, typ) + for _, extension := range extensions { + encoder = extension.DecorateEncoder(typ, encoder) + } + encoder = ctx.encoderExtension.DecorateEncoder(typ, encoder) + for _, extension := range ctx.extraExtensions { + encoder = extension.DecorateEncoder(typ, encoder) + } + return encoder +} + +func createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder { + encoder := ctx.encoders[typ] + if encoder != nil { + return encoder + } + placeholder := &placeholderEncoder{} + ctx.encoders[typ] = placeholder + encoder = _createEncoderOfType(ctx, typ) + placeholder.encoder = encoder + return encoder +} +func _createEncoderOfType(ctx *ctx, typ reflect2.Type) ValEncoder { + encoder := createEncoderOfJsonRawMessage(ctx, typ) + if encoder != nil { + return encoder + } + encoder = createEncoderOfJsonNumber(ctx, typ) + if encoder != nil { + return encoder + } + encoder = createEncoderOfMarshaler(ctx, typ) + if encoder != nil { + return encoder + } + encoder = createEncoderOfAny(ctx, typ) + if encoder != nil { + return encoder + } + encoder = createEncoderOfNative(ctx, typ) + if encoder != nil { + return encoder + } + kind := typ.Kind() + switch kind { + case reflect.Interface: + return &dynamicEncoder{typ} + case reflect.Struct: + return encoderOfStruct(ctx, typ) + case reflect.Array: + return encoderOfArray(ctx, typ) + case reflect.Slice: + return encoderOfSlice(ctx, typ) + case reflect.Map: + return encoderOfMap(ctx, typ) + case reflect.Ptr: + return encoderOfOptional(ctx, typ) + default: + return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", ctx.prefix, typ.String())} + } +} + +type lazyErrorDecoder struct { + err error +} + +func (decoder *lazyErrorDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if iter.WhatIsNext() != NilValue { + if iter.Error == nil { + iter.Error = decoder.err + } + } else { + iter.Skip() + } +} + +type lazyErrorEncoder struct { + err error +} + +func (encoder *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + if ptr == nil { + stream.WriteNil() + } else if stream.Error == nil { + stream.Error = encoder.err + } +} + +func (encoder *lazyErrorEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return false +} + +type placeholderDecoder struct { + decoder ValDecoder +} + +func (decoder *placeholderDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + decoder.decoder.Decode(ptr, iter) +} + +type placeholderEncoder struct { + encoder ValEncoder +} + +func (encoder *placeholderEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + encoder.encoder.Encode(ptr, stream) +} + +func (encoder *placeholderEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.encoder.IsEmpty(ptr) +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/reflect_array.go b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_array.go new file mode 100644 index 0000000..13a0b7b --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_array.go @@ -0,0 +1,104 @@ +package jsoniter + +import ( + "fmt" + "github.com/modern-go/reflect2" + "io" + "unsafe" +) + +func decoderOfArray(ctx *ctx, typ reflect2.Type) ValDecoder { + arrayType := typ.(*reflect2.UnsafeArrayType) + decoder := decoderOfType(ctx.append("[arrayElem]"), arrayType.Elem()) + return &arrayDecoder{arrayType, decoder} +} + +func encoderOfArray(ctx *ctx, typ reflect2.Type) ValEncoder { + arrayType := typ.(*reflect2.UnsafeArrayType) + if arrayType.Len() == 0 { + return emptyArrayEncoder{} + } + encoder := encoderOfType(ctx.append("[arrayElem]"), arrayType.Elem()) + return &arrayEncoder{arrayType, encoder} +} + +type emptyArrayEncoder struct{} + +func (encoder emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteEmptyArray() +} + +func (encoder emptyArrayEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return true +} + +type arrayEncoder struct { + arrayType *reflect2.UnsafeArrayType + elemEncoder ValEncoder +} + +func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteArrayStart() + elemPtr := unsafe.Pointer(ptr) + encoder.elemEncoder.Encode(elemPtr, stream) + for i := 1; i < encoder.arrayType.Len(); i++ { + stream.WriteMore() + elemPtr = encoder.arrayType.UnsafeGetIndex(ptr, i) + encoder.elemEncoder.Encode(elemPtr, stream) + } + stream.WriteArrayEnd() + if stream.Error != nil && stream.Error != io.EOF { + stream.Error = fmt.Errorf("%v: %s", encoder.arrayType, stream.Error.Error()) + } +} + +func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return false +} + +type arrayDecoder struct { + arrayType *reflect2.UnsafeArrayType + elemDecoder ValDecoder +} + +func (decoder *arrayDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + decoder.doDecode(ptr, iter) + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v: %s", decoder.arrayType, iter.Error.Error()) + } +} + +func (decoder *arrayDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) { + c := iter.nextToken() + arrayType := decoder.arrayType + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + return + } + if c != '[' { + iter.ReportError("decode array", "expect [ or n, but found "+string([]byte{c})) + return + } + c = iter.nextToken() + if c == ']' { + return + } + iter.unreadByte() + elemPtr := arrayType.UnsafeGetIndex(ptr, 0) + decoder.elemDecoder.Decode(elemPtr, iter) + length := 1 + for c = iter.nextToken(); c == ','; c = iter.nextToken() { + if length >= arrayType.Len() { + iter.Skip() + continue + } + idx := length + length += 1 + elemPtr = arrayType.UnsafeGetIndex(ptr, idx) + decoder.elemDecoder.Decode(elemPtr, iter) + } + if c != ']' { + iter.ReportError("decode array", "expect ], but found "+string([]byte{c})) + return + } +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/reflect_dynamic.go b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_dynamic.go new file mode 100644 index 0000000..8b6bc8b --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_dynamic.go @@ -0,0 +1,70 @@ +package jsoniter + +import ( + "github.com/modern-go/reflect2" + "reflect" + "unsafe" +) + +type dynamicEncoder struct { + valType reflect2.Type +} + +func (encoder *dynamicEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + obj := encoder.valType.UnsafeIndirect(ptr) + stream.WriteVal(obj) +} + +func (encoder *dynamicEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.valType.UnsafeIndirect(ptr) == nil +} + +type efaceDecoder struct { +} + +func (decoder *efaceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + pObj := (*interface{})(ptr) + obj := *pObj + if obj == nil { + *pObj = iter.Read() + return + } + typ := reflect2.TypeOf(obj) + if typ.Kind() != reflect.Ptr { + *pObj = iter.Read() + return + } + ptrType := typ.(*reflect2.UnsafePtrType) + ptrElemType := ptrType.Elem() + if iter.WhatIsNext() == NilValue { + if ptrElemType.Kind() != reflect.Ptr { + iter.skipFourBytes('n', 'u', 'l', 'l') + *pObj = nil + return + } + } + if reflect2.IsNil(obj) { + obj := ptrElemType.New() + iter.ReadVal(obj) + *pObj = obj + return + } + iter.ReadVal(obj) +} + +type ifaceDecoder struct { + valType *reflect2.UnsafeIFaceType +} + +func (decoder *ifaceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if iter.ReadNil() { + decoder.valType.UnsafeSet(ptr, decoder.valType.UnsafeNew()) + return + } + obj := decoder.valType.UnsafeIndirect(ptr) + if reflect2.IsNil(obj) { + iter.ReportError("decode non empty interface", "can not unmarshal into nil") + return + } + iter.ReadVal(obj) +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/reflect_extension.go b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_extension.go new file mode 100644 index 0000000..05e8fbf --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_extension.go @@ -0,0 +1,483 @@ +package jsoniter + +import ( + "fmt" + "github.com/modern-go/reflect2" + "reflect" + "sort" + "strings" + "unicode" + "unsafe" +) + +var typeDecoders = map[string]ValDecoder{} +var fieldDecoders = map[string]ValDecoder{} +var typeEncoders = map[string]ValEncoder{} +var fieldEncoders = map[string]ValEncoder{} +var extensions = []Extension{} + +// StructDescriptor describe how should we encode/decode the struct +type StructDescriptor struct { + Type reflect2.Type + Fields []*Binding +} + +// GetField get one field from the descriptor by its name. +// Can not use map here to keep field orders. +func (structDescriptor *StructDescriptor) GetField(fieldName string) *Binding { + for _, binding := range structDescriptor.Fields { + if binding.Field.Name() == fieldName { + return binding + } + } + return nil +} + +// Binding describe how should we encode/decode the struct field +type Binding struct { + levels []int + Field reflect2.StructField + FromNames []string + ToNames []string + Encoder ValEncoder + Decoder ValDecoder +} + +// Extension the one for all SPI. Customize encoding/decoding by specifying alternate encoder/decoder. +// Can also rename fields by UpdateStructDescriptor. +type Extension interface { + UpdateStructDescriptor(structDescriptor *StructDescriptor) + CreateMapKeyDecoder(typ reflect2.Type) ValDecoder + CreateMapKeyEncoder(typ reflect2.Type) ValEncoder + CreateDecoder(typ reflect2.Type) ValDecoder + CreateEncoder(typ reflect2.Type) ValEncoder + DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder + DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder +} + +// DummyExtension embed this type get dummy implementation for all methods of Extension +type DummyExtension struct { +} + +// UpdateStructDescriptor No-op +func (extension *DummyExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) { +} + +// CreateMapKeyDecoder No-op +func (extension *DummyExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder { + return nil +} + +// CreateMapKeyEncoder No-op +func (extension *DummyExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder { + return nil +} + +// CreateDecoder No-op +func (extension *DummyExtension) CreateDecoder(typ reflect2.Type) ValDecoder { + return nil +} + +// CreateEncoder No-op +func (extension *DummyExtension) CreateEncoder(typ reflect2.Type) ValEncoder { + return nil +} + +// DecorateDecoder No-op +func (extension *DummyExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder { + return decoder +} + +// DecorateEncoder No-op +func (extension *DummyExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder { + return encoder +} + +type EncoderExtension map[reflect2.Type]ValEncoder + +// UpdateStructDescriptor No-op +func (extension EncoderExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) { +} + +// CreateDecoder No-op +func (extension EncoderExtension) CreateDecoder(typ reflect2.Type) ValDecoder { + return nil +} + +// CreateEncoder get encoder from map +func (extension EncoderExtension) CreateEncoder(typ reflect2.Type) ValEncoder { + return extension[typ] +} + +// CreateMapKeyDecoder No-op +func (extension EncoderExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder { + return nil +} + +// CreateMapKeyEncoder No-op +func (extension EncoderExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder { + return nil +} + +// DecorateDecoder No-op +func (extension EncoderExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder { + return decoder +} + +// DecorateEncoder No-op +func (extension EncoderExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder { + return encoder +} + +type DecoderExtension map[reflect2.Type]ValDecoder + +// UpdateStructDescriptor No-op +func (extension DecoderExtension) UpdateStructDescriptor(structDescriptor *StructDescriptor) { +} + +// CreateMapKeyDecoder No-op +func (extension DecoderExtension) CreateMapKeyDecoder(typ reflect2.Type) ValDecoder { + return nil +} + +// CreateMapKeyEncoder No-op +func (extension DecoderExtension) CreateMapKeyEncoder(typ reflect2.Type) ValEncoder { + return nil +} + +// CreateDecoder get decoder from map +func (extension DecoderExtension) CreateDecoder(typ reflect2.Type) ValDecoder { + return extension[typ] +} + +// CreateEncoder No-op +func (extension DecoderExtension) CreateEncoder(typ reflect2.Type) ValEncoder { + return nil +} + +// DecorateDecoder No-op +func (extension DecoderExtension) DecorateDecoder(typ reflect2.Type, decoder ValDecoder) ValDecoder { + return decoder +} + +// DecorateEncoder No-op +func (extension DecoderExtension) DecorateEncoder(typ reflect2.Type, encoder ValEncoder) ValEncoder { + return encoder +} + +type funcDecoder struct { + fun DecoderFunc +} + +func (decoder *funcDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + decoder.fun(ptr, iter) +} + +type funcEncoder struct { + fun EncoderFunc + isEmptyFunc func(ptr unsafe.Pointer) bool +} + +func (encoder *funcEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + encoder.fun(ptr, stream) +} + +func (encoder *funcEncoder) IsEmpty(ptr unsafe.Pointer) bool { + if encoder.isEmptyFunc == nil { + return false + } + return encoder.isEmptyFunc(ptr) +} + +// DecoderFunc the function form of TypeDecoder +type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator) + +// EncoderFunc the function form of TypeEncoder +type EncoderFunc func(ptr unsafe.Pointer, stream *Stream) + +// RegisterTypeDecoderFunc register TypeDecoder for a type with function +func RegisterTypeDecoderFunc(typ string, fun DecoderFunc) { + typeDecoders[typ] = &funcDecoder{fun} +} + +// RegisterTypeDecoder register TypeDecoder for a typ +func RegisterTypeDecoder(typ string, decoder ValDecoder) { + typeDecoders[typ] = decoder +} + +// RegisterFieldDecoderFunc register TypeDecoder for a struct field with function +func RegisterFieldDecoderFunc(typ string, field string, fun DecoderFunc) { + RegisterFieldDecoder(typ, field, &funcDecoder{fun}) +} + +// RegisterFieldDecoder register TypeDecoder for a struct field +func RegisterFieldDecoder(typ string, field string, decoder ValDecoder) { + fieldDecoders[fmt.Sprintf("%s/%s", typ, field)] = decoder +} + +// RegisterTypeEncoderFunc register TypeEncoder for a type with encode/isEmpty function +func RegisterTypeEncoderFunc(typ string, fun EncoderFunc, isEmptyFunc func(unsafe.Pointer) bool) { + typeEncoders[typ] = &funcEncoder{fun, isEmptyFunc} +} + +// RegisterTypeEncoder register TypeEncoder for a type +func RegisterTypeEncoder(typ string, encoder ValEncoder) { + typeEncoders[typ] = encoder +} + +// RegisterFieldEncoderFunc register TypeEncoder for a struct field with encode/isEmpty function +func RegisterFieldEncoderFunc(typ string, field string, fun EncoderFunc, isEmptyFunc func(unsafe.Pointer) bool) { + RegisterFieldEncoder(typ, field, &funcEncoder{fun, isEmptyFunc}) +} + +// RegisterFieldEncoder register TypeEncoder for a struct field +func RegisterFieldEncoder(typ string, field string, encoder ValEncoder) { + fieldEncoders[fmt.Sprintf("%s/%s", typ, field)] = encoder +} + +// RegisterExtension register extension +func RegisterExtension(extension Extension) { + extensions = append(extensions, extension) +} + +func getTypeDecoderFromExtension(ctx *ctx, typ reflect2.Type) ValDecoder { + decoder := _getTypeDecoderFromExtension(ctx, typ) + if decoder != nil { + for _, extension := range extensions { + decoder = extension.DecorateDecoder(typ, decoder) + } + decoder = ctx.decoderExtension.DecorateDecoder(typ, decoder) + for _, extension := range ctx.extraExtensions { + decoder = extension.DecorateDecoder(typ, decoder) + } + } + return decoder +} +func _getTypeDecoderFromExtension(ctx *ctx, typ reflect2.Type) ValDecoder { + for _, extension := range extensions { + decoder := extension.CreateDecoder(typ) + if decoder != nil { + return decoder + } + } + decoder := ctx.decoderExtension.CreateDecoder(typ) + if decoder != nil { + return decoder + } + for _, extension := range ctx.extraExtensions { + decoder := extension.CreateDecoder(typ) + if decoder != nil { + return decoder + } + } + typeName := typ.String() + decoder = typeDecoders[typeName] + if decoder != nil { + return decoder + } + if typ.Kind() == reflect.Ptr { + ptrType := typ.(*reflect2.UnsafePtrType) + decoder := typeDecoders[ptrType.Elem().String()] + if decoder != nil { + return &OptionalDecoder{ptrType.Elem(), decoder} + } + } + return nil +} + +func getTypeEncoderFromExtension(ctx *ctx, typ reflect2.Type) ValEncoder { + encoder := _getTypeEncoderFromExtension(ctx, typ) + if encoder != nil { + for _, extension := range extensions { + encoder = extension.DecorateEncoder(typ, encoder) + } + encoder = ctx.encoderExtension.DecorateEncoder(typ, encoder) + for _, extension := range ctx.extraExtensions { + encoder = extension.DecorateEncoder(typ, encoder) + } + } + return encoder +} + +func _getTypeEncoderFromExtension(ctx *ctx, typ reflect2.Type) ValEncoder { + for _, extension := range extensions { + encoder := extension.CreateEncoder(typ) + if encoder != nil { + return encoder + } + } + encoder := ctx.encoderExtension.CreateEncoder(typ) + if encoder != nil { + return encoder + } + for _, extension := range ctx.extraExtensions { + encoder := extension.CreateEncoder(typ) + if encoder != nil { + return encoder + } + } + typeName := typ.String() + encoder = typeEncoders[typeName] + if encoder != nil { + return encoder + } + if typ.Kind() == reflect.Ptr { + typePtr := typ.(*reflect2.UnsafePtrType) + encoder := typeEncoders[typePtr.Elem().String()] + if encoder != nil { + return &OptionalEncoder{encoder} + } + } + return nil +} + +func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor { + structType := typ.(*reflect2.UnsafeStructType) + embeddedBindings := []*Binding{} + bindings := []*Binding{} + for i := 0; i < structType.NumField(); i++ { + field := structType.Field(i) + tag, hastag := field.Tag().Lookup(ctx.getTagKey()) + if ctx.onlyTaggedField && !hastag && !field.Anonymous() { + continue + } + tagParts := strings.Split(tag, ",") + if tag == "-" { + continue + } + if field.Anonymous() && (tag == "" || tagParts[0] == "") { + if field.Type().Kind() == reflect.Struct { + structDescriptor := describeStruct(ctx, field.Type()) + for _, binding := range structDescriptor.Fields { + binding.levels = append([]int{i}, binding.levels...) + omitempty := binding.Encoder.(*structFieldEncoder).omitempty + binding.Encoder = &structFieldEncoder{field, binding.Encoder, omitempty} + binding.Decoder = &structFieldDecoder{field, binding.Decoder} + embeddedBindings = append(embeddedBindings, binding) + } + continue + } else if field.Type().Kind() == reflect.Ptr { + ptrType := field.Type().(*reflect2.UnsafePtrType) + if ptrType.Elem().Kind() == reflect.Struct { + structDescriptor := describeStruct(ctx, ptrType.Elem()) + for _, binding := range structDescriptor.Fields { + binding.levels = append([]int{i}, binding.levels...) + omitempty := binding.Encoder.(*structFieldEncoder).omitempty + binding.Encoder = &dereferenceEncoder{binding.Encoder} + binding.Encoder = &structFieldEncoder{field, binding.Encoder, omitempty} + binding.Decoder = &dereferenceDecoder{ptrType.Elem(), binding.Decoder} + binding.Decoder = &structFieldDecoder{field, binding.Decoder} + embeddedBindings = append(embeddedBindings, binding) + } + continue + } + } + } + fieldNames := calcFieldNames(field.Name(), tagParts[0], tag) + fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name()) + decoder := fieldDecoders[fieldCacheKey] + if decoder == nil { + decoder = decoderOfType(ctx.append(field.Name()), field.Type()) + } + encoder := fieldEncoders[fieldCacheKey] + if encoder == nil { + encoder = encoderOfType(ctx.append(field.Name()), field.Type()) + } + binding := &Binding{ + Field: field, + FromNames: fieldNames, + ToNames: fieldNames, + Decoder: decoder, + Encoder: encoder, + } + binding.levels = []int{i} + bindings = append(bindings, binding) + } + return createStructDescriptor(ctx, typ, bindings, embeddedBindings) +} +func createStructDescriptor(ctx *ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor { + structDescriptor := &StructDescriptor{ + Type: typ, + Fields: bindings, + } + for _, extension := range extensions { + extension.UpdateStructDescriptor(structDescriptor) + } + ctx.encoderExtension.UpdateStructDescriptor(structDescriptor) + ctx.decoderExtension.UpdateStructDescriptor(structDescriptor) + for _, extension := range ctx.extraExtensions { + extension.UpdateStructDescriptor(structDescriptor) + } + processTags(structDescriptor, ctx.frozenConfig) + // merge normal & embedded bindings & sort with original order + allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...)) + sort.Sort(allBindings) + structDescriptor.Fields = allBindings + return structDescriptor +} + +type sortableBindings []*Binding + +func (bindings sortableBindings) Len() int { + return len(bindings) +} + +func (bindings sortableBindings) Less(i, j int) bool { + left := bindings[i].levels + right := bindings[j].levels + k := 0 + for { + if left[k] < right[k] { + return true + } else if left[k] > right[k] { + return false + } + k++ + } +} + +func (bindings sortableBindings) Swap(i, j int) { + bindings[i], bindings[j] = bindings[j], bindings[i] +} + +func processTags(structDescriptor *StructDescriptor, cfg *frozenConfig) { + for _, binding := range structDescriptor.Fields { + shouldOmitEmpty := false + tagParts := strings.Split(binding.Field.Tag().Get(cfg.getTagKey()), ",") + for _, tagPart := range tagParts[1:] { + if tagPart == "omitempty" { + shouldOmitEmpty = true + } else if tagPart == "string" { + if binding.Field.Type().Kind() == reflect.String { + binding.Decoder = &stringModeStringDecoder{binding.Decoder, cfg} + binding.Encoder = &stringModeStringEncoder{binding.Encoder, cfg} + } else { + binding.Decoder = &stringModeNumberDecoder{binding.Decoder} + binding.Encoder = &stringModeNumberEncoder{binding.Encoder} + } + } + } + binding.Decoder = &structFieldDecoder{binding.Field, binding.Decoder} + binding.Encoder = &structFieldEncoder{binding.Field, binding.Encoder, shouldOmitEmpty} + } +} + +func calcFieldNames(originalFieldName string, tagProvidedFieldName string, wholeTag string) []string { + // ignore? + if wholeTag == "-" { + return []string{} + } + // rename? + var fieldNames []string + if tagProvidedFieldName == "" { + fieldNames = []string{originalFieldName} + } else { + fieldNames = []string{tagProvidedFieldName} + } + // private? + isNotExported := unicode.IsLower(rune(originalFieldName[0])) + if isNotExported { + fieldNames = []string{} + } + return fieldNames +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/reflect_json_number.go b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_json_number.go new file mode 100644 index 0000000..98d45c1 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_json_number.go @@ -0,0 +1,112 @@ +package jsoniter + +import ( + "encoding/json" + "github.com/modern-go/reflect2" + "strconv" + "unsafe" +) + +type Number string + +// String returns the literal text of the number. +func (n Number) String() string { return string(n) } + +// Float64 returns the number as a float64. +func (n Number) Float64() (float64, error) { + return strconv.ParseFloat(string(n), 64) +} + +// Int64 returns the number as an int64. +func (n Number) Int64() (int64, error) { + return strconv.ParseInt(string(n), 10, 64) +} + +func CastJsonNumber(val interface{}) (string, bool) { + switch typedVal := val.(type) { + case json.Number: + return string(typedVal), true + case Number: + return string(typedVal), true + } + return "", false +} + +var jsonNumberType = reflect2.TypeOfPtr((*json.Number)(nil)).Elem() +var jsoniterNumberType = reflect2.TypeOfPtr((*Number)(nil)).Elem() + +func createDecoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValDecoder { + if typ.AssignableTo(jsonNumberType) { + return &jsonNumberCodec{} + } + if typ.AssignableTo(jsoniterNumberType) { + return &jsoniterNumberCodec{} + } + return nil +} + +func createEncoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValEncoder { + if typ.AssignableTo(jsonNumberType) { + return &jsonNumberCodec{} + } + if typ.AssignableTo(jsoniterNumberType) { + return &jsoniterNumberCodec{} + } + return nil +} + +type jsonNumberCodec struct { +} + +func (codec *jsonNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + switch iter.WhatIsNext() { + case StringValue: + *((*json.Number)(ptr)) = json.Number(iter.ReadString()) + case NilValue: + iter.skipFourBytes('n', 'u', 'l', 'l') + *((*json.Number)(ptr)) = "" + default: + *((*json.Number)(ptr)) = json.Number([]byte(iter.readNumberAsString())) + } +} + +func (codec *jsonNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + number := *((*json.Number)(ptr)) + if len(number) == 0 { + stream.writeByte('0') + } else { + stream.WriteRaw(string(number)) + } +} + +func (codec *jsonNumberCodec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*json.Number)(ptr))) == 0 +} + +type jsoniterNumberCodec struct { +} + +func (codec *jsoniterNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + switch iter.WhatIsNext() { + case StringValue: + *((*Number)(ptr)) = Number(iter.ReadString()) + case NilValue: + iter.skipFourBytes('n', 'u', 'l', 'l') + *((*Number)(ptr)) = "" + default: + *((*Number)(ptr)) = Number([]byte(iter.readNumberAsString())) + } +} + +func (codec *jsoniterNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + number := *((*Number)(ptr)) + if len(number) == 0 { + stream.writeByte('0') + } else { + stream.WriteRaw(string(number)) + } +} + +func (codec *jsoniterNumberCodec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*Number)(ptr))) == 0 +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/reflect_json_raw_message.go b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_json_raw_message.go new file mode 100644 index 0000000..f261993 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_json_raw_message.go @@ -0,0 +1,60 @@ +package jsoniter + +import ( + "encoding/json" + "github.com/modern-go/reflect2" + "unsafe" +) + +var jsonRawMessageType = reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem() +var jsoniterRawMessageType = reflect2.TypeOfPtr((*RawMessage)(nil)).Elem() + +func createEncoderOfJsonRawMessage(ctx *ctx, typ reflect2.Type) ValEncoder { + if typ == jsonRawMessageType { + return &jsonRawMessageCodec{} + } + if typ == jsoniterRawMessageType { + return &jsoniterRawMessageCodec{} + } + return nil +} + +func createDecoderOfJsonRawMessage(ctx *ctx, typ reflect2.Type) ValDecoder { + if typ == jsonRawMessageType { + return &jsonRawMessageCodec{} + } + if typ == jsoniterRawMessageType { + return &jsoniterRawMessageCodec{} + } + return nil +} + +type jsonRawMessageCodec struct { +} + +func (codec *jsonRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + *((*json.RawMessage)(ptr)) = json.RawMessage(iter.SkipAndReturnBytes()) +} + +func (codec *jsonRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteRaw(string(*((*json.RawMessage)(ptr)))) +} + +func (codec *jsonRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*json.RawMessage)(ptr))) == 0 +} + +type jsoniterRawMessageCodec struct { +} + +func (codec *jsoniterRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + *((*RawMessage)(ptr)) = RawMessage(iter.SkipAndReturnBytes()) +} + +func (codec *jsoniterRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteRaw(string(*((*RawMessage)(ptr)))) +} + +func (codec *jsoniterRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*RawMessage)(ptr))) == 0 +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/reflect_map.go b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_map.go new file mode 100644 index 0000000..547b442 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_map.go @@ -0,0 +1,338 @@ +package jsoniter + +import ( + "fmt" + "github.com/modern-go/reflect2" + "io" + "reflect" + "sort" + "unsafe" +) + +func decoderOfMap(ctx *ctx, typ reflect2.Type) ValDecoder { + mapType := typ.(*reflect2.UnsafeMapType) + keyDecoder := decoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()) + elemDecoder := decoderOfType(ctx.append("[mapElem]"), mapType.Elem()) + return &mapDecoder{ + mapType: mapType, + keyType: mapType.Key(), + elemType: mapType.Elem(), + keyDecoder: keyDecoder, + elemDecoder: elemDecoder, + } +} + +func encoderOfMap(ctx *ctx, typ reflect2.Type) ValEncoder { + mapType := typ.(*reflect2.UnsafeMapType) + if ctx.sortMapKeys { + return &sortKeysMapEncoder{ + mapType: mapType, + keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()), + elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()), + } + } + return &mapEncoder{ + mapType: mapType, + keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()), + elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()), + } +} + +func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder { + decoder := ctx.decoderExtension.CreateMapKeyDecoder(typ) + if decoder != nil { + return decoder + } + for _, extension := range ctx.extraExtensions { + decoder := extension.CreateMapKeyDecoder(typ) + if decoder != nil { + return decoder + } + } + switch typ.Kind() { + case reflect.String: + return decoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String)) + case reflect.Bool, + reflect.Uint8, reflect.Int8, + reflect.Uint16, reflect.Int16, + reflect.Uint32, reflect.Int32, + reflect.Uint64, reflect.Int64, + reflect.Uint, reflect.Int, + reflect.Float32, reflect.Float64, + reflect.Uintptr: + typ = reflect2.DefaultTypeOfKind(typ.Kind()) + return &numericMapKeyDecoder{decoderOfType(ctx, typ)} + default: + ptrType := reflect2.PtrTo(typ) + if ptrType.Implements(unmarshalerType) { + return &referenceDecoder{ + &unmarshalerDecoder{ + valType: ptrType, + }, + } + } + if typ.Implements(unmarshalerType) { + return &unmarshalerDecoder{ + valType: typ, + } + } + if ptrType.Implements(textUnmarshalerType) { + return &referenceDecoder{ + &textUnmarshalerDecoder{ + valType: ptrType, + }, + } + } + if typ.Implements(textUnmarshalerType) { + return &textUnmarshalerDecoder{ + valType: typ, + } + } + return &lazyErrorDecoder{err: fmt.Errorf("unsupported map key type: %v", typ)} + } +} + +func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder { + encoder := ctx.encoderExtension.CreateMapKeyEncoder(typ) + if encoder != nil { + return encoder + } + for _, extension := range ctx.extraExtensions { + encoder := extension.CreateMapKeyEncoder(typ) + if encoder != nil { + return encoder + } + } + switch typ.Kind() { + case reflect.String: + return encoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String)) + case reflect.Bool, + reflect.Uint8, reflect.Int8, + reflect.Uint16, reflect.Int16, + reflect.Uint32, reflect.Int32, + reflect.Uint64, reflect.Int64, + reflect.Uint, reflect.Int, + reflect.Float32, reflect.Float64, + reflect.Uintptr: + typ = reflect2.DefaultTypeOfKind(typ.Kind()) + return &numericMapKeyEncoder{encoderOfType(ctx, typ)} + default: + if typ == textMarshalerType { + return &directTextMarshalerEncoder{ + stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), + } + } + if typ.Implements(textMarshalerType) { + return &textMarshalerEncoder{ + valType: typ, + stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), + } + } + if typ.Kind() == reflect.Interface { + return &dynamicMapKeyEncoder{ctx, typ} + } + return &lazyErrorEncoder{err: fmt.Errorf("unsupported map key type: %v", typ)} + } +} + +type mapDecoder struct { + mapType *reflect2.UnsafeMapType + keyType reflect2.Type + elemType reflect2.Type + keyDecoder ValDecoder + elemDecoder ValDecoder +} + +func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + mapType := decoder.mapType + c := iter.nextToken() + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + *(*unsafe.Pointer)(ptr) = nil + mapType.UnsafeSet(ptr, mapType.UnsafeNew()) + return + } + if mapType.UnsafeIsNil(ptr) { + mapType.UnsafeSet(ptr, mapType.UnsafeMakeMap(0)) + } + if c != '{' { + iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c})) + return + } + c = iter.nextToken() + if c == '}' { + return + } + if c != '"' { + iter.ReportError("ReadMapCB", `expect " after }, but found `+string([]byte{c})) + return + } + iter.unreadByte() + key := decoder.keyType.UnsafeNew() + decoder.keyDecoder.Decode(key, iter) + c = iter.nextToken() + if c != ':' { + iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c})) + return + } + elem := decoder.elemType.UnsafeNew() + decoder.elemDecoder.Decode(elem, iter) + decoder.mapType.UnsafeSetIndex(ptr, key, elem) + for c = iter.nextToken(); c == ','; c = iter.nextToken() { + key := decoder.keyType.UnsafeNew() + decoder.keyDecoder.Decode(key, iter) + c = iter.nextToken() + if c != ':' { + iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c})) + return + } + elem := decoder.elemType.UnsafeNew() + decoder.elemDecoder.Decode(elem, iter) + decoder.mapType.UnsafeSetIndex(ptr, key, elem) + } + if c != '}' { + iter.ReportError("ReadMapCB", `expect }, but found `+string([]byte{c})) + } +} + +type numericMapKeyDecoder struct { + decoder ValDecoder +} + +func (decoder *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + c := iter.nextToken() + if c != '"' { + iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c})) + return + } + decoder.decoder.Decode(ptr, iter) + c = iter.nextToken() + if c != '"' { + iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c})) + return + } +} + +type numericMapKeyEncoder struct { + encoder ValEncoder +} + +func (encoder *numericMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.writeByte('"') + encoder.encoder.Encode(ptr, stream) + stream.writeByte('"') +} + +func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return false +} + +type dynamicMapKeyEncoder struct { + ctx *ctx + valType reflect2.Type +} + +func (encoder *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + obj := encoder.valType.UnsafeIndirect(ptr) + encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).Encode(reflect2.PtrOf(obj), stream) +} + +func (encoder *dynamicMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool { + obj := encoder.valType.UnsafeIndirect(ptr) + return encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).IsEmpty(reflect2.PtrOf(obj)) +} + +type mapEncoder struct { + mapType *reflect2.UnsafeMapType + keyEncoder ValEncoder + elemEncoder ValEncoder +} + +func (encoder *mapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteObjectStart() + iter := encoder.mapType.UnsafeIterate(ptr) + for i := 0; iter.HasNext(); i++ { + if i != 0 { + stream.WriteMore() + } + key, elem := iter.UnsafeNext() + encoder.keyEncoder.Encode(key, stream) + if stream.indention > 0 { + stream.writeTwoBytes(byte(':'), byte(' ')) + } else { + stream.writeByte(':') + } + encoder.elemEncoder.Encode(elem, stream) + } + stream.WriteObjectEnd() +} + +func (encoder *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool { + iter := encoder.mapType.UnsafeIterate(ptr) + return !iter.HasNext() +} + +type sortKeysMapEncoder struct { + mapType *reflect2.UnsafeMapType + keyEncoder ValEncoder + elemEncoder ValEncoder +} + +func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + if *(*unsafe.Pointer)(ptr) == nil { + stream.WriteNil() + return + } + stream.WriteObjectStart() + mapIter := encoder.mapType.UnsafeIterate(ptr) + subStream := stream.cfg.BorrowStream(nil) + subIter := stream.cfg.BorrowIterator(nil) + keyValues := encodedKeyValues{} + for mapIter.HasNext() { + subStream.buf = make([]byte, 0, 64) + key, elem := mapIter.UnsafeNext() + encoder.keyEncoder.Encode(key, subStream) + if subStream.Error != nil && subStream.Error != io.EOF && stream.Error == nil { + stream.Error = subStream.Error + } + encodedKey := subStream.Buffer() + subIter.ResetBytes(encodedKey) + decodedKey := subIter.ReadString() + if stream.indention > 0 { + subStream.writeTwoBytes(byte(':'), byte(' ')) + } else { + subStream.writeByte(':') + } + encoder.elemEncoder.Encode(elem, subStream) + keyValues = append(keyValues, encodedKV{ + key: decodedKey, + keyValue: subStream.Buffer(), + }) + } + sort.Sort(keyValues) + for i, keyValue := range keyValues { + if i != 0 { + stream.WriteMore() + } + stream.Write(keyValue.keyValue) + } + stream.WriteObjectEnd() + stream.cfg.ReturnStream(subStream) + stream.cfg.ReturnIterator(subIter) +} + +func (encoder *sortKeysMapEncoder) IsEmpty(ptr unsafe.Pointer) bool { + iter := encoder.mapType.UnsafeIterate(ptr) + return !iter.HasNext() +} + +type encodedKeyValues []encodedKV + +type encodedKV struct { + key string + keyValue []byte +} + +func (sv encodedKeyValues) Len() int { return len(sv) } +func (sv encodedKeyValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } +func (sv encodedKeyValues) Less(i, j int) bool { return sv[i].key < sv[j].key } diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/reflect_marshaler.go b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_marshaler.go new file mode 100644 index 0000000..fea5071 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_marshaler.go @@ -0,0 +1,217 @@ +package jsoniter + +import ( + "encoding" + "encoding/json" + "github.com/modern-go/reflect2" + "unsafe" +) + +var marshalerType = reflect2.TypeOfPtr((*json.Marshaler)(nil)).Elem() +var unmarshalerType = reflect2.TypeOfPtr((*json.Unmarshaler)(nil)).Elem() +var textMarshalerType = reflect2.TypeOfPtr((*encoding.TextMarshaler)(nil)).Elem() +var textUnmarshalerType = reflect2.TypeOfPtr((*encoding.TextUnmarshaler)(nil)).Elem() + +func createDecoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValDecoder { + ptrType := reflect2.PtrTo(typ) + if ptrType.Implements(unmarshalerType) { + return &referenceDecoder{ + &unmarshalerDecoder{ptrType}, + } + } + if ptrType.Implements(textUnmarshalerType) { + return &referenceDecoder{ + &textUnmarshalerDecoder{ptrType}, + } + } + return nil +} + +func createEncoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValEncoder { + if typ == marshalerType { + checkIsEmpty := createCheckIsEmpty(ctx, typ) + var encoder ValEncoder = &directMarshalerEncoder{ + checkIsEmpty: checkIsEmpty, + } + return encoder + } + if typ.Implements(marshalerType) { + checkIsEmpty := createCheckIsEmpty(ctx, typ) + var encoder ValEncoder = &marshalerEncoder{ + valType: typ, + checkIsEmpty: checkIsEmpty, + } + return encoder + } + ptrType := reflect2.PtrTo(typ) + if ctx.prefix != "" && ptrType.Implements(marshalerType) { + checkIsEmpty := createCheckIsEmpty(ctx, ptrType) + var encoder ValEncoder = &marshalerEncoder{ + valType: ptrType, + checkIsEmpty: checkIsEmpty, + } + return &referenceEncoder{encoder} + } + if typ == textMarshalerType { + checkIsEmpty := createCheckIsEmpty(ctx, typ) + var encoder ValEncoder = &directTextMarshalerEncoder{ + checkIsEmpty: checkIsEmpty, + stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), + } + return encoder + } + if typ.Implements(textMarshalerType) { + checkIsEmpty := createCheckIsEmpty(ctx, typ) + var encoder ValEncoder = &textMarshalerEncoder{ + valType: typ, + stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), + checkIsEmpty: checkIsEmpty, + } + return encoder + } + // if prefix is empty, the type is the root type + if ctx.prefix != "" && ptrType.Implements(textMarshalerType) { + checkIsEmpty := createCheckIsEmpty(ctx, ptrType) + var encoder ValEncoder = &textMarshalerEncoder{ + valType: ptrType, + stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), + checkIsEmpty: checkIsEmpty, + } + return &referenceEncoder{encoder} + } + return nil +} + +type marshalerEncoder struct { + checkIsEmpty checkIsEmpty + valType reflect2.Type +} + +func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + obj := encoder.valType.UnsafeIndirect(ptr) + if encoder.valType.IsNullable() && reflect2.IsNil(obj) { + stream.WriteNil() + return + } + bytes, err := json.Marshal(obj) + if err != nil { + stream.Error = err + } else { + stream.Write(bytes) + } +} + +func (encoder *marshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.checkIsEmpty.IsEmpty(ptr) +} + +type directMarshalerEncoder struct { + checkIsEmpty checkIsEmpty +} + +func (encoder *directMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + marshaler := *(*json.Marshaler)(ptr) + if marshaler == nil { + stream.WriteNil() + return + } + bytes, err := marshaler.MarshalJSON() + if err != nil { + stream.Error = err + } else { + stream.Write(bytes) + } +} + +func (encoder *directMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.checkIsEmpty.IsEmpty(ptr) +} + +type textMarshalerEncoder struct { + valType reflect2.Type + stringEncoder ValEncoder + checkIsEmpty checkIsEmpty +} + +func (encoder *textMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + obj := encoder.valType.UnsafeIndirect(ptr) + if encoder.valType.IsNullable() && reflect2.IsNil(obj) { + stream.WriteNil() + return + } + marshaler := (obj).(encoding.TextMarshaler) + bytes, err := marshaler.MarshalText() + if err != nil { + stream.Error = err + } else { + str := string(bytes) + encoder.stringEncoder.Encode(unsafe.Pointer(&str), stream) + } +} + +func (encoder *textMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.checkIsEmpty.IsEmpty(ptr) +} + +type directTextMarshalerEncoder struct { + stringEncoder ValEncoder + checkIsEmpty checkIsEmpty +} + +func (encoder *directTextMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + marshaler := *(*encoding.TextMarshaler)(ptr) + if marshaler == nil { + stream.WriteNil() + return + } + bytes, err := marshaler.MarshalText() + if err != nil { + stream.Error = err + } else { + str := string(bytes) + encoder.stringEncoder.Encode(unsafe.Pointer(&str), stream) + } +} + +func (encoder *directTextMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.checkIsEmpty.IsEmpty(ptr) +} + +type unmarshalerDecoder struct { + valType reflect2.Type +} + +func (decoder *unmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + valType := decoder.valType + obj := valType.UnsafeIndirect(ptr) + unmarshaler := obj.(json.Unmarshaler) + iter.nextToken() + iter.unreadByte() // skip spaces + bytes := iter.SkipAndReturnBytes() + err := unmarshaler.UnmarshalJSON(bytes) + if err != nil { + iter.ReportError("unmarshalerDecoder", err.Error()) + } +} + +type textUnmarshalerDecoder struct { + valType reflect2.Type +} + +func (decoder *textUnmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + valType := decoder.valType + obj := valType.UnsafeIndirect(ptr) + if reflect2.IsNil(obj) { + ptrType := valType.(*reflect2.UnsafePtrType) + elemType := ptrType.Elem() + elem := elemType.UnsafeNew() + ptrType.UnsafeSet(ptr, unsafe.Pointer(&elem)) + obj = valType.UnsafeIndirect(ptr) + } + unmarshaler := (obj).(encoding.TextUnmarshaler) + str := iter.ReadString() + err := unmarshaler.UnmarshalText([]byte(str)) + if err != nil { + iter.ReportError("textUnmarshalerDecoder", err.Error()) + } +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/reflect_native.go b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_native.go new file mode 100644 index 0000000..9042eb0 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_native.go @@ -0,0 +1,451 @@ +package jsoniter + +import ( + "encoding/base64" + "reflect" + "strconv" + "unsafe" + + "github.com/modern-go/reflect2" +) + +const ptrSize = 32 << uintptr(^uintptr(0)>>63) + +func createEncoderOfNative(ctx *ctx, typ reflect2.Type) ValEncoder { + if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 { + sliceDecoder := decoderOfSlice(ctx, typ) + return &base64Codec{sliceDecoder: sliceDecoder} + } + typeName := typ.String() + kind := typ.Kind() + switch kind { + case reflect.String: + if typeName != "string" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*string)(nil)).Elem()) + } + return &stringCodec{} + case reflect.Int: + if typeName != "int" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*int)(nil)).Elem()) + } + if strconv.IntSize == 32 { + return &int32Codec{} + } + return &int64Codec{} + case reflect.Int8: + if typeName != "int8" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*int8)(nil)).Elem()) + } + return &int8Codec{} + case reflect.Int16: + if typeName != "int16" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*int16)(nil)).Elem()) + } + return &int16Codec{} + case reflect.Int32: + if typeName != "int32" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*int32)(nil)).Elem()) + } + return &int32Codec{} + case reflect.Int64: + if typeName != "int64" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*int64)(nil)).Elem()) + } + return &int64Codec{} + case reflect.Uint: + if typeName != "uint" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*uint)(nil)).Elem()) + } + if strconv.IntSize == 32 { + return &uint32Codec{} + } + return &uint64Codec{} + case reflect.Uint8: + if typeName != "uint8" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*uint8)(nil)).Elem()) + } + return &uint8Codec{} + case reflect.Uint16: + if typeName != "uint16" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*uint16)(nil)).Elem()) + } + return &uint16Codec{} + case reflect.Uint32: + if typeName != "uint32" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*uint32)(nil)).Elem()) + } + return &uint32Codec{} + case reflect.Uintptr: + if typeName != "uintptr" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*uintptr)(nil)).Elem()) + } + if ptrSize == 32 { + return &uint32Codec{} + } + return &uint64Codec{} + case reflect.Uint64: + if typeName != "uint64" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*uint64)(nil)).Elem()) + } + return &uint64Codec{} + case reflect.Float32: + if typeName != "float32" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*float32)(nil)).Elem()) + } + return &float32Codec{} + case reflect.Float64: + if typeName != "float64" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*float64)(nil)).Elem()) + } + return &float64Codec{} + case reflect.Bool: + if typeName != "bool" { + return encoderOfType(ctx, reflect2.TypeOfPtr((*bool)(nil)).Elem()) + } + return &boolCodec{} + } + return nil +} + +func createDecoderOfNative(ctx *ctx, typ reflect2.Type) ValDecoder { + if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 { + sliceDecoder := decoderOfSlice(ctx, typ) + return &base64Codec{sliceDecoder: sliceDecoder} + } + typeName := typ.String() + switch typ.Kind() { + case reflect.String: + if typeName != "string" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*string)(nil)).Elem()) + } + return &stringCodec{} + case reflect.Int: + if typeName != "int" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*int)(nil)).Elem()) + } + if strconv.IntSize == 32 { + return &int32Codec{} + } + return &int64Codec{} + case reflect.Int8: + if typeName != "int8" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*int8)(nil)).Elem()) + } + return &int8Codec{} + case reflect.Int16: + if typeName != "int16" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*int16)(nil)).Elem()) + } + return &int16Codec{} + case reflect.Int32: + if typeName != "int32" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*int32)(nil)).Elem()) + } + return &int32Codec{} + case reflect.Int64: + if typeName != "int64" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*int64)(nil)).Elem()) + } + return &int64Codec{} + case reflect.Uint: + if typeName != "uint" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*uint)(nil)).Elem()) + } + if strconv.IntSize == 32 { + return &uint32Codec{} + } + return &uint64Codec{} + case reflect.Uint8: + if typeName != "uint8" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*uint8)(nil)).Elem()) + } + return &uint8Codec{} + case reflect.Uint16: + if typeName != "uint16" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*uint16)(nil)).Elem()) + } + return &uint16Codec{} + case reflect.Uint32: + if typeName != "uint32" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*uint32)(nil)).Elem()) + } + return &uint32Codec{} + case reflect.Uintptr: + if typeName != "uintptr" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*uintptr)(nil)).Elem()) + } + if ptrSize == 32 { + return &uint32Codec{} + } + return &uint64Codec{} + case reflect.Uint64: + if typeName != "uint64" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*uint64)(nil)).Elem()) + } + return &uint64Codec{} + case reflect.Float32: + if typeName != "float32" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*float32)(nil)).Elem()) + } + return &float32Codec{} + case reflect.Float64: + if typeName != "float64" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*float64)(nil)).Elem()) + } + return &float64Codec{} + case reflect.Bool: + if typeName != "bool" { + return decoderOfType(ctx, reflect2.TypeOfPtr((*bool)(nil)).Elem()) + } + return &boolCodec{} + } + return nil +} + +type stringCodec struct { +} + +func (codec *stringCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + *((*string)(ptr)) = iter.ReadString() +} + +func (codec *stringCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + str := *((*string)(ptr)) + stream.WriteString(str) +} + +func (codec *stringCodec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*string)(ptr)) == "" +} + +type int8Codec struct { +} + +func (codec *int8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*int8)(ptr)) = iter.ReadInt8() + } +} + +func (codec *int8Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteInt8(*((*int8)(ptr))) +} + +func (codec *int8Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*int8)(ptr)) == 0 +} + +type int16Codec struct { +} + +func (codec *int16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*int16)(ptr)) = iter.ReadInt16() + } +} + +func (codec *int16Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteInt16(*((*int16)(ptr))) +} + +func (codec *int16Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*int16)(ptr)) == 0 +} + +type int32Codec struct { +} + +func (codec *int32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*int32)(ptr)) = iter.ReadInt32() + } +} + +func (codec *int32Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteInt32(*((*int32)(ptr))) +} + +func (codec *int32Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*int32)(ptr)) == 0 +} + +type int64Codec struct { +} + +func (codec *int64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*int64)(ptr)) = iter.ReadInt64() + } +} + +func (codec *int64Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteInt64(*((*int64)(ptr))) +} + +func (codec *int64Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*int64)(ptr)) == 0 +} + +type uint8Codec struct { +} + +func (codec *uint8Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*uint8)(ptr)) = iter.ReadUint8() + } +} + +func (codec *uint8Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteUint8(*((*uint8)(ptr))) +} + +func (codec *uint8Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*uint8)(ptr)) == 0 +} + +type uint16Codec struct { +} + +func (codec *uint16Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*uint16)(ptr)) = iter.ReadUint16() + } +} + +func (codec *uint16Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteUint16(*((*uint16)(ptr))) +} + +func (codec *uint16Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*uint16)(ptr)) == 0 +} + +type uint32Codec struct { +} + +func (codec *uint32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*uint32)(ptr)) = iter.ReadUint32() + } +} + +func (codec *uint32Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteUint32(*((*uint32)(ptr))) +} + +func (codec *uint32Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*uint32)(ptr)) == 0 +} + +type uint64Codec struct { +} + +func (codec *uint64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*uint64)(ptr)) = iter.ReadUint64() + } +} + +func (codec *uint64Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteUint64(*((*uint64)(ptr))) +} + +func (codec *uint64Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*uint64)(ptr)) == 0 +} + +type float32Codec struct { +} + +func (codec *float32Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*float32)(ptr)) = iter.ReadFloat32() + } +} + +func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteFloat32(*((*float32)(ptr))) +} + +func (codec *float32Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*float32)(ptr)) == 0 +} + +type float64Codec struct { +} + +func (codec *float64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*float64)(ptr)) = iter.ReadFloat64() + } +} + +func (codec *float64Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteFloat64(*((*float64)(ptr))) +} + +func (codec *float64Codec) IsEmpty(ptr unsafe.Pointer) bool { + return *((*float64)(ptr)) == 0 +} + +type boolCodec struct { +} + +func (codec *boolCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.ReadNil() { + *((*bool)(ptr)) = iter.ReadBool() + } +} + +func (codec *boolCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteBool(*((*bool)(ptr))) +} + +func (codec *boolCodec) IsEmpty(ptr unsafe.Pointer) bool { + return !(*((*bool)(ptr))) +} + +type base64Codec struct { + sliceType *reflect2.UnsafeSliceType + sliceDecoder ValDecoder +} + +func (codec *base64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) { + if iter.ReadNil() { + codec.sliceType.UnsafeSetNil(ptr) + return + } + switch iter.WhatIsNext() { + case StringValue: + src := iter.ReadString() + dst, err := base64.StdEncoding.DecodeString(src) + if err != nil { + iter.ReportError("decode base64", err.Error()) + } else { + codec.sliceType.UnsafeSet(ptr, unsafe.Pointer(&dst)) + } + case ArrayValue: + codec.sliceDecoder.Decode(ptr, iter) + default: + iter.ReportError("base64Codec", "invalid input") + } +} + +func (codec *base64Codec) Encode(ptr unsafe.Pointer, stream *Stream) { + src := *((*[]byte)(ptr)) + if len(src) == 0 { + stream.WriteNil() + return + } + encoding := base64.StdEncoding + stream.writeByte('"') + size := encoding.EncodedLen(len(src)) + buf := make([]byte, size) + encoding.Encode(buf, src) + stream.buf = append(stream.buf, buf...) + stream.writeByte('"') +} + +func (codec *base64Codec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*[]byte)(ptr))) == 0 +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/reflect_optional.go b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_optional.go new file mode 100644 index 0000000..43ec71d --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_optional.go @@ -0,0 +1,133 @@ +package jsoniter + +import ( + "github.com/modern-go/reflect2" + "reflect" + "unsafe" +) + +func decoderOfOptional(ctx *ctx, typ reflect2.Type) ValDecoder { + ptrType := typ.(*reflect2.UnsafePtrType) + elemType := ptrType.Elem() + decoder := decoderOfType(ctx, elemType) + if ctx.prefix == "" && elemType.Kind() == reflect.Ptr { + return &dereferenceDecoder{elemType, decoder} + } + return &OptionalDecoder{elemType, decoder} +} + +func encoderOfOptional(ctx *ctx, typ reflect2.Type) ValEncoder { + ptrType := typ.(*reflect2.UnsafePtrType) + elemType := ptrType.Elem() + elemEncoder := encoderOfType(ctx, elemType) + encoder := &OptionalEncoder{elemEncoder} + return encoder +} + +type OptionalDecoder struct { + ValueType reflect2.Type + ValueDecoder ValDecoder +} + +func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if iter.ReadNil() { + *((*unsafe.Pointer)(ptr)) = nil + } else { + if *((*unsafe.Pointer)(ptr)) == nil { + //pointer to null, we have to allocate memory to hold the value + newPtr := decoder.ValueType.UnsafeNew() + decoder.ValueDecoder.Decode(newPtr, iter) + *((*unsafe.Pointer)(ptr)) = newPtr + } else { + //reuse existing instance + decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter) + } + } +} + +type dereferenceDecoder struct { + // only to deference a pointer + valueType reflect2.Type + valueDecoder ValDecoder +} + +func (decoder *dereferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if *((*unsafe.Pointer)(ptr)) == nil { + //pointer to null, we have to allocate memory to hold the value + newPtr := decoder.valueType.UnsafeNew() + decoder.valueDecoder.Decode(newPtr, iter) + *((*unsafe.Pointer)(ptr)) = newPtr + } else { + //reuse existing instance + decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter) + } +} + +type OptionalEncoder struct { + ValueEncoder ValEncoder +} + +func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + if *((*unsafe.Pointer)(ptr)) == nil { + stream.WriteNil() + } else { + encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream) + } +} + +func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return *((*unsafe.Pointer)(ptr)) == nil +} + +type dereferenceEncoder struct { + ValueEncoder ValEncoder +} + +func (encoder *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + if *((*unsafe.Pointer)(ptr)) == nil { + stream.WriteNil() + } else { + encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream) + } +} + +func (encoder *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool { + dePtr := *((*unsafe.Pointer)(ptr)) + if dePtr == nil { + return true + } + return encoder.ValueEncoder.IsEmpty(dePtr) +} + +func (encoder *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool { + deReferenced := *((*unsafe.Pointer)(ptr)) + if deReferenced == nil { + return true + } + isEmbeddedPtrNil, converted := encoder.ValueEncoder.(IsEmbeddedPtrNil) + if !converted { + return false + } + fieldPtr := unsafe.Pointer(deReferenced) + return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr) +} + +type referenceEncoder struct { + encoder ValEncoder +} + +func (encoder *referenceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + encoder.encoder.Encode(unsafe.Pointer(&ptr), stream) +} + +func (encoder *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr)) +} + +type referenceDecoder struct { + decoder ValDecoder +} + +func (decoder *referenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + decoder.decoder.Decode(unsafe.Pointer(&ptr), iter) +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/reflect_slice.go b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_slice.go new file mode 100644 index 0000000..9441d79 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_slice.go @@ -0,0 +1,99 @@ +package jsoniter + +import ( + "fmt" + "github.com/modern-go/reflect2" + "io" + "unsafe" +) + +func decoderOfSlice(ctx *ctx, typ reflect2.Type) ValDecoder { + sliceType := typ.(*reflect2.UnsafeSliceType) + decoder := decoderOfType(ctx.append("[sliceElem]"), sliceType.Elem()) + return &sliceDecoder{sliceType, decoder} +} + +func encoderOfSlice(ctx *ctx, typ reflect2.Type) ValEncoder { + sliceType := typ.(*reflect2.UnsafeSliceType) + encoder := encoderOfType(ctx.append("[sliceElem]"), sliceType.Elem()) + return &sliceEncoder{sliceType, encoder} +} + +type sliceEncoder struct { + sliceType *reflect2.UnsafeSliceType + elemEncoder ValEncoder +} + +func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + if encoder.sliceType.UnsafeIsNil(ptr) { + stream.WriteNil() + return + } + length := encoder.sliceType.UnsafeLengthOf(ptr) + if length == 0 { + stream.WriteEmptyArray() + return + } + stream.WriteArrayStart() + encoder.elemEncoder.Encode(encoder.sliceType.UnsafeGetIndex(ptr, 0), stream) + for i := 1; i < length; i++ { + stream.WriteMore() + elemPtr := encoder.sliceType.UnsafeGetIndex(ptr, i) + encoder.elemEncoder.Encode(elemPtr, stream) + } + stream.WriteArrayEnd() + if stream.Error != nil && stream.Error != io.EOF { + stream.Error = fmt.Errorf("%v: %s", encoder.sliceType, stream.Error.Error()) + } +} + +func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.sliceType.UnsafeLengthOf(ptr) == 0 +} + +type sliceDecoder struct { + sliceType *reflect2.UnsafeSliceType + elemDecoder ValDecoder +} + +func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + decoder.doDecode(ptr, iter) + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v: %s", decoder.sliceType, iter.Error.Error()) + } +} + +func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) { + c := iter.nextToken() + sliceType := decoder.sliceType + if c == 'n' { + iter.skipThreeBytes('u', 'l', 'l') + sliceType.UnsafeSetNil(ptr) + return + } + if c != '[' { + iter.ReportError("decode slice", "expect [ or n, but found "+string([]byte{c})) + return + } + c = iter.nextToken() + if c == ']' { + sliceType.UnsafeSet(ptr, sliceType.UnsafeMakeSlice(0, 0)) + return + } + iter.unreadByte() + sliceType.UnsafeGrow(ptr, 1) + elemPtr := sliceType.UnsafeGetIndex(ptr, 0) + decoder.elemDecoder.Decode(elemPtr, iter) + length := 1 + for c = iter.nextToken(); c == ','; c = iter.nextToken() { + idx := length + length += 1 + sliceType.UnsafeGrow(ptr, length) + elemPtr = sliceType.UnsafeGetIndex(ptr, idx) + decoder.elemDecoder.Decode(elemPtr, iter) + } + if c != ']' { + iter.ReportError("decode slice", "expect ], but found "+string([]byte{c})) + return + } +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/reflect_struct_decoder.go b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_struct_decoder.go new file mode 100644 index 0000000..355d2d1 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_struct_decoder.go @@ -0,0 +1,1048 @@ +package jsoniter + +import ( + "fmt" + "io" + "strings" + "unsafe" + + "github.com/modern-go/reflect2" +) + +func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder { + bindings := map[string]*Binding{} + structDescriptor := describeStruct(ctx, typ) + for _, binding := range structDescriptor.Fields { + for _, fromName := range binding.FromNames { + old := bindings[fromName] + if old == nil { + bindings[fromName] = binding + continue + } + ignoreOld, ignoreNew := resolveConflictBinding(ctx.frozenConfig, old, binding) + if ignoreOld { + delete(bindings, fromName) + } + if !ignoreNew { + bindings[fromName] = binding + } + } + } + fields := map[string]*structFieldDecoder{} + for k, binding := range bindings { + fields[k] = binding.Decoder.(*structFieldDecoder) + } + + if !ctx.caseSensitive() { + for k, binding := range bindings { + if _, found := fields[strings.ToLower(k)]; !found { + fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder) + } + } + } + + return createStructDecoder(ctx, typ, fields) +} + +func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structFieldDecoder) ValDecoder { + if ctx.disallowUnknownFields { + return &generalStructDecoder{typ: typ, fields: fields, disallowUnknownFields: true} + } + knownHash := map[int64]struct{}{ + 0: {}, + } + + switch len(fields) { + case 0: + return &skipObjectDecoder{typ} + case 1: + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder} + } + case 2: + var fieldHash1 int64 + var fieldHash2 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldHash1 == 0 { + fieldHash1 = fieldHash + fieldDecoder1 = fieldDecoder + } else { + fieldHash2 = fieldHash + fieldDecoder2 = fieldDecoder + } + } + return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2} + case 3: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } + } + return &threeFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3} + case 4: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } + } + return &fourFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4} + case 5: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldName5 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + var fieldDecoder5 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else if fieldName4 == 0 { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } else { + fieldName5 = fieldHash + fieldDecoder5 = fieldDecoder + } + } + return &fiveFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4, + fieldName5, fieldDecoder5} + case 6: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldName5 int64 + var fieldName6 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + var fieldDecoder5 *structFieldDecoder + var fieldDecoder6 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else if fieldName4 == 0 { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } else if fieldName5 == 0 { + fieldName5 = fieldHash + fieldDecoder5 = fieldDecoder + } else { + fieldName6 = fieldHash + fieldDecoder6 = fieldDecoder + } + } + return &sixFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4, + fieldName5, fieldDecoder5, + fieldName6, fieldDecoder6} + case 7: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldName5 int64 + var fieldName6 int64 + var fieldName7 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + var fieldDecoder5 *structFieldDecoder + var fieldDecoder6 *structFieldDecoder + var fieldDecoder7 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else if fieldName4 == 0 { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } else if fieldName5 == 0 { + fieldName5 = fieldHash + fieldDecoder5 = fieldDecoder + } else if fieldName6 == 0 { + fieldName6 = fieldHash + fieldDecoder6 = fieldDecoder + } else { + fieldName7 = fieldHash + fieldDecoder7 = fieldDecoder + } + } + return &sevenFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4, + fieldName5, fieldDecoder5, + fieldName6, fieldDecoder6, + fieldName7, fieldDecoder7} + case 8: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldName5 int64 + var fieldName6 int64 + var fieldName7 int64 + var fieldName8 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + var fieldDecoder5 *structFieldDecoder + var fieldDecoder6 *structFieldDecoder + var fieldDecoder7 *structFieldDecoder + var fieldDecoder8 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else if fieldName4 == 0 { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } else if fieldName5 == 0 { + fieldName5 = fieldHash + fieldDecoder5 = fieldDecoder + } else if fieldName6 == 0 { + fieldName6 = fieldHash + fieldDecoder6 = fieldDecoder + } else if fieldName7 == 0 { + fieldName7 = fieldHash + fieldDecoder7 = fieldDecoder + } else { + fieldName8 = fieldHash + fieldDecoder8 = fieldDecoder + } + } + return &eightFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4, + fieldName5, fieldDecoder5, + fieldName6, fieldDecoder6, + fieldName7, fieldDecoder7, + fieldName8, fieldDecoder8} + case 9: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldName5 int64 + var fieldName6 int64 + var fieldName7 int64 + var fieldName8 int64 + var fieldName9 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + var fieldDecoder5 *structFieldDecoder + var fieldDecoder6 *structFieldDecoder + var fieldDecoder7 *structFieldDecoder + var fieldDecoder8 *structFieldDecoder + var fieldDecoder9 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else if fieldName4 == 0 { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } else if fieldName5 == 0 { + fieldName5 = fieldHash + fieldDecoder5 = fieldDecoder + } else if fieldName6 == 0 { + fieldName6 = fieldHash + fieldDecoder6 = fieldDecoder + } else if fieldName7 == 0 { + fieldName7 = fieldHash + fieldDecoder7 = fieldDecoder + } else if fieldName8 == 0 { + fieldName8 = fieldHash + fieldDecoder8 = fieldDecoder + } else { + fieldName9 = fieldHash + fieldDecoder9 = fieldDecoder + } + } + return &nineFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4, + fieldName5, fieldDecoder5, + fieldName6, fieldDecoder6, + fieldName7, fieldDecoder7, + fieldName8, fieldDecoder8, + fieldName9, fieldDecoder9} + case 10: + var fieldName1 int64 + var fieldName2 int64 + var fieldName3 int64 + var fieldName4 int64 + var fieldName5 int64 + var fieldName6 int64 + var fieldName7 int64 + var fieldName8 int64 + var fieldName9 int64 + var fieldName10 int64 + var fieldDecoder1 *structFieldDecoder + var fieldDecoder2 *structFieldDecoder + var fieldDecoder3 *structFieldDecoder + var fieldDecoder4 *structFieldDecoder + var fieldDecoder5 *structFieldDecoder + var fieldDecoder6 *structFieldDecoder + var fieldDecoder7 *structFieldDecoder + var fieldDecoder8 *structFieldDecoder + var fieldDecoder9 *structFieldDecoder + var fieldDecoder10 *structFieldDecoder + for fieldName, fieldDecoder := range fields { + fieldHash := calcHash(fieldName, ctx.caseSensitive()) + _, known := knownHash[fieldHash] + if known { + return &generalStructDecoder{typ, fields, false} + } + knownHash[fieldHash] = struct{}{} + if fieldName1 == 0 { + fieldName1 = fieldHash + fieldDecoder1 = fieldDecoder + } else if fieldName2 == 0 { + fieldName2 = fieldHash + fieldDecoder2 = fieldDecoder + } else if fieldName3 == 0 { + fieldName3 = fieldHash + fieldDecoder3 = fieldDecoder + } else if fieldName4 == 0 { + fieldName4 = fieldHash + fieldDecoder4 = fieldDecoder + } else if fieldName5 == 0 { + fieldName5 = fieldHash + fieldDecoder5 = fieldDecoder + } else if fieldName6 == 0 { + fieldName6 = fieldHash + fieldDecoder6 = fieldDecoder + } else if fieldName7 == 0 { + fieldName7 = fieldHash + fieldDecoder7 = fieldDecoder + } else if fieldName8 == 0 { + fieldName8 = fieldHash + fieldDecoder8 = fieldDecoder + } else if fieldName9 == 0 { + fieldName9 = fieldHash + fieldDecoder9 = fieldDecoder + } else { + fieldName10 = fieldHash + fieldDecoder10 = fieldDecoder + } + } + return &tenFieldsStructDecoder{typ, + fieldName1, fieldDecoder1, + fieldName2, fieldDecoder2, + fieldName3, fieldDecoder3, + fieldName4, fieldDecoder4, + fieldName5, fieldDecoder5, + fieldName6, fieldDecoder6, + fieldName7, fieldDecoder7, + fieldName8, fieldDecoder8, + fieldName9, fieldDecoder9, + fieldName10, fieldDecoder10} + } + return &generalStructDecoder{typ, fields, false} +} + +type generalStructDecoder struct { + typ reflect2.Type + fields map[string]*structFieldDecoder + disallowUnknownFields bool +} + +func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + var c byte + for c = ','; c == ','; c = iter.nextToken() { + decoder.decodeOneField(ptr, iter) + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } + if c != '}' { + iter.ReportError("struct Decode", `expect }, but found `+string([]byte{c})) + } +} + +func (decoder *generalStructDecoder) decodeOneField(ptr unsafe.Pointer, iter *Iterator) { + var field string + var fieldDecoder *structFieldDecoder + if iter.cfg.objectFieldMustBeSimpleString { + fieldBytes := iter.ReadStringAsSlice() + field = *(*string)(unsafe.Pointer(&fieldBytes)) + fieldDecoder = decoder.fields[field] + if fieldDecoder == nil && !iter.cfg.caseSensitive { + fieldDecoder = decoder.fields[strings.ToLower(field)] + } + } else { + field = iter.ReadString() + fieldDecoder = decoder.fields[field] + if fieldDecoder == nil && !iter.cfg.caseSensitive { + fieldDecoder = decoder.fields[strings.ToLower(field)] + } + } + if fieldDecoder == nil { + msg := "found unknown field: " + field + if decoder.disallowUnknownFields { + iter.ReportError("ReadObject", msg) + } + c := iter.nextToken() + if c != ':' { + iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) + } + iter.Skip() + return + } + c := iter.nextToken() + if c != ':' { + iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c})) + } + fieldDecoder.Decode(ptr, iter) +} + +type skipObjectDecoder struct { + typ reflect2.Type +} + +func (decoder *skipObjectDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + valueType := iter.WhatIsNext() + if valueType != ObjectValue && valueType != NilValue { + iter.ReportError("skipObjectDecoder", "expect object or null") + return + } + iter.Skip() +} + +type oneFieldStructDecoder struct { + typ reflect2.Type + fieldHash int64 + fieldDecoder *structFieldDecoder +} + +func (decoder *oneFieldStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + if iter.readFieldHash() == decoder.fieldHash { + decoder.fieldDecoder.Decode(ptr, iter) + } else { + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type twoFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder +} + +func (decoder *twoFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type threeFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder +} + +func (decoder *threeFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type fourFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder +} + +func (decoder *fourFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type fiveFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder + fieldHash5 int64 + fieldDecoder5 *structFieldDecoder +} + +func (decoder *fiveFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + case decoder.fieldHash5: + decoder.fieldDecoder5.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type sixFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder + fieldHash5 int64 + fieldDecoder5 *structFieldDecoder + fieldHash6 int64 + fieldDecoder6 *structFieldDecoder +} + +func (decoder *sixFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + case decoder.fieldHash5: + decoder.fieldDecoder5.Decode(ptr, iter) + case decoder.fieldHash6: + decoder.fieldDecoder6.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type sevenFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder + fieldHash5 int64 + fieldDecoder5 *structFieldDecoder + fieldHash6 int64 + fieldDecoder6 *structFieldDecoder + fieldHash7 int64 + fieldDecoder7 *structFieldDecoder +} + +func (decoder *sevenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + case decoder.fieldHash5: + decoder.fieldDecoder5.Decode(ptr, iter) + case decoder.fieldHash6: + decoder.fieldDecoder6.Decode(ptr, iter) + case decoder.fieldHash7: + decoder.fieldDecoder7.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type eightFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder + fieldHash5 int64 + fieldDecoder5 *structFieldDecoder + fieldHash6 int64 + fieldDecoder6 *structFieldDecoder + fieldHash7 int64 + fieldDecoder7 *structFieldDecoder + fieldHash8 int64 + fieldDecoder8 *structFieldDecoder +} + +func (decoder *eightFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + case decoder.fieldHash5: + decoder.fieldDecoder5.Decode(ptr, iter) + case decoder.fieldHash6: + decoder.fieldDecoder6.Decode(ptr, iter) + case decoder.fieldHash7: + decoder.fieldDecoder7.Decode(ptr, iter) + case decoder.fieldHash8: + decoder.fieldDecoder8.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type nineFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder + fieldHash5 int64 + fieldDecoder5 *structFieldDecoder + fieldHash6 int64 + fieldDecoder6 *structFieldDecoder + fieldHash7 int64 + fieldDecoder7 *structFieldDecoder + fieldHash8 int64 + fieldDecoder8 *structFieldDecoder + fieldHash9 int64 + fieldDecoder9 *structFieldDecoder +} + +func (decoder *nineFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + case decoder.fieldHash5: + decoder.fieldDecoder5.Decode(ptr, iter) + case decoder.fieldHash6: + decoder.fieldDecoder6.Decode(ptr, iter) + case decoder.fieldHash7: + decoder.fieldDecoder7.Decode(ptr, iter) + case decoder.fieldHash8: + decoder.fieldDecoder8.Decode(ptr, iter) + case decoder.fieldHash9: + decoder.fieldDecoder9.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type tenFieldsStructDecoder struct { + typ reflect2.Type + fieldHash1 int64 + fieldDecoder1 *structFieldDecoder + fieldHash2 int64 + fieldDecoder2 *structFieldDecoder + fieldHash3 int64 + fieldDecoder3 *structFieldDecoder + fieldHash4 int64 + fieldDecoder4 *structFieldDecoder + fieldHash5 int64 + fieldDecoder5 *structFieldDecoder + fieldHash6 int64 + fieldDecoder6 *structFieldDecoder + fieldHash7 int64 + fieldDecoder7 *structFieldDecoder + fieldHash8 int64 + fieldDecoder8 *structFieldDecoder + fieldHash9 int64 + fieldDecoder9 *structFieldDecoder + fieldHash10 int64 + fieldDecoder10 *structFieldDecoder +} + +func (decoder *tenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + if !iter.readObjectStart() { + return + } + for { + switch iter.readFieldHash() { + case decoder.fieldHash1: + decoder.fieldDecoder1.Decode(ptr, iter) + case decoder.fieldHash2: + decoder.fieldDecoder2.Decode(ptr, iter) + case decoder.fieldHash3: + decoder.fieldDecoder3.Decode(ptr, iter) + case decoder.fieldHash4: + decoder.fieldDecoder4.Decode(ptr, iter) + case decoder.fieldHash5: + decoder.fieldDecoder5.Decode(ptr, iter) + case decoder.fieldHash6: + decoder.fieldDecoder6.Decode(ptr, iter) + case decoder.fieldHash7: + decoder.fieldDecoder7.Decode(ptr, iter) + case decoder.fieldHash8: + decoder.fieldDecoder8.Decode(ptr, iter) + case decoder.fieldHash9: + decoder.fieldDecoder9.Decode(ptr, iter) + case decoder.fieldHash10: + decoder.fieldDecoder10.Decode(ptr, iter) + default: + iter.Skip() + } + if iter.isObjectEnd() { + break + } + } + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error()) + } +} + +type structFieldDecoder struct { + field reflect2.StructField + fieldDecoder ValDecoder +} + +func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + fieldPtr := decoder.field.UnsafeGet(ptr) + decoder.fieldDecoder.Decode(fieldPtr, iter) + if iter.Error != nil && iter.Error != io.EOF { + iter.Error = fmt.Errorf("%s: %s", decoder.field.Name(), iter.Error.Error()) + } +} + +type stringModeStringDecoder struct { + elemDecoder ValDecoder + cfg *frozenConfig +} + +func (decoder *stringModeStringDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + decoder.elemDecoder.Decode(ptr, iter) + str := *((*string)(ptr)) + tempIter := decoder.cfg.BorrowIterator([]byte(str)) + defer decoder.cfg.ReturnIterator(tempIter) + *((*string)(ptr)) = tempIter.ReadString() +} + +type stringModeNumberDecoder struct { + elemDecoder ValDecoder +} + +func (decoder *stringModeNumberDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + c := iter.nextToken() + if c != '"' { + iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c})) + return + } + decoder.elemDecoder.Decode(ptr, iter) + if iter.Error != nil { + return + } + c = iter.readByte() + if c != '"' { + iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c})) + return + } +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/reflect_struct_encoder.go b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_struct_encoder.go new file mode 100644 index 0000000..d0759cf --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/reflect_struct_encoder.go @@ -0,0 +1,210 @@ +package jsoniter + +import ( + "fmt" + "github.com/modern-go/reflect2" + "io" + "reflect" + "unsafe" +) + +func encoderOfStruct(ctx *ctx, typ reflect2.Type) ValEncoder { + type bindingTo struct { + binding *Binding + toName string + ignored bool + } + orderedBindings := []*bindingTo{} + structDescriptor := describeStruct(ctx, typ) + for _, binding := range structDescriptor.Fields { + for _, toName := range binding.ToNames { + new := &bindingTo{ + binding: binding, + toName: toName, + } + for _, old := range orderedBindings { + if old.toName != toName { + continue + } + old.ignored, new.ignored = resolveConflictBinding(ctx.frozenConfig, old.binding, new.binding) + } + orderedBindings = append(orderedBindings, new) + } + } + if len(orderedBindings) == 0 { + return &emptyStructEncoder{} + } + finalOrderedFields := []structFieldTo{} + for _, bindingTo := range orderedBindings { + if !bindingTo.ignored { + finalOrderedFields = append(finalOrderedFields, structFieldTo{ + encoder: bindingTo.binding.Encoder.(*structFieldEncoder), + toName: bindingTo.toName, + }) + } + } + return &structEncoder{typ, finalOrderedFields} +} + +func createCheckIsEmpty(ctx *ctx, typ reflect2.Type) checkIsEmpty { + encoder := createEncoderOfNative(ctx, typ) + if encoder != nil { + return encoder + } + kind := typ.Kind() + switch kind { + case reflect.Interface: + return &dynamicEncoder{typ} + case reflect.Struct: + return &structEncoder{typ: typ} + case reflect.Array: + return &arrayEncoder{} + case reflect.Slice: + return &sliceEncoder{} + case reflect.Map: + return encoderOfMap(ctx, typ) + case reflect.Ptr: + return &OptionalEncoder{} + default: + return &lazyErrorEncoder{err: fmt.Errorf("unsupported type: %v", typ)} + } +} + +func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ignoreNew bool) { + newTagged := new.Field.Tag().Get(cfg.getTagKey()) != "" + oldTagged := old.Field.Tag().Get(cfg.getTagKey()) != "" + if newTagged { + if oldTagged { + if len(old.levels) > len(new.levels) { + return true, false + } else if len(new.levels) > len(old.levels) { + return false, true + } else { + return true, true + } + } else { + return true, false + } + } else { + if oldTagged { + return true, false + } + if len(old.levels) > len(new.levels) { + return true, false + } else if len(new.levels) > len(old.levels) { + return false, true + } else { + return true, true + } + } +} + +type structFieldEncoder struct { + field reflect2.StructField + fieldEncoder ValEncoder + omitempty bool +} + +func (encoder *structFieldEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + fieldPtr := encoder.field.UnsafeGet(ptr) + encoder.fieldEncoder.Encode(fieldPtr, stream) + if stream.Error != nil && stream.Error != io.EOF { + stream.Error = fmt.Errorf("%s: %s", encoder.field.Name(), stream.Error.Error()) + } +} + +func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool { + fieldPtr := encoder.field.UnsafeGet(ptr) + return encoder.fieldEncoder.IsEmpty(fieldPtr) +} + +func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool { + isEmbeddedPtrNil, converted := encoder.fieldEncoder.(IsEmbeddedPtrNil) + if !converted { + return false + } + fieldPtr := encoder.field.UnsafeGet(ptr) + return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr) +} + +type IsEmbeddedPtrNil interface { + IsEmbeddedPtrNil(ptr unsafe.Pointer) bool +} + +type structEncoder struct { + typ reflect2.Type + fields []structFieldTo +} + +type structFieldTo struct { + encoder *structFieldEncoder + toName string +} + +func (encoder *structEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteObjectStart() + isNotFirst := false + for _, field := range encoder.fields { + if field.encoder.omitempty && field.encoder.IsEmpty(ptr) { + continue + } + if field.encoder.IsEmbeddedPtrNil(ptr) { + continue + } + if isNotFirst { + stream.WriteMore() + } + stream.WriteObjectField(field.toName) + field.encoder.Encode(ptr, stream) + isNotFirst = true + } + stream.WriteObjectEnd() + if stream.Error != nil && stream.Error != io.EOF { + stream.Error = fmt.Errorf("%v.%s", encoder.typ, stream.Error.Error()) + } +} + +func (encoder *structEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return false +} + +type emptyStructEncoder struct { +} + +func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteEmptyObject() +} + +func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return false +} + +type stringModeNumberEncoder struct { + elemEncoder ValEncoder +} + +func (encoder *stringModeNumberEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.writeByte('"') + encoder.elemEncoder.Encode(ptr, stream) + stream.writeByte('"') +} + +func (encoder *stringModeNumberEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.elemEncoder.IsEmpty(ptr) +} + +type stringModeStringEncoder struct { + elemEncoder ValEncoder + cfg *frozenConfig +} + +func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + tempStream := encoder.cfg.BorrowStream(nil) + defer encoder.cfg.ReturnStream(tempStream) + encoder.elemEncoder.Encode(ptr, tempStream) + stream.WriteString(string(tempStream.Buffer())) +} + +func (encoder *stringModeStringEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.elemEncoder.IsEmpty(ptr) +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/stream.go b/go/src/themaru/vendor/github.com/json-iterator/go/stream.go new file mode 100644 index 0000000..17662fd --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/stream.go @@ -0,0 +1,211 @@ +package jsoniter + +import ( + "io" +) + +// stream is a io.Writer like object, with JSON specific write functions. +// Error is not returned as return value, but stored as Error member on this stream instance. +type Stream struct { + cfg *frozenConfig + out io.Writer + buf []byte + Error error + indention int + Attachment interface{} // open for customized encoder +} + +// NewStream create new stream instance. +// cfg can be jsoniter.ConfigDefault. +// out can be nil if write to internal buffer. +// bufSize is the initial size for the internal buffer in bytes. +func NewStream(cfg API, out io.Writer, bufSize int) *Stream { + return &Stream{ + cfg: cfg.(*frozenConfig), + out: out, + buf: make([]byte, 0, bufSize), + Error: nil, + indention: 0, + } +} + +// Pool returns a pool can provide more stream with same configuration +func (stream *Stream) Pool() StreamPool { + return stream.cfg +} + +// Reset reuse this stream instance by assign a new writer +func (stream *Stream) Reset(out io.Writer) { + stream.out = out + stream.buf = stream.buf[:0] +} + +// Available returns how many bytes are unused in the buffer. +func (stream *Stream) Available() int { + return cap(stream.buf) - len(stream.buf) +} + +// Buffered returns the number of bytes that have been written into the current buffer. +func (stream *Stream) Buffered() int { + return len(stream.buf) +} + +// Buffer if writer is nil, use this method to take the result +func (stream *Stream) Buffer() []byte { + return stream.buf +} + +// SetBuffer allows to append to the internal buffer directly +func (stream *Stream) SetBuffer(buf []byte) { + stream.buf = buf +} + +// Write writes the contents of p into the buffer. +// It returns the number of bytes written. +// If nn < len(p), it also returns an error explaining +// why the write is short. +func (stream *Stream) Write(p []byte) (nn int, err error) { + stream.buf = append(stream.buf, p...) + if stream.out != nil { + nn, err = stream.out.Write(stream.buf) + stream.buf = stream.buf[nn:] + return + } + return len(p), nil +} + +// WriteByte writes a single byte. +func (stream *Stream) writeByte(c byte) { + stream.buf = append(stream.buf, c) +} + +func (stream *Stream) writeTwoBytes(c1 byte, c2 byte) { + stream.buf = append(stream.buf, c1, c2) +} + +func (stream *Stream) writeThreeBytes(c1 byte, c2 byte, c3 byte) { + stream.buf = append(stream.buf, c1, c2, c3) +} + +func (stream *Stream) writeFourBytes(c1 byte, c2 byte, c3 byte, c4 byte) { + stream.buf = append(stream.buf, c1, c2, c3, c4) +} + +func (stream *Stream) writeFiveBytes(c1 byte, c2 byte, c3 byte, c4 byte, c5 byte) { + stream.buf = append(stream.buf, c1, c2, c3, c4, c5) +} + +// Flush writes any buffered data to the underlying io.Writer. +func (stream *Stream) Flush() error { + if stream.out == nil { + return nil + } + if stream.Error != nil { + return stream.Error + } + n, err := stream.out.Write(stream.buf) + if err != nil { + if stream.Error == nil { + stream.Error = err + } + return err + } + stream.buf = stream.buf[n:] + return nil +} + +// WriteRaw write string out without quotes, just like []byte +func (stream *Stream) WriteRaw(s string) { + stream.buf = append(stream.buf, s...) +} + +// WriteNil write null to stream +func (stream *Stream) WriteNil() { + stream.writeFourBytes('n', 'u', 'l', 'l') +} + +// WriteTrue write true to stream +func (stream *Stream) WriteTrue() { + stream.writeFourBytes('t', 'r', 'u', 'e') +} + +// WriteFalse write false to stream +func (stream *Stream) WriteFalse() { + stream.writeFiveBytes('f', 'a', 'l', 's', 'e') +} + +// WriteBool write true or false into stream +func (stream *Stream) WriteBool(val bool) { + if val { + stream.WriteTrue() + } else { + stream.WriteFalse() + } +} + +// WriteObjectStart write { with possible indention +func (stream *Stream) WriteObjectStart() { + stream.indention += stream.cfg.indentionStep + stream.writeByte('{') + stream.writeIndention(0) +} + +// WriteObjectField write "field": with possible indention +func (stream *Stream) WriteObjectField(field string) { + stream.WriteString(field) + if stream.indention > 0 { + stream.writeTwoBytes(':', ' ') + } else { + stream.writeByte(':') + } +} + +// WriteObjectEnd write } with possible indention +func (stream *Stream) WriteObjectEnd() { + stream.writeIndention(stream.cfg.indentionStep) + stream.indention -= stream.cfg.indentionStep + stream.writeByte('}') +} + +// WriteEmptyObject write {} +func (stream *Stream) WriteEmptyObject() { + stream.writeByte('{') + stream.writeByte('}') +} + +// WriteMore write , with possible indention +func (stream *Stream) WriteMore() { + stream.writeByte(',') + stream.writeIndention(0) + stream.Flush() +} + +// WriteArrayStart write [ with possible indention +func (stream *Stream) WriteArrayStart() { + stream.indention += stream.cfg.indentionStep + stream.writeByte('[') + stream.writeIndention(0) +} + +// WriteEmptyArray write [] +func (stream *Stream) WriteEmptyArray() { + stream.writeTwoBytes('[', ']') +} + +// WriteArrayEnd write ] with possible indention +func (stream *Stream) WriteArrayEnd() { + stream.writeIndention(stream.cfg.indentionStep) + stream.indention -= stream.cfg.indentionStep + stream.writeByte(']') +} + +func (stream *Stream) writeIndention(delta int) { + if stream.indention == 0 { + return + } + stream.writeByte('\n') + toWrite := stream.indention - delta + for i := 0; i < toWrite; i++ { + stream.buf = append(stream.buf, ' ') + } +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/stream_float.go b/go/src/themaru/vendor/github.com/json-iterator/go/stream_float.go new file mode 100644 index 0000000..f318d2c --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/stream_float.go @@ -0,0 +1,94 @@ +package jsoniter + +import ( + "math" + "strconv" +) + +var pow10 []uint64 + +func init() { + pow10 = []uint64{1, 10, 100, 1000, 10000, 100000, 1000000} +} + +// WriteFloat32 write float32 to stream +func (stream *Stream) WriteFloat32(val float32) { + abs := math.Abs(float64(val)) + fmt := byte('f') + // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. + if abs != 0 { + if float32(abs) < 1e-6 || float32(abs) >= 1e21 { + fmt = 'e' + } + } + stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 32) +} + +// WriteFloat32Lossy write float32 to stream with ONLY 6 digits precision although much much faster +func (stream *Stream) WriteFloat32Lossy(val float32) { + if val < 0 { + stream.writeByte('-') + val = -val + } + if val > 0x4ffffff { + stream.WriteFloat32(val) + return + } + precision := 6 + exp := uint64(1000000) // 6 + lval := uint64(float64(val)*float64(exp) + 0.5) + stream.WriteUint64(lval / exp) + fval := lval % exp + if fval == 0 { + return + } + stream.writeByte('.') + for p := precision - 1; p > 0 && fval < pow10[p]; p-- { + stream.writeByte('0') + } + stream.WriteUint64(fval) + for stream.buf[len(stream.buf)-1] == '0' { + stream.buf = stream.buf[:len(stream.buf)-1] + } +} + +// WriteFloat64 write float64 to stream +func (stream *Stream) WriteFloat64(val float64) { + abs := math.Abs(val) + fmt := byte('f') + // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. + if abs != 0 { + if abs < 1e-6 || abs >= 1e21 { + fmt = 'e' + } + } + stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 64) +} + +// WriteFloat64Lossy write float64 to stream with ONLY 6 digits precision although much much faster +func (stream *Stream) WriteFloat64Lossy(val float64) { + if val < 0 { + stream.writeByte('-') + val = -val + } + if val > 0x4ffffff { + stream.WriteFloat64(val) + return + } + precision := 6 + exp := uint64(1000000) // 6 + lval := uint64(val*float64(exp) + 0.5) + stream.WriteUint64(lval / exp) + fval := lval % exp + if fval == 0 { + return + } + stream.writeByte('.') + for p := precision - 1; p > 0 && fval < pow10[p]; p-- { + stream.writeByte('0') + } + stream.WriteUint64(fval) + for stream.buf[len(stream.buf)-1] == '0' { + stream.buf = stream.buf[:len(stream.buf)-1] + } +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/stream_int.go b/go/src/themaru/vendor/github.com/json-iterator/go/stream_int.go new file mode 100644 index 0000000..d1059ee --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/stream_int.go @@ -0,0 +1,190 @@ +package jsoniter + +var digits []uint32 + +func init() { + digits = make([]uint32, 1000) + for i := uint32(0); i < 1000; i++ { + digits[i] = (((i / 100) + '0') << 16) + ((((i / 10) % 10) + '0') << 8) + i%10 + '0' + if i < 10 { + digits[i] += 2 << 24 + } else if i < 100 { + digits[i] += 1 << 24 + } + } +} + +func writeFirstBuf(space []byte, v uint32) []byte { + start := v >> 24 + if start == 0 { + space = append(space, byte(v>>16), byte(v>>8)) + } else if start == 1 { + space = append(space, byte(v>>8)) + } + space = append(space, byte(v)) + return space +} + +func writeBuf(buf []byte, v uint32) []byte { + return append(buf, byte(v>>16), byte(v>>8), byte(v)) +} + +// WriteUint8 write uint8 to stream +func (stream *Stream) WriteUint8(val uint8) { + stream.buf = writeFirstBuf(stream.buf, digits[val]) +} + +// WriteInt8 write int8 to stream +func (stream *Stream) WriteInt8(nval int8) { + var val uint8 + if nval < 0 { + val = uint8(-nval) + stream.buf = append(stream.buf, '-') + } else { + val = uint8(nval) + } + stream.buf = writeFirstBuf(stream.buf, digits[val]) +} + +// WriteUint16 write uint16 to stream +func (stream *Stream) WriteUint16(val uint16) { + q1 := val / 1000 + if q1 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[val]) + return + } + r1 := val - q1*1000 + stream.buf = writeFirstBuf(stream.buf, digits[q1]) + stream.buf = writeBuf(stream.buf, digits[r1]) + return +} + +// WriteInt16 write int16 to stream +func (stream *Stream) WriteInt16(nval int16) { + var val uint16 + if nval < 0 { + val = uint16(-nval) + stream.buf = append(stream.buf, '-') + } else { + val = uint16(nval) + } + stream.WriteUint16(val) +} + +// WriteUint32 write uint32 to stream +func (stream *Stream) WriteUint32(val uint32) { + q1 := val / 1000 + if q1 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[val]) + return + } + r1 := val - q1*1000 + q2 := q1 / 1000 + if q2 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q1]) + stream.buf = writeBuf(stream.buf, digits[r1]) + return + } + r2 := q1 - q2*1000 + q3 := q2 / 1000 + if q3 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q2]) + } else { + r3 := q2 - q3*1000 + stream.buf = append(stream.buf, byte(q3+'0')) + stream.buf = writeBuf(stream.buf, digits[r3]) + } + stream.buf = writeBuf(stream.buf, digits[r2]) + stream.buf = writeBuf(stream.buf, digits[r1]) +} + +// WriteInt32 write int32 to stream +func (stream *Stream) WriteInt32(nval int32) { + var val uint32 + if nval < 0 { + val = uint32(-nval) + stream.buf = append(stream.buf, '-') + } else { + val = uint32(nval) + } + stream.WriteUint32(val) +} + +// WriteUint64 write uint64 to stream +func (stream *Stream) WriteUint64(val uint64) { + q1 := val / 1000 + if q1 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[val]) + return + } + r1 := val - q1*1000 + q2 := q1 / 1000 + if q2 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q1]) + stream.buf = writeBuf(stream.buf, digits[r1]) + return + } + r2 := q1 - q2*1000 + q3 := q2 / 1000 + if q3 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q2]) + stream.buf = writeBuf(stream.buf, digits[r2]) + stream.buf = writeBuf(stream.buf, digits[r1]) + return + } + r3 := q2 - q3*1000 + q4 := q3 / 1000 + if q4 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q3]) + stream.buf = writeBuf(stream.buf, digits[r3]) + stream.buf = writeBuf(stream.buf, digits[r2]) + stream.buf = writeBuf(stream.buf, digits[r1]) + return + } + r4 := q3 - q4*1000 + q5 := q4 / 1000 + if q5 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q4]) + stream.buf = writeBuf(stream.buf, digits[r4]) + stream.buf = writeBuf(stream.buf, digits[r3]) + stream.buf = writeBuf(stream.buf, digits[r2]) + stream.buf = writeBuf(stream.buf, digits[r1]) + return + } + r5 := q4 - q5*1000 + q6 := q5 / 1000 + if q6 == 0 { + stream.buf = writeFirstBuf(stream.buf, digits[q5]) + } else { + stream.buf = writeFirstBuf(stream.buf, digits[q6]) + r6 := q5 - q6*1000 + stream.buf = writeBuf(stream.buf, digits[r6]) + } + stream.buf = writeBuf(stream.buf, digits[r5]) + stream.buf = writeBuf(stream.buf, digits[r4]) + stream.buf = writeBuf(stream.buf, digits[r3]) + stream.buf = writeBuf(stream.buf, digits[r2]) + stream.buf = writeBuf(stream.buf, digits[r1]) +} + +// WriteInt64 write int64 to stream +func (stream *Stream) WriteInt64(nval int64) { + var val uint64 + if nval < 0 { + val = uint64(-nval) + stream.buf = append(stream.buf, '-') + } else { + val = uint64(nval) + } + stream.WriteUint64(val) +} + +// WriteInt write int to stream +func (stream *Stream) WriteInt(val int) { + stream.WriteInt64(int64(val)) +} + +// WriteUint write uint to stream +func (stream *Stream) WriteUint(val uint) { + stream.WriteUint64(uint64(val)) +} diff --git a/go/src/themaru/vendor/github.com/json-iterator/go/stream_str.go b/go/src/themaru/vendor/github.com/json-iterator/go/stream_str.go new file mode 100644 index 0000000..54c2ba0 --- /dev/null +++ b/go/src/themaru/vendor/github.com/json-iterator/go/stream_str.go @@ -0,0 +1,372 @@ +package jsoniter + +import ( + "unicode/utf8" +) + +// htmlSafeSet holds the value true if the ASCII character with the given +// array position can be safely represented inside a JSON string, embedded +// inside of HTML