1
0
mirror of https://github.com/kubernetes-sigs/descheduler.git synced 2026-01-28 14:41:10 +01:00

Update vendor dependencies.

This commit is contained in:
Avesh Agarwal
2017-07-29 15:15:36 -04:00
parent 198dfc8a2e
commit 92006cbd77
1923 changed files with 1442573 additions and 1 deletions

4
vendor/github.com/mailru/easyjson/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,4 @@
.root
*_easyjson.go
*.iml
.idea

8
vendor/github.com/mailru/easyjson/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,8 @@
language: go
go:
- tip
install:
- go get github.com/ugorji/go/codec
- go get github.com/pquerna/ffjson/fflib/v1
- go get github.com/golang/lint/golint

7
vendor/github.com/mailru/easyjson/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,7 @@
Copyright (c) 2016 Mail.Ru Group
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.

50
vendor/github.com/mailru/easyjson/Makefile generated vendored Normal file
View File

@@ -0,0 +1,50 @@
PKG=github.com/mailru/easyjson
GOPATH:=$(PWD)/.root:$(GOPATH)
export GOPATH
all: test
.root/src/$(PKG):
mkdir -p $@
for i in $$PWD/* ; do ln -s $$i $@/`basename $$i` ; done
root: .root/src/$(PKG)
clean:
rm -rf .root
build:
go build -i -o .root/bin/easyjson $(PKG)/easyjson
generate: root build
.root/bin/easyjson -stubs \
.root/src/$(PKG)/tests/snake.go \
.root/src/$(PKG)/tests/data.go \
.root/src/$(PKG)/tests/omitempty.go \
.root/src/$(PKG)/tests/nothing.go
.root/bin/easyjson -all .root/src/$(PKG)/tests/data.go
.root/bin/easyjson -all .root/src/$(PKG)/tests/nothing.go
.root/bin/easyjson -snake_case .root/src/$(PKG)/tests/snake.go
.root/bin/easyjson -omit_empty .root/src/$(PKG)/tests/omitempty.go
.root/bin/easyjson -build_tags=use_easyjson .root/src/$(PKG)/benchmark/data.go
test: generate root
go test \
$(PKG)/tests \
$(PKG)/jlexer \
$(PKG)/gen \
$(PKG)/buffer
go test -benchmem -tags use_easyjson -bench . $(PKG)/benchmark
golint -set_exit_status .root/src/$(PKG)/tests/*_easyjson.go
bench-other: generate root
@go test -benchmem -bench . $(PKG)/benchmark
@go test -benchmem -tags use_ffjson -bench . $(PKG)/benchmark
@go test -benchmem -tags use_codec -bench . $(PKG)/benchmark
bench-python:
benchmark/ujson.sh
.PHONY: root clean generate test build

193
vendor/github.com/mailru/easyjson/README.md generated vendored Normal file
View File

@@ -0,0 +1,193 @@
# easyjson [![Build Status](https://travis-ci.org/mailru/easyjson.svg?branch=master)](https://travis-ci.org/mailru/easyjson)
easyjson allows to (un-)marshal JSON golang structs without the use of reflection by generating marshaller code.
One of the aims of the library is to keep generated code simple enough so that it can be easily optimized or fixed. Another goal is to provide users with ability to customize the generated code not available in 'encoding/json', such as generating snake_case names or enabling 'omitempty' behavior by default.
## usage
```
go get github.com/mailru/easyjson/...
easyjson -all <file>.go
```
This will generate `<file>_easyjson.go` with marshaller/unmarshaller methods for structs. `GOPATH` variable needs to be set up correctly, since the generation invokes a `go run` on a temporary file (this is a really convenient approach to code generation borrowed from https://github.com/pquerna/ffjson).
## options
```
Usage of .root/bin/easyjson:
-all
generate un-/marshallers for all structs in a file
-build_tags string
build tags to add to generated file
-leave_temps
do not delete temporary files
-no_std_marshalers
don't generate MarshalJSON/UnmarshalJSON methods
-noformat
do not run 'gofmt -w' on output file
-omit_empty
omit empty fields by default
-snake_case
use snake_case names instead of CamelCase by default
-stubs
only generate stubs for marshallers/unmarshallers methods
```
Using `-all` will generate (un-)marshallers for all structs in the file. By default, structs need to have a line beginning with `easyjson:json` in their docstring, e.g.:
```
//easyjson:json
struct A{}
```
`-snake_case` tells easyjson to generate snake\_case field names by default (unless explicitly overriden by a field tag). The CamelCase to snake\_case conversion algorithm should work in most cases (e.g. HTTPVersion will be converted to http_version). There can be names like JSONHTTPRPC where the conversion will return an unexpected result (jsonhttprpc without underscores), but such names require a dictionary to do the conversion and may be ambiguous.
`-build_tags` will add corresponding build tag line for the generated file.
## marshaller/unmarshaller interfaces
easyjson generates MarshalJSON/UnmarshalJSON methods that are compatible with interfaces from 'encoding/json'. They are usable with 'json.Marshal' and 'json.Unmarshal' functions, however actually using those will result in significantly worse performance compared to custom interfaces.
`MarshalEasyJSON` / `UnmarshalEasyJSON` methods are generated for faster parsing using custom Lexer/Writer structs (`jlexer.Lexer` and `jwriter.Writer`). The method signature is defined in `easyjson.Marshaler` / `easyjson.Unmarshaler` interfaces. These interfaces allow to avoid using any unnecessary reflection or type assertions during parsing. Functions can be used manually or with `easyjson.Marshal<...>` and `easyjson.Unmarshal<...>` helper methods.
`jwriter.Writer` struct in addition to function for returning the data as a single slice also has methods to return the size and to send the data to an `io.Writer`. This is aimed at a typical HTTP use-case, when you want to know the `Content-Length` before actually starting to send the data.
There are helpers in the top-level package for marhsaling/unmarshaling the data using custom interfaces to and from writers, including a helper for `http.ResponseWriter`.
## custom types
If `easyjson.Marshaler` / `easyjson.Unmarshaler` interfaces are implemented by a type involved in JSON parsing, the type will be marshaled/unmarshaled using these methods. `easyjson.Optional` interface allows for a custom type to integrate with 'omitempty' logic.
As an example, easyjson includes an `easyjson.RawMessage` analogous to `json.RawMessage`.
Also, there are 'optional' wrappers for primitive types in `easyjson/opt` package. These are useful in the case when it is necessary to distinguish between missing and default value for the type. Wrappers allow to avoid pointers and extra heap allocations in such cases.
## memory pooling
The library uses a custom buffer which allocates data in increasing chunks (128-32768 bytes). Chunks of 512 bytes and larger are reused with the help of `sync.Pool`. The maximum size of a chunk is bounded to reduce redundancy in memory allocation and to make the chunks more reusable in the case of large buffer sizes.
The buffer code is in `easyjson/buffer` package the exact values can be tweaked by a `buffer.Init()` call before the first serialization.
## limitations
* The library is at an early stage, there are likely to be some bugs and some features of 'encoding/json' may not be supported. Please report such cases, so that they may be fixed sooner.
* Object keys are case-sensitive (unlike encodin/json). Case-insentive behavior will be implemented as an option (case-insensitive matching is slower).
* Unsafe package is used by the code. While a non-unsafe version of easyjson can be made in the future, using unsafe package simplifies a lot of code by allowing no-copy []byte to string conversion within the library. This is used only during parsing and all the returned values are allocated properly.
* Floats are currently formatted with default precision for 'strconv' package. It is obvious that it is not always the correct way to handle it, but there aren't enough use-cases for floats at hand to do anything better.
* During parsing, parts of JSON that are skipped over are not syntactically validated more than required to skip matching parentheses.
* No true streaming support for encoding/decoding. For many use-cases and protocols, data length is typically known on input and needs to be known before sending the data.
## benchmarks
Most benchmarks were done using a sample 13kB JSON (9k if serialized back trimming the whitespace) from https://dev.twitter.com/rest/reference/get/search/tweets. The sample is very close to real-world data, quite structured and contains a variety of different types.
For small request benchmarks, an 80-byte portion of the regular sample was used.
For large request marshalling benchmarks, a struct containing 50 regular samples was used, making a ~500kB output JSON.
Benchmarks are available in the repository and are run on 'make'.
### easyjson vs. encoding/json
easyjson seems to be 5-6 times faster than the default json serialization for unmarshalling, 3-4 times faster for non-concurrent marshalling. Concurrent marshalling is 6-7x faster if marshalling to a writer.
### easyjson vs. ffjson
easyjson uses the same approach for code generation as ffjson, but a significantly different approach to lexing and generated code. This allows easyjson to be 2-3x faster for unmarshalling and 1.5-2x faster for non-concurrent unmarshalling.
ffjson seems to behave weird if used concurrently: for large request pooling hurts performance instead of boosting it, it also does not quite scale well. These issues are likely to be fixable and until that comparisons might vary from version to version a lot.
easyjson is similar in performance for small requests and 2-5x times faster for large ones if used with a writer.
### easyjson vs. go/codec
github.com/ugorji/go/codec library provides compile-time helpers for JSON generation. In this case, helpers are not exactly marshallers as they are encoding-independent.
easyjson is generally ~2x faster for non-concurrent benchmarks and about 3x faster for concurrent encoding (without marshalling to a writer). Unsafe option for generated helpers was used.
As an attempt to measure marshalling performance of 'go/codec' (as opposed to allocations/memcpy/writer interface invocations), a benchmark was done with resetting lenght of a byte slice rather than resetting the whole slice to nil. However, the optimization in this exact form may not be applicable in practice, since the memory is not freed between marshalling operations.
### easyjson vs 'ujson' python module
ujson is using C code for parsing, so it is interesting to see how plain golang compares to that. It is imporant to note that the resulting object for python is slower to access, since the library parses JSON object into dictionaries.
easyjson seems to be slightly faster for unmarshalling (finally!) and 2-3x faster for marshalling.
### benchmark figures
The data was measured on 4 February, 2016 using current ffjson and golang 1.6. Data for go/codec was added on 4 March 2016, benchmarked on the same machine.
#### Unmarshalling
| lib | json size | MB/s | allocs/op | B/op
|--------|-----------|------|-----------|-------
|standard| regular | 22 | 218 | 10229
|standard| small | 9.7 | 14 | 720
|--------|-----------|------|-----------|-------
|easyjson| regular | 125 | 128 | 9794
|easyjson| small | 67 | 3 | 128
|--------|-----------|------|-----------|-------
|ffjson | regular | 66 | 141 | 9985
|ffjson | small | 17.6 | 10 | 488
|--------|-----------|------|-----------|-------
|codec | regular | 55 | 434 | 19299
|codec | small | 29 | 7 | 336
|--------|-----------|------|-----------|-------
|ujson | regular | 103 | N/A | N/A
#### Marshalling, one goroutine.
| lib | json size | MB/s | allocs/op | B/op
|----------|-----------|------|-----------|-------
|standard | regular | 75 | 9 | 23256
|standard | small | 32 | 3 | 328
|standard | large | 80 | 17 | 1.2M
|----------|-----------|------|-----------|-------
|easyjson | regular | 213 | 9 | 10260
|easyjson* | regular | 263 | 8 | 742
|easyjson | small | 125 | 1 | 128
|easyjson | large | 212 | 33 | 490k
|easyjson* | large | 262 | 25 | 2879
|----------|-----------|------|-----------|-------
|ffjson | regular | 122 | 153 | 21340
|ffjson** | regular | 146 | 152 | 4897
|ffjson | small | 36 | 5 | 384
|ffjson** | small | 64 | 4 | 128
|ffjson | large | 134 | 7317 | 818k
|ffjson** | large | 125 | 7320 | 827k
|----------|-----------|------|-----------|-------
|codec | regular | 80 | 17 | 33601
|codec*** | regular | 108 | 9 | 1153
|codec | small | 42 | 3 | 304
|codec*** | small | 56 | 1 | 48
|codec | large | 73 | 483 | 2.5M
|codec*** | large | 103 | 451 | 66007
|----------|-----------|------|-----------|-------
|ujson | regular | 92 | N/A | N/A
\* marshalling to a writer,
\*\* using `ffjson.Pool()`,
\*\*\* reusing output slice instead of resetting it to nil
#### Marshalling, concurrent.
| lib | json size | MB/s | allocs/op | B/op
|----------|-----------|-------|-----------|-------
|standard | regular | 252 | 9 | 23257
|standard | small | 124 | 3 | 328
|standard | large | 289 | 17 | 1.2M
|----------|-----------|-------|-----------|-------
|easyjson | regular | 792 | 9 | 10597
|easyjson* | regular | 1748 | 8 | 779
|easyjson | small | 333 | 1 | 128
|easyjson | large | 718 | 36 | 548k
|easyjson* | large | 2134 | 25 | 4957
|----------|-----------|------|-----------|-------
|ffjson | regular | 301 | 153 | 21629
|ffjson** | regular | 707 | 152 | 5148
|ffjson | small | 62 | 5 | 384
|ffjson** | small | 282 | 4 | 128
|ffjson | large | 438 | 7330 | 1.0M
|ffjson** | large | 131 | 7319 | 820k
|----------|-----------|------|-----------|-------
|codec | regular | 183 | 17 | 33603
|codec*** | regular | 671 | 9 | 1157
|codec | small | 147 | 3 | 304
|codec*** | small | 299 | 1 | 48
|codec | large | 190 | 483 | 2.5M
|codec*** | large | 752 | 451 | 77574
\* marshalling to a writer,
\*\* using `ffjson.Pool()`,
\*\*\* reusing output slice instead of resetting it to nil

View File

@@ -0,0 +1,279 @@
// +build use_codec
package benchmark
import (
"testing"
"github.com/ugorji/go/codec"
)
func BenchmarkCodec_Unmarshal_M(b *testing.B) {
var h codec.Handle = new(codec.JsonHandle)
dec := codec.NewDecoderBytes(nil, h)
b.SetBytes(int64(len(largeStructText)))
for i := 0; i < b.N; i++ {
var s LargeStruct
dec.ResetBytes(largeStructText)
if err := dec.Decode(&s); err != nil {
b.Error(err)
}
}
}
func BenchmarkCodec_Unmarshal_S(b *testing.B) {
var h codec.Handle = new(codec.JsonHandle)
dec := codec.NewDecoderBytes(nil, h)
b.SetBytes(int64(len(smallStructText)))
for i := 0; i < b.N; i++ {
var s LargeStruct
dec.ResetBytes(smallStructText)
if err := dec.Decode(&s); err != nil {
b.Error(err)
}
}
}
func BenchmarkCodec_Marshal_S(b *testing.B) {
var h codec.Handle = new(codec.JsonHandle)
var out []byte
enc := codec.NewEncoderBytes(&out, h)
var l int64
for i := 0; i < b.N; i++ {
enc.ResetBytes(&out)
if err := enc.Encode(&smallStructData); err != nil {
b.Error(err)
}
l = int64(len(out))
out = nil
}
b.SetBytes(l)
}
func BenchmarkCodec_Marshal_M(b *testing.B) {
var h codec.Handle = new(codec.JsonHandle)
var out []byte
enc := codec.NewEncoderBytes(&out, h)
var l int64
for i := 0; i < b.N; i++ {
enc.ResetBytes(&out)
if err := enc.Encode(&largeStructData); err != nil {
b.Error(err)
}
l = int64(len(out))
out = nil
}
b.SetBytes(l)
}
func BenchmarkCodec_Marshal_L(b *testing.B) {
var h codec.Handle = new(codec.JsonHandle)
var out []byte
enc := codec.NewEncoderBytes(&out, h)
var l int64
for i := 0; i < b.N; i++ {
enc.ResetBytes(&out)
if err := enc.Encode(&xlStructData); err != nil {
b.Error(err)
}
l = int64(len(out))
out = nil
}
b.SetBytes(l)
}
func BenchmarkCodec_Marshal_S_Reuse(b *testing.B) {
var h codec.Handle = new(codec.JsonHandle)
var out []byte
enc := codec.NewEncoderBytes(&out, h)
var l int64
for i := 0; i < b.N; i++ {
enc.ResetBytes(&out)
if err := enc.Encode(&smallStructData); err != nil {
b.Error(err)
}
l = int64(len(out))
out = out[:0]
}
b.SetBytes(l)
}
func BenchmarkCodec_Marshal_M_Reuse(b *testing.B) {
var h codec.Handle = new(codec.JsonHandle)
var out []byte
enc := codec.NewEncoderBytes(&out, h)
var l int64
for i := 0; i < b.N; i++ {
enc.ResetBytes(&out)
if err := enc.Encode(&largeStructData); err != nil {
b.Error(err)
}
l = int64(len(out))
out = out[:0]
}
b.SetBytes(l)
}
func BenchmarkCodec_Marshal_L_Reuse(b *testing.B) {
var h codec.Handle = new(codec.JsonHandle)
var out []byte
enc := codec.NewEncoderBytes(&out, h)
var l int64
for i := 0; i < b.N; i++ {
enc.ResetBytes(&out)
if err := enc.Encode(&xlStructData); err != nil {
b.Error(err)
}
l = int64(len(out))
out = out[:0]
}
b.SetBytes(l)
}
func BenchmarkCodec_Marshal_S_Parallel(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
var out []byte
var h codec.Handle = new(codec.JsonHandle)
enc := codec.NewEncoderBytes(&out, h)
for pb.Next() {
enc.ResetBytes(&out)
if err := enc.Encode(&smallStructData); err != nil {
b.Error(err)
}
l = int64(len(out))
out = nil
}
})
b.SetBytes(l)
}
func BenchmarkCodec_Marshal_M_Parallel(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
var h codec.Handle = new(codec.JsonHandle)
var out []byte
enc := codec.NewEncoderBytes(&out, h)
for pb.Next() {
enc.ResetBytes(&out)
if err := enc.Encode(&largeStructData); err != nil {
b.Error(err)
}
l = int64(len(out))
out = nil
}
})
b.SetBytes(l)
}
func BenchmarkCodec_Marshal_L_Parallel(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
var h codec.Handle = new(codec.JsonHandle)
var out []byte
enc := codec.NewEncoderBytes(&out, h)
for pb.Next() {
enc.ResetBytes(&out)
if err := enc.Encode(&xlStructData); err != nil {
b.Error(err)
}
l = int64(len(out))
out = nil
}
})
b.SetBytes(l)
}
func BenchmarkCodec_Marshal_S_Parallel_Reuse(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
var out []byte
var h codec.Handle = new(codec.JsonHandle)
enc := codec.NewEncoderBytes(&out, h)
for pb.Next() {
enc.ResetBytes(&out)
if err := enc.Encode(&smallStructData); err != nil {
b.Error(err)
}
l = int64(len(out))
out = out[:0]
}
})
b.SetBytes(l)
}
func BenchmarkCodec_Marshal_M_Parallel_Reuse(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
var h codec.Handle = new(codec.JsonHandle)
var out []byte
enc := codec.NewEncoderBytes(&out, h)
for pb.Next() {
enc.ResetBytes(&out)
if err := enc.Encode(&largeStructData); err != nil {
b.Error(err)
}
l = int64(len(out))
out = out[:0]
}
})
b.SetBytes(l)
}
func BenchmarkCodec_Marshal_L_Parallel_Reuse(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
var h codec.Handle = new(codec.JsonHandle)
var out []byte
enc := codec.NewEncoderBytes(&out, h)
for pb.Next() {
enc.ResetBytes(&out)
if err := enc.Encode(&xlStructData); err != nil {
b.Error(err)
}
l = int64(len(out))
out = out[:0]
}
})
b.SetBytes(l)
}

148
vendor/github.com/mailru/easyjson/benchmark/data.go generated vendored Normal file
View File

@@ -0,0 +1,148 @@
// Package benchmark provides a simple benchmark for easyjson against default serialization and ffjson.
// The data example is taken from https://dev.twitter.com/rest/reference/get/search/tweets
package benchmark
import (
"io/ioutil"
)
var largeStructText, _ = ioutil.ReadFile("example.json")
var xlStructData XLStruct
func init() {
for i := 0; i < 50; i++ {
xlStructData.Data = append(xlStructData.Data, largeStructData)
}
}
var smallStructText = []byte(`{"hashtags":[{"indices":[5, 10],"text":"some-text"}],"urls":[],"user_mentions":[]}`)
var smallStructData = Entities{
Hashtags: []Hashtag{{Indices: []int{5, 10}, Text: "some-text"}},
Urls: []*string{},
UserMentions: []*string{},
}
type SearchMetadata struct {
CompletedIn float64 `json:"completed_in"`
Count int `json:"count"`
MaxID int `json:"max_id"`
MaxIDStr string `json:"max_id_str"`
NextResults string `json:"next_results"`
Query string `json:"query"`
RefreshURL string `json:"refresh_url"`
SinceID int `json:"since_id"`
SinceIDStr string `json:"since_id_str"`
}
type Hashtag struct {
Indices []int `json:"indices"`
Text string `json:"text"`
}
//easyjson:json
type Entities struct {
Hashtags []Hashtag `json:"hashtags"`
Urls []*string `json:"urls"`
UserMentions []*string `json:"user_mentions"`
}
type UserEntityDescription struct {
Urls []*string `json:"urls"`
}
type URL struct {
ExpandedURL *string `json:"expanded_url"`
Indices []int `json:"indices"`
URL string `json:"url"`
}
type UserEntityURL struct {
Urls []URL `json:"urls"`
}
type UserEntities struct {
Description UserEntityDescription `json:"description"`
URL UserEntityURL `json:"url"`
}
type User struct {
ContributorsEnabled bool `json:"contributors_enabled"`
CreatedAt string `json:"created_at"`
DefaultProfile bool `json:"default_profile"`
DefaultProfileImage bool `json:"default_profile_image"`
Description string `json:"description"`
Entities UserEntities `json:"entities"`
FavouritesCount int `json:"favourites_count"`
FollowRequestSent *string `json:"follow_request_sent"`
FollowersCount int `json:"followers_count"`
Following *string `json:"following"`
FriendsCount int `json:"friends_count"`
GeoEnabled bool `json:"geo_enabled"`
ID int `json:"id"`
IDStr string `json:"id_str"`
IsTranslator bool `json:"is_translator"`
Lang string `json:"lang"`
ListedCount int `json:"listed_count"`
Location string `json:"location"`
Name string `json:"name"`
Notifications *string `json:"notifications"`
ProfileBackgroundColor string `json:"profile_background_color"`
ProfileBackgroundImageURL string `json:"profile_background_image_url"`
ProfileBackgroundImageURLHTTPS string `json:"profile_background_image_url_https"`
ProfileBackgroundTile bool `json:"profile_background_tile"`
ProfileImageURL string `json:"profile_image_url"`
ProfileImageURLHTTPS string `json:"profile_image_url_https"`
ProfileLinkColor string `json:"profile_link_color"`
ProfileSidebarBorderColor string `json:"profile_sidebar_border_color"`
ProfileSidebarFillColor string `json:"profile_sidebar_fill_color"`
ProfileTextColor string `json:"profile_text_color"`
ProfileUseBackgroundImage bool `json:"profile_use_background_image"`
Protected bool `json:"protected"`
ScreenName string `json:"screen_name"`
ShowAllInlineMedia bool `json:"show_all_inline_media"`
StatusesCount int `json:"statuses_count"`
TimeZone string `json:"time_zone"`
URL *string `json:"url"`
UtcOffset int `json:"utc_offset"`
Verified bool `json:"verified"`
}
type StatusMetadata struct {
IsoLanguageCode string `json:"iso_language_code"`
ResultType string `json:"result_type"`
}
type Status struct {
Contributors *string `json:"contributors"`
Coordinates *string `json:"coordinates"`
CreatedAt string `json:"created_at"`
Entities Entities `json:"entities"`
Favorited bool `json:"favorited"`
Geo *string `json:"geo"`
ID int64 `json:"id"`
IDStr string `json:"id_str"`
InReplyToScreenName *string `json:"in_reply_to_screen_name"`
InReplyToStatusID *string `json:"in_reply_to_status_id"`
InReplyToStatusIDStr *string `json:"in_reply_to_status_id_str"`
InReplyToUserID *string `json:"in_reply_to_user_id"`
InReplyToUserIDStr *string `json:"in_reply_to_user_id_str"`
Metadata StatusMetadata `json:"metadata"`
Place *string `json:"place"`
RetweetCount int `json:"retweet_count"`
Retweeted bool `json:"retweeted"`
Source string `json:"source"`
Text string `json:"text"`
Truncated bool `json:"truncated"`
User User `json:"user"`
}
//easyjson:json
type LargeStruct struct {
SearchMetadata SearchMetadata `json:"search_metadata"`
Statuses []Status `json:"statuses"`
}
//easyjson:json
type XLStruct struct {
Data []LargeStruct
}

6911
vendor/github.com/mailru/easyjson/benchmark/data_codec.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

350
vendor/github.com/mailru/easyjson/benchmark/data_var.go generated vendored Normal file
View File

@@ -0,0 +1,350 @@
package benchmark
var largeStructData = LargeStruct{
SearchMetadata: SearchMetadata{
CompletedIn: 0.035,
Count: 4,
MaxID: 250126199840518145,
MaxIDStr: "250126199840518145",
NextResults: "?max_id=249279667666817023&q=%23freebandnames&count=4&include_entities=1&result_type=mixed",
Query: "%23freebandnames",
RefreshURL: "?since_id=250126199840518145&q=%23freebandnames&result_type=mixed&include_entities=1",
SinceID: 24012619984051000,
SinceIDStr: "24012619984051000",
},
Statuses: []Status{
{
Contributors: nil,
Coordinates: nil,
CreatedAt: "Mon Sep 24 03:35:21 +0000 2012",
Entities: Entities{
Hashtags: []Hashtag{{
Indices: []int{20, 34},
Text: "freebandnames"},
},
Urls: []*string{},
UserMentions: []*string{},
},
Favorited: false,
Geo: nil,
ID: 250075927172759552,
IDStr: "250075927172759552",
InReplyToScreenName: nil,
InReplyToStatusID: nil,
InReplyToStatusIDStr: nil,
InReplyToUserID: nil,
InReplyToUserIDStr: nil,
Metadata: StatusMetadata{
IsoLanguageCode: "en",
ResultType: "recent",
},
Place: nil,
RetweetCount: 0,
Retweeted: false,
Source: "<a href=\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for Mac</a>",
Text: "Aggressive Ponytail #freebandnames",
Truncated: false,
User: User{
ContributorsEnabled: false,
CreatedAt: "Mon Apr 26 06:01:55 +0000 2010",
DefaultProfile: true,
DefaultProfileImage: false,
Description: "Born 330 Live 310",
Entities: UserEntities{
Description: UserEntityDescription{
Urls: []*string{},
},
URL: UserEntityURL{
Urls: []URL{{
ExpandedURL: nil,
Indices: []int{0, 0},
URL: "",
}},
},
},
FavouritesCount: 0,
FollowRequestSent: nil,
FollowersCount: 70,
Following: nil,
FriendsCount: 110,
GeoEnabled: true,
ID: 137238150,
IDStr: "137238150",
IsTranslator: false,
Lang: "en",
ListedCount: 2,
Location: "LA, CA",
Name: "Sean Cummings",
Notifications: nil,
ProfileBackgroundColor: "C0DEED",
ProfileBackgroundImageURL: "http://a0.twimg.com/images/themes/theme1/bg.png",
ProfileBackgroundImageURLHTTPS: "https://si0.twimg.com/images/themes/theme1/bg.png",
ProfileBackgroundTile: false,
ProfileImageURL: "http://a0.twimg.com/profile_images/2359746665/1v6zfgqo8g0d3mk7ii5s_normal.jpeg",
ProfileImageURLHTTPS: "https://si0.twimg.com/profile_images/2359746665/1v6zfgqo8g0d3mk7ii5s_normal.jpeg",
ProfileLinkColor: "0084B4",
ProfileSidebarBorderColor: "C0DEED",
ProfileSidebarFillColor: "DDEEF6",
ProfileTextColor: "333333",
ProfileUseBackgroundImage: true,
Protected: false,
ScreenName: "sean_cummings",
ShowAllInlineMedia: false,
StatusesCount: 579,
TimeZone: "Pacific Time (US & Canada)",
URL: nil,
UtcOffset: -28800,
Verified: false,
},
},
{
Contributors: nil,
Coordinates: nil,
CreatedAt: "Fri Sep 21 23:40:54 +0000 2012",
Entities: Entities{
Hashtags: []Hashtag{{
Indices: []int{20, 34},
Text: "FreeBandNames",
}},
Urls: []*string{},
UserMentions: []*string{},
},
Favorited: false,
Geo: nil,
ID: 249292149810667520,
IDStr: "249292149810667520",
InReplyToScreenName: nil,
InReplyToStatusID: nil,
InReplyToStatusIDStr: nil,
InReplyToUserID: nil,
InReplyToUserIDStr: nil,
Metadata: StatusMetadata{
IsoLanguageCode: "pl",
ResultType: "recent",
},
Place: nil,
RetweetCount: 0,
Retweeted: false,
Source: "web",
Text: "Thee Namaste Nerdz. #FreeBandNames",
Truncated: false,
User: User{
ContributorsEnabled: false,
CreatedAt: "Tue Apr 07 19:05:07 +0000 2009",
DefaultProfile: false,
DefaultProfileImage: false,
Description: "You will come to Durham, North Carolina. I will sell you some records then, here in Durham, North Carolina. Fun will happen.",
Entities: UserEntities{
Description: UserEntityDescription{Urls: []*string{}},
URL: UserEntityURL{
Urls: []URL{{
ExpandedURL: nil,
Indices: []int{0, 32},
URL: "http://bullcityrecords.com/wnng/"}},
},
},
FavouritesCount: 8,
FollowRequestSent: nil,
FollowersCount: 2052,
Following: nil,
FriendsCount: 348,
GeoEnabled: false,
ID: 29516238,
IDStr: "29516238",
IsTranslator: false,
Lang: "en",
ListedCount: 118,
Location: "Durham, NC",
Name: "Chaz Martenstein",
Notifications: nil,
ProfileBackgroundColor: "9AE4E8",
ProfileBackgroundImageURL: "http://a0.twimg.com/profile_background_images/9423277/background_tile.bmp",
ProfileBackgroundImageURLHTTPS: "https://si0.twimg.com/profile_background_images/9423277/background_tile.bmp",
ProfileBackgroundTile: true,
ProfileImageURL: "http://a0.twimg.com/profile_images/447958234/Lichtenstein_normal.jpg",
ProfileImageURLHTTPS: "https://si0.twimg.com/profile_images/447958234/Lichtenstein_normal.jpg",
ProfileLinkColor: "0084B4",
ProfileSidebarBorderColor: "BDDCAD",
ProfileSidebarFillColor: "DDFFCC",
ProfileTextColor: "333333",
ProfileUseBackgroundImage: true,
Protected: false,
ScreenName: "bullcityrecords",
ShowAllInlineMedia: true,
StatusesCount: 7579,
TimeZone: "Eastern Time (US & Canada)",
URL: nil,
UtcOffset: -18000,
Verified: false,
},
},
Status{
Contributors: nil,
Coordinates: nil,
CreatedAt: "Fri Sep 21 23:30:20 +0000 2012",
Entities: Entities{
Hashtags: []Hashtag{{
Indices: []int{29, 43},
Text: "freebandnames",
}},
Urls: []*string{},
UserMentions: []*string{},
},
Favorited: false,
Geo: nil,
ID: 249289491129438208,
IDStr: "249289491129438208",
InReplyToScreenName: nil,
InReplyToStatusID: nil,
InReplyToStatusIDStr: nil,
InReplyToUserID: nil,
InReplyToUserIDStr: nil,
Metadata: StatusMetadata{
IsoLanguageCode: "en",
ResultType: "recent",
},
Place: nil,
RetweetCount: 0,
Retweeted: false,
Source: "web",
Text: "Mexican Heaven, Mexican Hell #freebandnames",
Truncated: false,
User: User{
ContributorsEnabled: false,
CreatedAt: "Tue Sep 01 21:21:35 +0000 2009",
DefaultProfile: false,
DefaultProfileImage: false,
Description: "Science Fiction Writer, sort of. Likes Superheroes, Mole People, Alt. Timelines.",
Entities: UserEntities{
Description: UserEntityDescription{
Urls: nil,
},
URL: UserEntityURL{
Urls: []URL{{
ExpandedURL: nil,
Indices: []int{0, 0},
URL: "",
}},
},
},
FavouritesCount: 19,
FollowRequestSent: nil,
FollowersCount: 63,
Following: nil,
FriendsCount: 63,
GeoEnabled: false,
ID: 70789458,
IDStr: "70789458",
IsTranslator: false,
Lang: "en",
ListedCount: 1,
Location: "Kingston New York",
Name: "Thomas John Wakeman",
Notifications: nil,
ProfileBackgroundColor: "352726",
ProfileBackgroundImageURL: "http://a0.twimg.com/images/themes/theme5/bg.gif",
ProfileBackgroundImageURLHTTPS: "https://si0.twimg.com/images/themes/theme5/bg.gif",
ProfileBackgroundTile: false,
ProfileImageURL: "http://a0.twimg.com/profile_images/2219333930/Froggystyle_normal.png",
ProfileImageURLHTTPS: "https://si0.twimg.com/profile_images/2219333930/Froggystyle_normal.png",
ProfileLinkColor: "D02B55",
ProfileSidebarBorderColor: "829D5E",
ProfileSidebarFillColor: "99CC33",
ProfileTextColor: "3E4415",
ProfileUseBackgroundImage: true,
Protected: false,
ScreenName: "MonkiesFist",
ShowAllInlineMedia: false,
StatusesCount: 1048,
TimeZone: "Eastern Time (US & Canada)",
URL: nil,
UtcOffset: -18000,
Verified: false,
},
},
Status{
Contributors: nil,
Coordinates: nil,
CreatedAt: "Fri Sep 21 22:51:18 +0000 2012",
Entities: Entities{
Hashtags: []Hashtag{{
Indices: []int{20, 34},
Text: "freebandnames",
}},
Urls: []*string{},
UserMentions: []*string{},
},
Favorited: false,
Geo: nil,
ID: 249279667666817024,
IDStr: "249279667666817024",
InReplyToScreenName: nil,
InReplyToStatusID: nil,
InReplyToStatusIDStr: nil,
InReplyToUserID: nil,
InReplyToUserIDStr: nil,
Metadata: StatusMetadata{
IsoLanguageCode: "en",
ResultType: "recent",
},
Place: nil,
RetweetCount: 0,
Retweeted: false,
Source: "<a href=\"//twitter.com/download/iphone%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for iPhone</a>",
Text: "The Foolish Mortals #freebandnames",
Truncated: false,
User: User{
ContributorsEnabled: false,
CreatedAt: "Mon May 04 00:05:00 +0000 2009",
DefaultProfile: false,
DefaultProfileImage: false,
Description: "Cartoonist, Illustrator, and T-Shirt connoisseur",
Entities: UserEntities{
Description: UserEntityDescription{
Urls: []*string{},
},
URL: UserEntityURL{
Urls: []URL{{
ExpandedURL: nil,
Indices: []int{0, 24},
URL: "http://www.omnitarian.me",
}},
},
},
FavouritesCount: 647,
FollowRequestSent: nil,
FollowersCount: 608,
Following: nil,
FriendsCount: 249,
GeoEnabled: false,
ID: 37539828,
IDStr: "37539828",
IsTranslator: false,
Lang: "en",
ListedCount: 52,
Location: "Wisconsin, USA",
Name: "Marty Elmer",
Notifications: nil,
ProfileBackgroundColor: "EEE3C4",
ProfileBackgroundImageURL: "http://a0.twimg.com/profile_background_images/106455659/rect6056-9.png",
ProfileBackgroundImageURLHTTPS: "https://si0.twimg.com/profile_background_images/106455659/rect6056-9.png",
ProfileBackgroundTile: true,
ProfileImageURL: "http://a0.twimg.com/profile_images/1629790393/shrinker_2000_trans_normal.png",
ProfileImageURLHTTPS: "https://si0.twimg.com/profile_images/1629790393/shrinker_2000_trans_normal.png",
ProfileLinkColor: "3B2A26",
ProfileSidebarBorderColor: "615A44",
ProfileSidebarFillColor: "BFAC83",
ProfileTextColor: "000000",
ProfileUseBackgroundImage: true,
Protected: false,
ScreenName: "Omnitarian",
ShowAllInlineMedia: true,
StatusesCount: 3575,
TimeZone: "Central Time (US & Canada)",
URL: nil,
UtcOffset: -21600,
Verified: false,
},
},
},
}

View File

@@ -0,0 +1,118 @@
// +build !use_easyjson,!use_ffjson,!use_codec
package benchmark
import (
"encoding/json"
"testing"
)
func BenchmarkStd_Unmarshal_M(b *testing.B) {
b.SetBytes(int64(len(largeStructText)))
for i := 0; i < b.N; i++ {
var s LargeStruct
err := json.Unmarshal(largeStructText, &s)
if err != nil {
b.Error(err)
}
}
}
func BenchmarkStd_Unmarshal_S(b *testing.B) {
for i := 0; i < b.N; i++ {
var s Entities
err := json.Unmarshal(smallStructText, &s)
if err != nil {
b.Error(err)
}
}
b.SetBytes(int64(len(smallStructText)))
}
func BenchmarkStd_Marshal_M(b *testing.B) {
var l int64
for i := 0; i < b.N; i++ {
data, err := json.Marshal(&largeStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
b.SetBytes(l)
}
func BenchmarkStd_Marshal_L(b *testing.B) {
var l int64
for i := 0; i < b.N; i++ {
data, err := json.Marshal(&xlStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
b.SetBytes(l)
}
func BenchmarkStd_Marshal_M_Parallel(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data, err := json.Marshal(&largeStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
})
b.SetBytes(l)
}
func BenchmarkStd_Marshal_L_Parallel(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data, err := json.Marshal(&xlStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
})
b.SetBytes(l)
}
func BenchmarkStd_Marshal_S(b *testing.B) {
var l int64
for i := 0; i < b.N; i++ {
data, err := json.Marshal(&smallStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
b.SetBytes(l)
}
func BenchmarkStd_Marshal_S_Parallel(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data, err := json.Marshal(&smallStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
})
b.SetBytes(l)
}
func BenchmarkStd_Marshal_M_ToWriter(b *testing.B) {
enc := json.NewEncoder(&DummyWriter{})
for i := 0; i < b.N; i++ {
err := enc.Encode(&largeStructData)
if err != nil {
b.Error(err)
}
}
}

View File

@@ -0,0 +1,11 @@
package benchmark
import (
"testing"
)
type DummyWriter struct{}
func (w DummyWriter) Write(data []byte) (int, error) { return len(data), nil }
func TestToSuppressNoTestsWarning(t *testing.T) {}

View File

@@ -0,0 +1,184 @@
// +build use_easyjson
package benchmark
import (
"testing"
"github.com/mailru/easyjson"
"github.com/mailru/easyjson/jwriter"
)
func BenchmarkEJ_Unmarshal_M(b *testing.B) {
b.SetBytes(int64(len(largeStructText)))
for i := 0; i < b.N; i++ {
var s LargeStruct
err := s.UnmarshalJSON(largeStructText)
if err != nil {
b.Error(err)
}
}
}
func BenchmarkEJ_Unmarshal_S(b *testing.B) {
b.SetBytes(int64(len(smallStructText)))
for i := 0; i < b.N; i++ {
var s Entities
err := s.UnmarshalJSON(smallStructText)
if err != nil {
b.Error(err)
}
}
}
func BenchmarkEJ_Marshal_M(b *testing.B) {
var l int64
for i := 0; i < b.N; i++ {
data, err := easyjson.Marshal(&largeStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
b.SetBytes(l)
}
func BenchmarkEJ_Marshal_L(b *testing.B) {
var l int64
for i := 0; i < b.N; i++ {
data, err := easyjson.Marshal(&xlStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
b.SetBytes(l)
}
func BenchmarkEJ_Marshal_L_ToWriter(b *testing.B) {
var l int64
out := &DummyWriter{}
for i := 0; i < b.N; i++ {
w := jwriter.Writer{}
xlStructData.MarshalEasyJSON(&w)
if w.Error != nil {
b.Error(w.Error)
}
l = int64(w.Size())
w.DumpTo(out)
}
b.SetBytes(l)
}
func BenchmarkEJ_Marshal_M_Parallel(b *testing.B) {
b.SetBytes(int64(len(largeStructText)))
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err := largeStructData.MarshalJSON()
if err != nil {
b.Error(err)
}
}
})
}
func BenchmarkEJ_Marshal_M_ToWriter(b *testing.B) {
var l int64
out := &DummyWriter{}
for i := 0; i < b.N; i++ {
w := jwriter.Writer{}
largeStructData.MarshalEasyJSON(&w)
if w.Error != nil {
b.Error(w.Error)
}
l = int64(w.Size())
w.DumpTo(out)
}
b.SetBytes(l)
}
func BenchmarkEJ_Marshal_M_ToWriter_Parallel(b *testing.B) {
out := &DummyWriter{}
b.RunParallel(func(pb *testing.PB) {
var l int64
for pb.Next() {
w := jwriter.Writer{}
largeStructData.MarshalEasyJSON(&w)
if w.Error != nil {
b.Error(w.Error)
}
l = int64(w.Size())
w.DumpTo(out)
}
if l > 0 {
b.SetBytes(l)
}
})
}
func BenchmarkEJ_Marshal_L_Parallel(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data, err := xlStructData.MarshalJSON()
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
})
b.SetBytes(l)
}
func BenchmarkEJ_Marshal_L_ToWriter_Parallel(b *testing.B) {
out := &DummyWriter{}
b.RunParallel(func(pb *testing.PB) {
var l int64
for pb.Next() {
w := jwriter.Writer{}
xlStructData.MarshalEasyJSON(&w)
if w.Error != nil {
b.Error(w.Error)
}
l = int64(w.Size())
w.DumpTo(out)
}
if l > 0 {
b.SetBytes(l)
}
})
}
func BenchmarkEJ_Marshal_S(b *testing.B) {
var l int64
for i := 0; i < b.N; i++ {
data, err := smallStructData.MarshalJSON()
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
b.SetBytes(l)
}
func BenchmarkEJ_Marshal_S_Parallel(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data, err := smallStructData.MarshalJSON()
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
})
b.SetBytes(l)
}

View File

@@ -0,0 +1,415 @@
{
"statuses": [
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Mon Sep 24 03:35:21 +0000 2012",
"id_str": "250075927172759552",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "freebandnames",
"indices": [
20,
34
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "Aggressive Ponytail #freebandnames",
"metadata": {
"iso_language_code": "en",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 250075927172759552,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "DDEEF6",
"profile_sidebar_border_color": "C0DEED",
"profile_background_tile": false,
"name": "Sean Cummings",
"profile_image_url": "http://a0.twimg.com/profile_images/2359746665/1v6zfgqo8g0d3mk7ii5s_normal.jpeg",
"created_at": "Mon Apr 26 06:01:55 +0000 2010",
"location": "LA, CA",
"follow_request_sent": null,
"profile_link_color": "0084B4",
"is_translator": false,
"id_str": "137238150",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "",
"indices": [
0,
0
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": true,
"contributors_enabled": false,
"favourites_count": 0,
"url": null,
"profile_image_url_https": "https://si0.twimg.com/profile_images/2359746665/1v6zfgqo8g0d3mk7ii5s_normal.jpeg",
"utc_offset": -28800,
"id": 137238150,
"profile_use_background_image": true,
"listed_count": 2,
"profile_text_color": "333333",
"lang": "en",
"followers_count": 70,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/images/themes/theme1/bg.png",
"profile_background_color": "C0DEED",
"verified": false,
"geo_enabled": true,
"time_zone": "Pacific Time (US & Canada)",
"description": "Born 330 Live 310",
"default_profile_image": false,
"profile_background_image_url": "http://a0.twimg.com/images/themes/theme1/bg.png",
"statuses_count": 579,
"friends_count": 110,
"following": null,
"show_all_inline_media": false,
"screen_name": "sean_cummings"
},
"in_reply_to_screen_name": null,
"source": "<a href=\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for Mac</a>",
"in_reply_to_status_id": null
},
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Fri Sep 21 23:40:54 +0000 2012",
"id_str": "249292149810667520",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "FreeBandNames",
"indices": [
20,
34
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "Thee Namaste Nerdz. #FreeBandNames",
"metadata": {
"iso_language_code": "pl",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 249292149810667520,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "DDFFCC",
"profile_sidebar_border_color": "BDDCAD",
"profile_background_tile": true,
"name": "Chaz Martenstein",
"profile_image_url": "http://a0.twimg.com/profile_images/447958234/Lichtenstein_normal.jpg",
"created_at": "Tue Apr 07 19:05:07 +0000 2009",
"location": "Durham, NC",
"follow_request_sent": null,
"profile_link_color": "0084B4",
"is_translator": false,
"id_str": "29516238",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "http://bullcityrecords.com/wnng/",
"indices": [
0,
32
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": false,
"contributors_enabled": false,
"favourites_count": 8,
"url": "http://bullcityrecords.com/wnng/",
"profile_image_url_https": "https://si0.twimg.com/profile_images/447958234/Lichtenstein_normal.jpg",
"utc_offset": -18000,
"id": 29516238,
"profile_use_background_image": true,
"listed_count": 118,
"profile_text_color": "333333",
"lang": "en",
"followers_count": 2052,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/9423277/background_tile.bmp",
"profile_background_color": "9AE4E8",
"verified": false,
"geo_enabled": false,
"time_zone": "Eastern Time (US & Canada)",
"description": "You will come to Durham, North Carolina. I will sell you some records then, here in Durham, North Carolina. Fun will happen.",
"default_profile_image": false,
"profile_background_image_url": "http://a0.twimg.com/profile_background_images/9423277/background_tile.bmp",
"statuses_count": 7579,
"friends_count": 348,
"following": null,
"show_all_inline_media": true,
"screen_name": "bullcityrecords"
},
"in_reply_to_screen_name": null,
"source": "web",
"in_reply_to_status_id": null
},
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Fri Sep 21 23:30:20 +0000 2012",
"id_str": "249289491129438208",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "freebandnames",
"indices": [
29,
43
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "Mexican Heaven, Mexican Hell #freebandnames",
"metadata": {
"iso_language_code": "en",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 249289491129438208,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "99CC33",
"profile_sidebar_border_color": "829D5E",
"profile_background_tile": false,
"name": "Thomas John Wakeman",
"profile_image_url": "http://a0.twimg.com/profile_images/2219333930/Froggystyle_normal.png",
"created_at": "Tue Sep 01 21:21:35 +0000 2009",
"location": "Kingston New York",
"follow_request_sent": null,
"profile_link_color": "D02B55",
"is_translator": false,
"id_str": "70789458",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "",
"indices": [
0,
0
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": false,
"contributors_enabled": false,
"favourites_count": 19,
"url": null,
"profile_image_url_https": "https://si0.twimg.com/profile_images/2219333930/Froggystyle_normal.png",
"utc_offset": -18000,
"id": 70789458,
"profile_use_background_image": true,
"listed_count": 1,
"profile_text_color": "3E4415",
"lang": "en",
"followers_count": 63,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/images/themes/theme5/bg.gif",
"profile_background_color": "352726",
"verified": false,
"geo_enabled": false,
"time_zone": "Eastern Time (US & Canada)",
"description": "Science Fiction Writer, sort of. Likes Superheroes, Mole People, Alt. Timelines.",
"default_profile_image": false,
"profile_background_image_url": "http://a0.twimg.com/images/themes/theme5/bg.gif",
"statuses_count": 1048,
"friends_count": 63,
"following": null,
"show_all_inline_media": false,
"screen_name": "MonkiesFist"
},
"in_reply_to_screen_name": null,
"source": "web",
"in_reply_to_status_id": null
},
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Fri Sep 21 22:51:18 +0000 2012",
"id_str": "249279667666817024",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "freebandnames",
"indices": [
20,
34
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "The Foolish Mortals #freebandnames",
"metadata": {
"iso_language_code": "en",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 249279667666817024,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "BFAC83",
"profile_sidebar_border_color": "615A44",
"profile_background_tile": true,
"name": "Marty Elmer",
"profile_image_url": "http://a0.twimg.com/profile_images/1629790393/shrinker_2000_trans_normal.png",
"created_at": "Mon May 04 00:05:00 +0000 2009",
"location": "Wisconsin, USA",
"follow_request_sent": null,
"profile_link_color": "3B2A26",
"is_translator": false,
"id_str": "37539828",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "http://www.omnitarian.me",
"indices": [
0,
24
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": false,
"contributors_enabled": false,
"favourites_count": 647,
"url": "http://www.omnitarian.me",
"profile_image_url_https": "https://si0.twimg.com/profile_images/1629790393/shrinker_2000_trans_normal.png",
"utc_offset": -21600,
"id": 37539828,
"profile_use_background_image": true,
"listed_count": 52,
"profile_text_color": "000000",
"lang": "en",
"followers_count": 608,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/106455659/rect6056-9.png",
"profile_background_color": "EEE3C4",
"verified": false,
"geo_enabled": false,
"time_zone": "Central Time (US & Canada)",
"description": "Cartoonist, Illustrator, and T-Shirt connoisseur",
"default_profile_image": false,
"profile_background_image_url": "http://a0.twimg.com/profile_background_images/106455659/rect6056-9.png",
"statuses_count": 3575,
"friends_count": 249,
"following": null,
"show_all_inline_media": true,
"screen_name": "Omnitarian"
},
"in_reply_to_screen_name": null,
"source": "<a href=\"//twitter.com/download/iphone%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for iPhone</a>",
"in_reply_to_status_id": null
}
],
"search_metadata": {
"max_id": 250126199840518145,
"since_id": 24012619984051000,
"refresh_url": "?since_id=250126199840518145&q=%23freebandnames&result_type=mixed&include_entities=1",
"next_results": "?max_id=249279667666817023&q=%23freebandnames&count=4&include_entities=1&result_type=mixed",
"count": 4,
"completed_in": 0.035,
"since_id_str": "24012619984051000",
"query": "%23freebandnames",
"max_id_str": "250126199840518145"
}
}

View File

@@ -0,0 +1,190 @@
// +build use_ffjson
package benchmark
import (
"testing"
"github.com/pquerna/ffjson/ffjson"
)
func BenchmarkFF_Unmarshal_M(b *testing.B) {
b.SetBytes(int64(len(largeStructText)))
for i := 0; i < b.N; i++ {
var s LargeStruct
err := ffjson.UnmarshalFast(largeStructText, &s)
if err != nil {
b.Error(err)
}
}
}
func BenchmarkFF_Unmarshal_S(b *testing.B) {
for i := 0; i < b.N; i++ {
var s Entities
err := ffjson.UnmarshalFast(smallStructText, &s)
if err != nil {
b.Error(err)
}
}
b.SetBytes(int64(len(smallStructText)))
}
func BenchmarkFF_Marshal_M(b *testing.B) {
var l int64
for i := 0; i < b.N; i++ {
data, err := ffjson.MarshalFast(&largeStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
b.SetBytes(l)
}
func BenchmarkFF_Marshal_S(b *testing.B) {
var l int64
for i := 0; i < b.N; i++ {
data, err := ffjson.MarshalFast(&smallStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
b.SetBytes(l)
}
func BenchmarkFF_Marshal_M_Pool(b *testing.B) {
var l int64
for i := 0; i < b.N; i++ {
data, err := ffjson.MarshalFast(&largeStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
ffjson.Pool(data)
}
b.SetBytes(l)
}
func BenchmarkFF_Marshal_L(b *testing.B) {
var l int64
for i := 0; i < b.N; i++ {
data, err := ffjson.MarshalFast(&xlStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
b.SetBytes(l)
}
func BenchmarkFF_Marshal_L_Pool(b *testing.B) {
var l int64
for i := 0; i < b.N; i++ {
data, err := ffjson.MarshalFast(&xlStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
ffjson.Pool(data)
}
b.SetBytes(l)
}
func BenchmarkFF_Marshal_L_Pool_Parallel(b *testing.B) {
var l int64
for i := 0; i < b.N; i++ {
data, err := ffjson.MarshalFast(&xlStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
ffjson.Pool(data)
}
b.SetBytes(l)
}
func BenchmarkFF_Marshal_M_Pool_Parallel(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data, err := ffjson.MarshalFast(&largeStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
ffjson.Pool(data)
}
})
b.SetBytes(l)
}
func BenchmarkFF_Marshal_S_Pool(b *testing.B) {
var l int64
for i := 0; i < b.N; i++ {
data, err := ffjson.MarshalFast(&smallStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
ffjson.Pool(data)
}
b.SetBytes(l)
}
func BenchmarkFF_Marshal_S_Pool_Parallel(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data, err := ffjson.MarshalFast(&smallStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
ffjson.Pool(data)
}
})
b.SetBytes(l)
}
func BenchmarkFF_Marshal_S_Parallel(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data, err := ffjson.MarshalFast(&smallStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
})
b.SetBytes(l)
}
func BenchmarkFF_Marshal_M_Parallel(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data, err := ffjson.MarshalFast(&largeStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
})
b.SetBytes(l)
}
func BenchmarkFF_Marshal_L_Parallel(b *testing.B) {
var l int64
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data, err := ffjson.MarshalFast(&xlStructData)
if err != nil {
b.Error(err)
}
l = int64(len(data))
}
})
b.SetBytes(l)
}

7
vendor/github.com/mailru/easyjson/benchmark/ujson.sh generated vendored Executable file
View File

@@ -0,0 +1,7 @@
#/bin/bash
echo -n "Python ujson module, DECODE: "
python -m timeit -s "import ujson; data = open('`dirname $0`/example.json', 'r').read()" 'ujson.loads(data)'
echo -n "Python ujson module, ENCODE: "
python -m timeit -s "import ujson; data = open('`dirname $0`/example.json', 'r').read(); obj = ujson.loads(data)" 'ujson.dumps(obj)'

View File

@@ -0,0 +1,180 @@
// Package bootstrap implements the bootstrapping logic: generation of a .go file to
// launch the actual generator and launching the generator itself.
//
// The package may be preferred to a command-line utility if generating the serializers
// from golang code is required.
package bootstrap
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
)
const genPackage = "github.com/mailru/easyjson/gen"
const pkgWriter = "github.com/mailru/easyjson/jwriter"
const pkgLexer = "github.com/mailru/easyjson/jlexer"
type Generator struct {
PkgPath, PkgName string
Types []string
NoStdMarshalers bool
SnakeCase bool
OmitEmpty bool
OutName string
BuildTags string
StubsOnly bool
LeaveTemps bool
NoFormat bool
}
// writeStub outputs an initial stubs for marshalers/unmarshalers so that the package
// using marshalers/unmarshales compiles correctly for boostrapping code.
func (g *Generator) writeStub() error {
f, err := os.Create(g.OutName)
if err != nil {
return err
}
defer f.Close()
if g.BuildTags != "" {
fmt.Fprintln(f, "// +build ", g.BuildTags)
fmt.Fprintln(f)
}
fmt.Fprintln(f, "// TEMPORARY AUTOGENERATED FILE: easyjson stub code to make the package")
fmt.Fprintln(f, "// compilable during generation.")
fmt.Fprintln(f)
fmt.Fprintln(f, "package ", g.PkgName)
if len(g.Types) > 0 {
fmt.Fprintln(f)
fmt.Fprintln(f, "import (")
fmt.Fprintln(f, ` "`+pkgWriter+`"`)
fmt.Fprintln(f, ` "`+pkgLexer+`"`)
fmt.Fprintln(f, ")")
}
for _, t := range g.Types {
fmt.Fprintln(f)
if !g.NoStdMarshalers {
fmt.Fprintln(f, "func (", t, ") MarshalJSON() ([]byte, error) { return nil, nil }")
fmt.Fprintln(f, "func (*", t, ") UnmarshalJSON([]byte) error { return nil }")
}
fmt.Fprintln(f, "func (", t, ") MarshalEasyJSON(w *jwriter.Writer) {}")
fmt.Fprintln(f, "func (*", t, ") UnmarshalEasyJSON(l *jlexer.Lexer) {}")
fmt.Fprintln(f)
fmt.Fprintln(f, "type EasyJSON_exporter_"+t+" *"+t)
}
return nil
}
// writeMain creates a .go file that launches the generator if 'go run'.
func (g *Generator) writeMain() (path string, err error) {
f, err := ioutil.TempFile(filepath.Dir(g.OutName), "easyjson-bootstrap")
if err != nil {
return "", err
}
fmt.Fprintln(f, "// +build ignore")
fmt.Fprintln(f)
fmt.Fprintln(f, "// TEMPORARY AUTOGENERATED FILE: easyjson bootstapping code to launch")
fmt.Fprintln(f, "// the actual generator.")
fmt.Fprintln(f)
fmt.Fprintln(f, "package main")
fmt.Fprintln(f)
fmt.Fprintln(f, "import (")
fmt.Fprintln(f, ` "fmt"`)
fmt.Fprintln(f, ` "os"`)
fmt.Fprintln(f)
fmt.Fprintf(f, " %q\n", genPackage)
if len(g.Types) > 0 {
fmt.Fprintln(f)
fmt.Fprintf(f, " pkg %q\n", g.PkgPath)
}
fmt.Fprintln(f, ")")
fmt.Fprintln(f)
fmt.Fprintln(f, "func main() {")
fmt.Fprintf(f, " g := gen.NewGenerator(%q)\n", filepath.Base(g.OutName))
fmt.Fprintf(f, " g.SetPkg(%q, %q)\n", g.PkgName, g.PkgPath)
if g.BuildTags != "" {
fmt.Fprintf(f, " g.SetBuildTags(%q)\n", g.BuildTags)
}
if g.SnakeCase {
fmt.Fprintln(f, " g.UseSnakeCase()")
}
if g.OmitEmpty {
fmt.Fprintln(f, " g.OmitEmpty()")
}
if g.NoStdMarshalers {
fmt.Fprintln(f, " g.NoStdMarshalers()")
}
for _, v := range g.Types {
fmt.Fprintln(f, " g.Add(pkg.EasyJSON_exporter_"+v+"(nil))")
}
fmt.Fprintln(f, " if err := g.Run(os.Stdout); err != nil {")
fmt.Fprintln(f, " fmt.Fprintln(os.Stderr, err)")
fmt.Fprintln(f, " os.Exit(1)")
fmt.Fprintln(f, " }")
fmt.Fprintln(f, "}")
src := f.Name()
if err := f.Close(); err != nil {
return src, err
}
dest := src + ".go"
return dest, os.Rename(src, dest)
}
func (g *Generator) Run() error {
if err := g.writeStub(); err != nil {
return err
}
if g.StubsOnly {
return nil
}
path, err := g.writeMain()
if err != nil {
return err
}
if !g.LeaveTemps {
defer os.Remove(path)
}
f, err := os.Create(g.OutName + ".tmp")
if err != nil {
return err
}
if !g.LeaveTemps {
defer os.Remove(f.Name()) // will not remove after rename
}
cmd := exec.Command("go", "run", "-tags", g.BuildTags, path)
cmd.Stdout = f
cmd.Stderr = os.Stderr
if err = cmd.Run(); err != nil {
return err
}
f.Close()
if !g.NoFormat {
cmd = exec.Command("gofmt", "-w", f.Name())
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
if err = cmd.Run(); err != nil {
return err
}
}
return os.Rename(f.Name(), g.OutName)
}

207
vendor/github.com/mailru/easyjson/buffer/pool.go generated vendored Normal file
View File

@@ -0,0 +1,207 @@
// Package buffer implements a buffer for serialization, consisting of a chain of []byte-s to
// reduce copying and to allow reuse of individual chunks.
package buffer
import (
"io"
"sync"
)
// PoolConfig contains configuration for the allocation and reuse strategy.
type PoolConfig struct {
StartSize int // Minimum chunk size that is allocated.
PooledSize int // Minimum chunk size that is reused, reusing chunks too small will result in overhead.
MaxSize int // Maximum chunk size that will be allocated.
}
var config = PoolConfig{
StartSize: 128,
PooledSize: 512,
MaxSize: 32768,
}
// Reuse pool: chunk size -> pool.
var buffers = map[int]*sync.Pool{}
func initBuffers() {
for l := config.PooledSize; l <= config.MaxSize; l *= 2 {
buffers[l] = new(sync.Pool)
}
}
func init() {
initBuffers()
}
// Init sets up a non-default pooling and allocation strategy. Should be run before serialization is done.
func Init(cfg PoolConfig) {
config = cfg
initBuffers()
}
// putBuf puts a chunk to reuse pool if it can be reused.
func putBuf(buf []byte) {
size := cap(buf)
if size < config.PooledSize {
return
}
if c := buffers[size]; c != nil {
c.Put(buf[:0])
}
}
// getBuf gets a chunk from reuse pool or creates a new one if reuse failed.
func getBuf(size int) []byte {
if size < config.PooledSize {
return make([]byte, 0, size)
}
if c := buffers[size]; c != nil {
v := c.Get()
if v != nil {
return v.([]byte)
}
}
return make([]byte, 0, size)
}
// Buffer is a buffer optimized for serialization without extra copying.
type Buffer struct {
// Buf is the current chunk that can be used for serialization.
Buf []byte
toPool []byte
bufs [][]byte
}
// EnsureSpace makes sure that the current chunk contains at least s free bytes,
// possibly creating a new chunk.
func (b *Buffer) EnsureSpace(s int) {
if cap(b.Buf)-len(b.Buf) >= s {
return
}
l := len(b.Buf)
if l > 0 {
if cap(b.toPool) != cap(b.Buf) {
// Chunk was reallocated, toPool can be pooled.
putBuf(b.toPool)
}
if cap(b.bufs) == 0 {
b.bufs = make([][]byte, 0, 8)
}
b.bufs = append(b.bufs, b.Buf)
l = cap(b.toPool) * 2
} else {
l = config.StartSize
}
if l > config.MaxSize {
l = config.MaxSize
}
b.Buf = getBuf(l)
b.toPool = b.Buf
}
// AppendByte appends a single byte to buffer.
func (b *Buffer) AppendByte(data byte) {
if cap(b.Buf) == len(b.Buf) { // EnsureSpace won't be inlined.
b.EnsureSpace(1)
}
b.Buf = append(b.Buf, data)
}
// AppendBytes appends a byte slice to buffer.
func (b *Buffer) AppendBytes(data []byte) {
for len(data) > 0 {
if cap(b.Buf) == len(b.Buf) { // EnsureSpace won't be inlined.
b.EnsureSpace(1)
}
sz := cap(b.Buf) - len(b.Buf)
if sz > len(data) {
sz = len(data)
}
b.Buf = append(b.Buf, data[:sz]...)
data = data[sz:]
}
}
// AppendBytes appends a string to buffer.
func (b *Buffer) AppendString(data string) {
for len(data) > 0 {
if cap(b.Buf) == len(b.Buf) { // EnsureSpace won't be inlined.
b.EnsureSpace(1)
}
sz := cap(b.Buf) - len(b.Buf)
if sz > len(data) {
sz = len(data)
}
b.Buf = append(b.Buf, data[:sz]...)
data = data[sz:]
}
}
// Size computes the size of a buffer by adding sizes of every chunk.
func (b *Buffer) Size() int {
size := len(b.Buf)
for _, buf := range b.bufs {
size += len(buf)
}
return size
}
// DumpTo outputs the contents of a buffer to a writer and resets the buffer.
func (b *Buffer) DumpTo(w io.Writer) (written int, err error) {
var n int
for _, buf := range b.bufs {
if err == nil {
n, err = w.Write(buf)
written += n
}
putBuf(buf)
}
if err == nil {
n, err = w.Write(b.Buf)
written += n
}
putBuf(b.toPool)
b.bufs = nil
b.Buf = nil
b.toPool = nil
return
}
// BuildBytes creates a single byte slice with all the contents of the buffer. Data is
// copied if it does not fit in a single chunk.
func (b *Buffer) BuildBytes() []byte {
if len(b.bufs) == 0 {
ret := b.Buf
b.toPool = nil
b.Buf = nil
return ret
}
ret := make([]byte, 0, b.Size())
for _, buf := range b.bufs {
ret = append(ret, buf...)
putBuf(buf)
}
ret = append(ret, b.Buf...)
putBuf(b.toPool)
b.bufs = nil
b.toPool = nil
b.Buf = nil
return ret
}

79
vendor/github.com/mailru/easyjson/buffer/pool_test.go generated vendored Normal file
View File

@@ -0,0 +1,79 @@
package buffer
import (
"bytes"
"testing"
)
func TestAppendByte(t *testing.T) {
var b Buffer
var want []byte
for i := 0; i < 1000; i++ {
b.AppendByte(1)
b.AppendByte(2)
want = append(want, 1, 2)
}
got := b.BuildBytes()
if !bytes.Equal(got, want) {
t.Errorf("BuildBytes() = %v; want %v", got, want)
}
}
func TestAppendBytes(t *testing.T) {
var b Buffer
var want []byte
for i := 0; i < 1000; i++ {
b.AppendBytes([]byte{1, 2})
want = append(want, 1, 2)
}
got := b.BuildBytes()
if !bytes.Equal(got, want) {
t.Errorf("BuildBytes() = %v; want %v", got, want)
}
}
func TestAppendString(t *testing.T) {
var b Buffer
var want []byte
s := "test"
for i := 0; i < 1000; i++ {
b.AppendBytes([]byte(s))
want = append(want, s...)
}
got := b.BuildBytes()
if !bytes.Equal(got, want) {
t.Errorf("BuildBytes() = %v; want %v", got, want)
}
}
func TestDumpTo(t *testing.T) {
var b Buffer
var want []byte
s := "test"
for i := 0; i < 1000; i++ {
b.AppendBytes([]byte(s))
want = append(want, s...)
}
out := &bytes.Buffer{}
n, err := b.DumpTo(out)
if err != nil {
t.Errorf("DumpTo() error: %v", err)
}
got := out.Bytes()
if !bytes.Equal(got, want) {
t.Errorf("DumpTo(): got %v; want %v", got, want)
}
if n != len(want) {
t.Errorf("DumpTo() = %v; want %v", n, len(want))
}
}

83
vendor/github.com/mailru/easyjson/easyjson/main.go generated vendored Normal file
View File

@@ -0,0 +1,83 @@
package main
import (
"flag"
"fmt"
"os"
"strings"
"github.com/mailru/easyjson/bootstrap"
// Reference the gen package to be friendly to vendoring tools,
// as it is an indirect dependency.
// (The temporary bootstrapping code uses it.)
_ "github.com/mailru/easyjson/gen"
"github.com/mailru/easyjson/parser"
)
var buildTags = flag.String("build_tags", "", "build tags to add to generated file")
var snakeCase = flag.Bool("snake_case", false, "use snake_case names instead of CamelCase by default")
var noStdMarshalers = flag.Bool("no_std_marshalers", false, "don't generate MarshalJSON/UnmarshalJSON methods")
var omitEmpty = flag.Bool("omit_empty", false, "omit empty fields by default")
var allStructs = flag.Bool("all", false, "generate un-/marshallers for all structs in a file")
var leaveTemps = flag.Bool("leave_temps", false, "do not delete temporary files")
var stubs = flag.Bool("stubs", false, "only generate stubs for marshallers/unmarshallers methods")
var noformat = flag.Bool("noformat", false, "do not run 'gofmt -w' on output file")
var specifiedName = flag.String("output_filename", "", "specify the filename of the output")
func generate(fname string) (err error) {
p := parser.Parser{AllStructs: *allStructs}
if err := p.Parse(fname); err != nil {
return fmt.Errorf("Error parsing %v: %v", fname, err)
}
var outName string
if s := strings.TrimSuffix(fname, ".go"); s == fname {
return fmt.Errorf("Filename must end in '.go'")
} else {
outName = s + "_easyjson.go"
}
if *specifiedName != "" {
outName = *specifiedName
}
g := bootstrap.Generator{
BuildTags: *buildTags,
PkgPath: p.PkgPath,
PkgName: p.PkgName,
Types: p.StructNames,
SnakeCase: *snakeCase,
NoStdMarshalers: *noStdMarshalers,
OmitEmpty: *omitEmpty,
LeaveTemps: *leaveTemps,
OutName: outName,
StubsOnly: *stubs,
NoFormat: *noformat,
}
if err := g.Run(); err != nil {
return fmt.Errorf("Bootstrap failed: %v", err)
}
return nil
}
func main() {
flag.Parse()
files := flag.Args()
gofile := os.Getenv("GOFILE")
if len(files) == 0 && gofile != "" {
files = []string{gofile}
} else if len(files) == 0 {
flag.Usage()
os.Exit(1)
}
for _, fname := range files {
if err := generate(fname); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
}

385
vendor/github.com/mailru/easyjson/gen/decoder.go generated vendored Normal file
View File

@@ -0,0 +1,385 @@
package gen
import (
"encoding/json"
"fmt"
"reflect"
"strings"
"unicode"
"github.com/mailru/easyjson"
)
// Target this byte size for initial slice allocation to reduce garbage collection.
const minSliceBytes = 64
func (g *Generator) getDecoderName(t reflect.Type) string {
return g.functionName("decode", t)
}
var primitiveDecoders = map[reflect.Kind]string{
reflect.String: "in.String()",
reflect.Bool: "in.Bool()",
reflect.Int: "in.Int()",
reflect.Int8: "in.Int8()",
reflect.Int16: "in.Int16()",
reflect.Int32: "in.Int32()",
reflect.Int64: "in.Int64()",
reflect.Uint: "in.Uint()",
reflect.Uint8: "in.Uint8()",
reflect.Uint16: "in.Uint16()",
reflect.Uint32: "in.Uint32()",
reflect.Uint64: "in.Uint64()",
reflect.Float32: "in.Float32()",
reflect.Float64: "in.Float64()",
}
var primitiveStringDecoders = map[reflect.Kind]string{
reflect.Int: "in.IntStr()",
reflect.Int8: "in.Int8Str()",
reflect.Int16: "in.Int16Str()",
reflect.Int32: "in.Int32Str()",
reflect.Int64: "in.Int64Str()",
reflect.Uint: "in.UintStr()",
reflect.Uint8: "in.Uint8Str()",
reflect.Uint16: "in.Uint16Str()",
reflect.Uint32: "in.Uint32Str()",
reflect.Uint64: "in.Uint64Str()",
}
// genTypeDecoder generates decoding code for the type t, but uses unmarshaler interface if implemented by t.
func (g *Generator) genTypeDecoder(t reflect.Type, out string, tags fieldTags, indent int) error {
ws := strings.Repeat(" ", indent)
unmarshalerIface := reflect.TypeOf((*easyjson.Unmarshaler)(nil)).Elem()
if reflect.PtrTo(t).Implements(unmarshalerIface) {
fmt.Fprintln(g.out, ws+"("+out+").UnmarshalEasyJSON(in)")
return nil
}
unmarshalerIface = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
if reflect.PtrTo(t).Implements(unmarshalerIface) {
fmt.Fprintln(g.out, ws+"if data := in.Raw(); in.Ok() {")
fmt.Fprintln(g.out, ws+" in.AddError( ("+out+").UnmarshalJSON(data) )")
fmt.Fprintln(g.out, ws+"}")
return nil
}
err := g.genTypeDecoderNoCheck(t, out, tags, indent)
return err
}
// genTypeDecoderNoCheck generates decoding code for the type t.
func (g *Generator) genTypeDecoderNoCheck(t reflect.Type, out string, tags fieldTags, indent int) error {
ws := strings.Repeat(" ", indent)
// Check whether type is primitive, needs to be done after interface check.
if dec := primitiveStringDecoders[t.Kind()]; dec != "" && tags.asString {
fmt.Fprintln(g.out, ws+out+" = "+g.getType(t)+"("+dec+")")
return nil
} else if dec := primitiveDecoders[t.Kind()]; dec != "" {
fmt.Fprintln(g.out, ws+out+" = "+g.getType(t)+"("+dec+")")
return nil
}
switch t.Kind() {
case reflect.Slice:
tmpVar := g.uniqueVarName()
elem := t.Elem()
capacity := minSliceBytes / elem.Size()
if capacity == 0 {
capacity = 1
}
fmt.Fprintln(g.out, ws+"in.Delim('[')")
fmt.Fprintln(g.out, ws+"if !in.IsDelim(']') {")
fmt.Fprintln(g.out, ws+" "+out+" = make("+g.getType(t)+", 0, "+fmt.Sprint(capacity)+")")
fmt.Fprintln(g.out, ws+"} else {")
fmt.Fprintln(g.out, ws+" "+out+" = nil")
fmt.Fprintln(g.out, ws+"}")
fmt.Fprintln(g.out, ws+"for !in.IsDelim(']') {")
fmt.Fprintln(g.out, ws+" var "+tmpVar+" "+g.getType(elem))
g.genTypeDecoder(elem, tmpVar, tags, indent+1)
fmt.Fprintln(g.out, ws+" "+out+" = append("+out+", "+tmpVar+")")
fmt.Fprintln(g.out, ws+" in.WantComma()")
fmt.Fprintln(g.out, ws+"}")
fmt.Fprintln(g.out, ws+"in.Delim(']')")
case reflect.Struct:
dec := g.getDecoderName(t)
g.addType(t)
fmt.Fprintln(g.out, ws+dec+"(in, &"+out+")")
case reflect.Ptr:
fmt.Fprintln(g.out, ws+"if in.IsNull() {")
fmt.Fprintln(g.out, ws+" in.Skip()")
fmt.Fprintln(g.out, ws+" "+out+" = nil")
fmt.Fprintln(g.out, ws+"} else {")
fmt.Fprintln(g.out, ws+" "+out+" = new("+g.getType(t.Elem())+")")
g.genTypeDecoder(t.Elem(), "*"+out, tags, indent+1)
fmt.Fprintln(g.out, ws+"}")
case reflect.Map:
key := t.Key()
if key.Kind() != reflect.String {
return fmt.Errorf("map type %v not supported: only string keys are allowed", key)
}
elem := t.Elem()
tmpVar := g.uniqueVarName()
fmt.Fprintln(g.out, ws+"if in.IsNull() {")
fmt.Fprintln(g.out, ws+" in.Skip()")
fmt.Fprintln(g.out, ws+"} else {")
fmt.Fprintln(g.out, ws+" in.Delim('{')")
fmt.Fprintln(g.out, ws+" if !in.IsDelim('}') {")
fmt.Fprintln(g.out, ws+" "+out+" = make("+g.getType(t)+")")
fmt.Fprintln(g.out, ws+" } else {")
fmt.Fprintln(g.out, ws+" "+out+" = nil")
fmt.Fprintln(g.out, ws+" }")
fmt.Fprintln(g.out, ws+" for !in.IsDelim('}') {")
fmt.Fprintln(g.out, ws+" key := "+g.getType(t.Key())+"(in.String())")
fmt.Fprintln(g.out, ws+" in.WantColon()")
fmt.Fprintln(g.out, ws+" var "+tmpVar+" "+g.getType(elem))
g.genTypeDecoder(elem, tmpVar, tags, indent+2)
fmt.Fprintln(g.out, ws+" ("+out+")[key] = "+tmpVar)
fmt.Fprintln(g.out, ws+" in.WantComma()")
fmt.Fprintln(g.out, ws+" }")
fmt.Fprintln(g.out, ws+" in.Delim('}')")
fmt.Fprintln(g.out, ws+"}")
case reflect.Interface:
if t.NumMethod() != 0 {
return fmt.Errorf("interface type %v not supported: only interface{} is allowed", t)
}
fmt.Fprintln(g.out, ws+out+" = in.Interface()")
default:
return fmt.Errorf("don't know how to decode %v", t)
}
return nil
}
func (g *Generator) genStructFieldDecoder(t reflect.Type, f reflect.StructField) error {
jsonName := g.fieldNamer.GetJSONFieldName(t, f)
tags := parseFieldTags(f)
if tags.omit {
return nil
}
fmt.Fprintf(g.out, " case %q:\n", jsonName)
if err := g.genTypeDecoder(f.Type, "out."+f.Name, tags, 3); err != nil {
return err
}
if tags.required {
fmt.Fprintf(g.out, "%sSet = true\n", f.Name)
}
return nil
}
func (g *Generator) genRequiredFieldSet(t reflect.Type, f reflect.StructField) {
tags := parseFieldTags(f)
if !tags.required {
return
}
fmt.Fprintf(g.out, "var %sSet bool\n", f.Name)
}
func (g *Generator) genRequiredFieldCheck(t reflect.Type, f reflect.StructField) {
jsonName := g.fieldNamer.GetJSONFieldName(t, f)
tags := parseFieldTags(f)
if !tags.required {
return
}
g.imports["fmt"] = "fmt"
fmt.Fprintf(g.out, "if !%sSet {\n", f.Name)
fmt.Fprintf(g.out, " in.AddError(fmt.Errorf(\"key '%s' is required\"))\n", jsonName)
fmt.Fprintf(g.out, "}\n")
}
func mergeStructFields(fields1, fields2 []reflect.StructField) (fields []reflect.StructField) {
used := map[string]bool{}
for _, f := range fields2 {
used[f.Name] = true
fields = append(fields, f)
}
for _, f := range fields1 {
if !used[f.Name] {
fields = append(fields, f)
}
}
return
}
func getStructFields(t reflect.Type) ([]reflect.StructField, error) {
if t.Kind() != reflect.Struct {
return nil, fmt.Errorf("got %v; expected a struct", t)
}
var efields []reflect.StructField
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if !f.Anonymous {
continue
}
t1 := f.Type
if t1.Kind() == reflect.Ptr {
t1 = t1.Elem()
}
fs, err := getStructFields(t1)
if err != nil {
return nil, fmt.Errorf("error processing embedded field: %v", err)
}
efields = mergeStructFields(efields, fs)
}
var fields []reflect.StructField
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if f.Anonymous {
continue
}
c := []rune(f.Name)[0]
if unicode.IsUpper(c) {
fields = append(fields, f)
}
}
return mergeStructFields(efields, fields), nil
}
func (g *Generator) genDecoder(t reflect.Type) error {
switch t.Kind() {
case reflect.Slice:
return g.genSliceDecoder(t)
default:
return g.genStructDecoder(t)
}
}
func (g *Generator) genSliceDecoder(t reflect.Type) error {
if t.Kind() != reflect.Slice {
return fmt.Errorf("cannot generate encoder/decoder for %v, not a slice type", t)
}
fname := g.getDecoderName(t)
typ := g.getType(t)
fmt.Fprintln(g.out, "func "+fname+"(in *jlexer.Lexer, out *"+typ+") {")
err := g.genTypeDecoderNoCheck(t, "*out", fieldTags{}, 1)
if err != nil {
return err
}
fmt.Fprintln(g.out, "}")
return nil
}
func (g *Generator) genStructDecoder(t reflect.Type) error {
if t.Kind() != reflect.Struct {
return fmt.Errorf("cannot generate encoder/decoder for %v, not a struct type", t)
}
fname := g.getDecoderName(t)
typ := g.getType(t)
fmt.Fprintln(g.out, "func "+fname+"(in *jlexer.Lexer, out *"+typ+") {")
fmt.Fprintln(g.out, " if in.IsNull() {")
fmt.Fprintln(g.out, " in.Skip()")
fmt.Fprintln(g.out, " return")
fmt.Fprintln(g.out, " }")
// Init embedded pointer fields.
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if !f.Anonymous || f.Type.Kind() != reflect.Ptr {
continue
}
fmt.Fprintln(g.out, " out."+f.Name+" = new("+g.getType(f.Type.Elem())+")")
}
fs, err := getStructFields(t)
if err != nil {
return fmt.Errorf("cannot generate decoder for %v: %v", t, err)
}
for _, f := range fs {
g.genRequiredFieldSet(t, f)
}
fmt.Fprintln(g.out, " in.Delim('{')")
fmt.Fprintln(g.out, " for !in.IsDelim('}') {")
fmt.Fprintln(g.out, " key := in.UnsafeString()")
fmt.Fprintln(g.out, " in.WantColon()")
fmt.Fprintln(g.out, " if in.IsNull() {")
fmt.Fprintln(g.out, " in.Skip()")
fmt.Fprintln(g.out, " in.WantComma()")
fmt.Fprintln(g.out, " continue")
fmt.Fprintln(g.out, " }")
fmt.Fprintln(g.out, " switch key {")
for _, f := range fs {
if err := g.genStructFieldDecoder(t, f); err != nil {
return err
}
}
fmt.Fprintln(g.out, " default:")
fmt.Fprintln(g.out, " in.SkipRecursive()")
fmt.Fprintln(g.out, " }")
fmt.Fprintln(g.out, " in.WantComma()")
fmt.Fprintln(g.out, " }")
fmt.Fprintln(g.out, " in.Delim('}')")
for _, f := range fs {
g.genRequiredFieldCheck(t, f)
}
fmt.Fprintln(g.out, "}")
return nil
}
func (g *Generator) genStructUnmarshaller(t reflect.Type) error {
if t.Kind() != reflect.Struct && t.Kind() != reflect.Slice {
return fmt.Errorf("cannot generate encoder/decoder for %v, not a struct/slice type", t)
}
fname := g.getDecoderName(t)
typ := g.getType(t)
if !g.noStdMarshalers {
fmt.Fprintln(g.out, "// UnmarshalJSON supports json.Unmarshaler interface")
fmt.Fprintln(g.out, "func (v *"+typ+") UnmarshalJSON(data []byte) error {")
fmt.Fprintln(g.out, " r := jlexer.Lexer{Data: data}")
fmt.Fprintln(g.out, " "+fname+"(&r, v)")
fmt.Fprintln(g.out, " return r.Error()")
fmt.Fprintln(g.out, "}")
}
fmt.Fprintln(g.out, "// UnmarshalEasyJSON supports easyjson.Unmarshaler interface")
fmt.Fprintln(g.out, "func (v *"+typ+") UnmarshalEasyJSON(l *jlexer.Lexer) {")
fmt.Fprintln(g.out, " "+fname+"(l, v)")
fmt.Fprintln(g.out, "}")
return nil
}

313
vendor/github.com/mailru/easyjson/gen/encoder.go generated vendored Normal file
View File

@@ -0,0 +1,313 @@
package gen
import (
"encoding/json"
"fmt"
"reflect"
"strconv"
"strings"
"github.com/mailru/easyjson"
)
func (g *Generator) getEncoderName(t reflect.Type) string {
return g.functionName("encode", t)
}
var primitiveEncoders = map[reflect.Kind]string{
reflect.String: "out.String(string(%v))",
reflect.Bool: "out.Bool(bool(%v))",
reflect.Int: "out.Int(int(%v))",
reflect.Int8: "out.Int8(int8(%v))",
reflect.Int16: "out.Int16(int16(%v))",
reflect.Int32: "out.Int32(int32(%v))",
reflect.Int64: "out.Int64(int64(%v))",
reflect.Uint: "out.Uint(uint(%v))",
reflect.Uint8: "out.Uint8(uint8(%v))",
reflect.Uint16: "out.Uint16(uint16(%v))",
reflect.Uint32: "out.Uint32(uint32(%v))",
reflect.Uint64: "out.Uint64(uint64(%v))",
reflect.Float32: "out.Float32(float32(%v))",
reflect.Float64: "out.Float64(float64(%v))",
}
var primitiveStringEncoders = map[reflect.Kind]string{
reflect.Int: "out.IntStr(int(%v))",
reflect.Int8: "out.Int8Str(int8(%v))",
reflect.Int16: "out.Int16Str(int16(%v))",
reflect.Int32: "out.Int32Str(int32(%v))",
reflect.Int64: "out.Int64Str(int64(%v))",
reflect.Uint: "out.UintStr(uint(%v))",
reflect.Uint8: "out.Uint8Str(uint8(%v))",
reflect.Uint16: "out.Uint16Str(uint16(%v))",
reflect.Uint32: "out.Uint32Str(uint32(%v))",
reflect.Uint64: "out.Uint64Str(uint64(%v))",
}
// fieldTags contains parsed version of json struct field tags.
type fieldTags struct {
name string
omit bool
omitEmpty bool
noOmitEmpty bool
asString bool
required bool
}
// parseFieldTags parses the json field tag into a structure.
func parseFieldTags(f reflect.StructField) fieldTags {
var ret fieldTags
for i, s := range strings.Split(f.Tag.Get("json"), ",") {
switch {
case i == 0 && s == "-":
ret.omit = true
case i == 0:
ret.name = s
case s == "omitempty":
ret.omitEmpty = true
case s == "!omitempty":
ret.noOmitEmpty = true
case s == "string":
ret.asString = true
case s == "required":
ret.required = true
}
}
return ret
}
// genTypeEncoder generates code that encodes in of type t into the writer, but uses marshaler interface if implemented by t.
func (g *Generator) genTypeEncoder(t reflect.Type, in string, tags fieldTags, indent int) error {
ws := strings.Repeat(" ", indent)
marshalerIface := reflect.TypeOf((*easyjson.Marshaler)(nil)).Elem()
if reflect.PtrTo(t).Implements(marshalerIface) {
fmt.Fprintln(g.out, ws+"("+in+").MarshalEasyJSON(out)")
return nil
}
marshalerIface = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
if reflect.PtrTo(t).Implements(marshalerIface) {
fmt.Fprintln(g.out, ws+"out.Raw( ("+in+").MarshalJSON() )")
return nil
}
err := g.genTypeEncoderNoCheck(t, in, tags, indent)
return err
}
// genTypeEncoderNoCheck generates code that encodes in of type t into the writer.
func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldTags, indent int) error {
ws := strings.Repeat(" ", indent)
// Check whether type is primitive, needs to be done after interface check.
if enc := primitiveStringEncoders[t.Kind()]; enc != "" && tags.asString {
fmt.Fprintf(g.out, ws+enc+"\n", in)
return nil
} else if enc := primitiveEncoders[t.Kind()]; enc != "" {
fmt.Fprintf(g.out, ws+enc+"\n", in)
return nil
}
switch t.Kind() {
case reflect.Slice:
elem := t.Elem()
iVar := g.uniqueVarName()
vVar := g.uniqueVarName()
fmt.Fprintln(g.out, ws+"out.RawByte('[')")
fmt.Fprintln(g.out, ws+"for "+iVar+", "+vVar+" := range "+in+" {")
fmt.Fprintln(g.out, ws+" if "+iVar+" > 0 {")
fmt.Fprintln(g.out, ws+" out.RawByte(',')")
fmt.Fprintln(g.out, ws+" }")
g.genTypeEncoder(elem, vVar, tags, indent+1)
fmt.Fprintln(g.out, ws+"}")
fmt.Fprintln(g.out, ws+"out.RawByte(']')")
case reflect.Struct:
enc := g.getEncoderName(t)
g.addType(t)
fmt.Fprintln(g.out, ws+enc+"(out, "+in+")")
case reflect.Ptr:
fmt.Fprintln(g.out, ws+"if "+in+" == nil {")
fmt.Fprintln(g.out, ws+` out.RawString("null")`)
fmt.Fprintln(g.out, ws+"} else {")
g.genTypeEncoder(t.Elem(), "*"+in, tags, indent+1)
fmt.Fprintln(g.out, ws+"}")
case reflect.Map:
key := t.Key()
if key.Kind() != reflect.String {
return fmt.Errorf("map type %v not supported: only string keys are allowed", key)
}
tmpVar := g.uniqueVarName()
fmt.Fprintln(g.out, ws+"if "+in+" == nil {")
fmt.Fprintln(g.out, ws+" out.RawString(`null`)")
fmt.Fprintln(g.out, ws+"} else {")
fmt.Fprintln(g.out, ws+" out.RawByte('{')")
fmt.Fprintln(g.out, ws+" "+tmpVar+"First := true")
fmt.Fprintln(g.out, ws+" for "+tmpVar+"Name, "+tmpVar+"Value := range "+in+" {")
fmt.Fprintln(g.out, ws+" if !"+tmpVar+"First { out.RawByte(',') }")
fmt.Fprintln(g.out, ws+" "+tmpVar+"First = false")
fmt.Fprintln(g.out, ws+" out.String(string("+tmpVar+"Name))")
fmt.Fprintln(g.out, ws+" out.RawByte(':')")
g.genTypeEncoder(t.Elem(), tmpVar+"Value", tags, indent+2)
fmt.Fprintln(g.out, ws+" }")
fmt.Fprintln(g.out, ws+" out.RawByte('}')")
fmt.Fprintln(g.out, ws+"}")
case reflect.Interface:
if t.NumMethod() != 0 {
return fmt.Errorf("interface type %v not supported: only interface{} is allowed", t)
}
fmt.Fprintln(g.out, ws+"out.Raw(json.Marshal("+in+"))")
default:
return fmt.Errorf("don't know how to encode %v", t)
}
return nil
}
func (g *Generator) notEmptyCheck(t reflect.Type, v string) string {
optionalIface := reflect.TypeOf((*easyjson.Optional)(nil)).Elem()
if reflect.PtrTo(t).Implements(optionalIface) {
return "(" + v + ").IsDefined()"
}
switch t.Kind() {
case reflect.Slice, reflect.Map:
return "len(" + v + ") != 0"
case reflect.Interface, reflect.Ptr:
return v + " != nil"
case reflect.Bool:
return v
case reflect.String:
return v + ` != ""`
case reflect.Float32, reflect.Float64,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return v + " != 0"
default:
return "true"
}
}
func (g *Generator) genStructFieldEncoder(t reflect.Type, f reflect.StructField) error {
jsonName := g.fieldNamer.GetJSONFieldName(t, f)
tags := parseFieldTags(f)
if tags.omit {
return nil
}
if !tags.omitEmpty && !g.omitEmpty || tags.noOmitEmpty {
fmt.Fprintln(g.out, " if !first { out.RawByte(',') }")
fmt.Fprintln(g.out, " first = false")
fmt.Fprintf(g.out, " out.RawString(%q)\n", strconv.Quote(jsonName)+":")
return g.genTypeEncoder(f.Type, "in."+f.Name, tags, 1)
}
fmt.Fprintln(g.out, " if", g.notEmptyCheck(f.Type, "in."+f.Name), "{")
fmt.Fprintln(g.out, " if !first { out.RawByte(',') }")
fmt.Fprintln(g.out, " first = false")
fmt.Fprintf(g.out, " out.RawString(%q)\n", strconv.Quote(jsonName)+":")
if err := g.genTypeEncoder(f.Type, "in."+f.Name, tags, 2); err != nil {
return err
}
fmt.Fprintln(g.out, " }")
return nil
}
func (g *Generator) genEncoder(t reflect.Type) error {
switch t.Kind() {
case reflect.Slice:
return g.genSliceEncoder(t)
default:
return g.genStructEncoder(t)
}
}
func (g *Generator) genSliceEncoder(t reflect.Type) error {
if t.Kind() != reflect.Slice {
return fmt.Errorf("cannot generate encoder/decoder for %v, not a slice type", t)
}
fname := g.getEncoderName(t)
typ := g.getType(t)
fmt.Fprintln(g.out, "func "+fname+"(out *jwriter.Writer, in "+typ+") {")
err := g.genTypeEncoderNoCheck(t, "in", fieldTags{}, 1)
if err != nil {
return err
}
fmt.Fprintln(g.out, "}")
return nil
}
func (g *Generator) genStructEncoder(t reflect.Type) error {
if t.Kind() != reflect.Struct {
return fmt.Errorf("cannot generate encoder/decoder for %v, not a struct type")
}
fname := g.getEncoderName(t)
typ := g.getType(t)
fmt.Fprintln(g.out, "func "+fname+"(out *jwriter.Writer, in "+typ+") {")
fmt.Fprintln(g.out, " out.RawByte('{')")
fmt.Fprintln(g.out, " first := true")
fmt.Fprintln(g.out, " _ = first")
fs, err := getStructFields(t)
if err != nil {
return fmt.Errorf("cannot generate encoder for %v: %v", t, err)
}
for _, f := range fs {
if err := g.genStructFieldEncoder(t, f); err != nil {
return err
}
}
fmt.Fprintln(g.out, " out.RawByte('}')")
fmt.Fprintln(g.out, "}")
return nil
}
func (g *Generator) genStructMarshaller(t reflect.Type) error {
if t.Kind() != reflect.Struct && t.Kind() != reflect.Slice {
return fmt.Errorf("cannot generate encoder/decoder for %v, not a struct/slice type", t)
}
fname := g.getEncoderName(t)
typ := g.getType(t)
if !g.noStdMarshalers {
fmt.Fprintln(g.out, "// MarshalJSON supports json.Marshaler interface")
fmt.Fprintln(g.out, "func (v "+typ+") MarshalJSON() ([]byte, error) {")
fmt.Fprintln(g.out, " w := jwriter.Writer{}")
fmt.Fprintln(g.out, " "+fname+"(&w, v)")
fmt.Fprintln(g.out, " return w.Buffer.BuildBytes(), w.Error")
fmt.Fprintln(g.out, "}")
}
fmt.Fprintln(g.out, "// MarshalEasyJSON supports easyjson.Marshaler interface")
fmt.Fprintln(g.out, "func (v "+typ+") MarshalEasyJSON(w *jwriter.Writer) {")
fmt.Fprintln(g.out, " "+fname+"(w, v)")
fmt.Fprintln(g.out, "}")
return nil
}

395
vendor/github.com/mailru/easyjson/gen/generator.go generated vendored Normal file
View File

@@ -0,0 +1,395 @@
package gen
import (
"bytes"
"fmt"
"hash/fnv"
"io"
"path"
"reflect"
"sort"
"strings"
"unicode"
)
const pkgWriter = "github.com/mailru/easyjson/jwriter"
const pkgLexer = "github.com/mailru/easyjson/jlexer"
// FieldNamer defines a policy for generating names for struct fields.
type FieldNamer interface {
GetJSONFieldName(t reflect.Type, f reflect.StructField) string
}
// Generator generates the requested marshallers/unmarshallers.
type Generator struct {
out *bytes.Buffer
pkgName string
pkgPath string
buildTags string
hashString string
varCounter int
noStdMarshalers bool
omitEmpty bool
fieldNamer FieldNamer
// package path to local alias map for tracking imports
imports map[string]string
// types that marshallers were requested for by user
marshallers map[reflect.Type]bool
// types that encoders were already generated for
typesSeen map[reflect.Type]bool
// types that encoders were requested for (e.g. by encoders of other types)
typesUnseen []reflect.Type
// function name to relevant type maps to track names of de-/encoders in
// case of a name clash or unnamed structs
functionNames map[string]reflect.Type
}
// NewGenerator initializes and returns a Generator.
func NewGenerator(filename string) *Generator {
ret := &Generator{
imports: map[string]string{
pkgWriter: "jwriter",
pkgLexer: "jlexer",
"encoding/json": "json",
},
fieldNamer: DefaultFieldNamer{},
marshallers: make(map[reflect.Type]bool),
typesSeen: make(map[reflect.Type]bool),
functionNames: make(map[string]reflect.Type),
}
// Use a file-unique prefix on all auxiliary functions to avoid
// name clashes.
hash := fnv.New32()
hash.Write([]byte(filename))
ret.hashString = fmt.Sprintf("%x", hash.Sum32())
return ret
}
// SetPkg sets the name and path of output package.
func (g *Generator) SetPkg(name, path string) {
g.pkgName = name
g.pkgPath = path
}
// SetBuildTags sets build tags for the output file.
func (g *Generator) SetBuildTags(tags string) {
g.buildTags = tags
}
// SetFieldNamer sets field naming strategy.
func (g *Generator) SetFieldNamer(n FieldNamer) {
g.fieldNamer = n
}
// UseSnakeCase sets snake_case field naming strategy.
func (g *Generator) UseSnakeCase() {
g.fieldNamer = SnakeCaseFieldNamer{}
}
// NoStdMarshalers instructs not to generate standard MarshalJSON/UnmarshalJSON
// methods (only the custom interface).
func (g *Generator) NoStdMarshalers() {
g.noStdMarshalers = true
}
// OmitEmpty triggers `json=",omitempty"` behaviour by default.
func (g *Generator) OmitEmpty() {
g.omitEmpty = true
}
// addTypes requests to generate en-/decoding functions for the given type.
func (g *Generator) addType(t reflect.Type) {
if g.typesSeen[t] {
return
}
for _, t1 := range g.typesUnseen {
if t1 == t {
return
}
}
g.typesUnseen = append(g.typesUnseen, t)
}
// Add requests to generate (un-)marshallers and en-/decoding functions for the type of given object.
func (g *Generator) Add(obj interface{}) {
t := reflect.TypeOf(obj)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
g.addType(t)
g.marshallers[t] = true
}
// printHeader prints package declaration and imports.
func (g *Generator) printHeader() {
if g.buildTags != "" {
fmt.Println("// +build ", g.buildTags)
fmt.Println()
}
fmt.Println("// AUTOGENERATED FILE: easyjson marshaller/unmarshallers.")
fmt.Println()
fmt.Println("package ", g.pkgName)
fmt.Println()
byAlias := map[string]string{}
var aliases []string
for path, alias := range g.imports {
aliases = append(aliases, alias)
byAlias[alias] = path
}
sort.Strings(aliases)
fmt.Println("import (")
for _, alias := range g.imports {
fmt.Printf(" %s %q\n", alias, byAlias[alias])
}
fmt.Println(")")
fmt.Println("")
fmt.Println("// suppress unused package warning")
fmt.Println("var (")
fmt.Println(" _ = json.RawMessage{}")
fmt.Println(" _ = jlexer.Lexer{}")
fmt.Println(" _ = jwriter.Writer{}")
fmt.Println(")")
fmt.Println()
}
// Run runs the generator and outputs generated code to out.
func (g *Generator) Run(out io.Writer) error {
g.out = &bytes.Buffer{}
for len(g.typesUnseen) > 0 {
t := g.typesUnseen[len(g.typesUnseen)-1]
g.typesUnseen = g.typesUnseen[:len(g.typesUnseen)-1]
g.typesSeen[t] = true
if err := g.genDecoder(t); err != nil {
return err
}
if err := g.genEncoder(t); err != nil {
return err
}
if !g.marshallers[t] {
continue
}
if err := g.genStructMarshaller(t); err != nil {
return err
}
if err := g.genStructUnmarshaller(t); err != nil {
return err
}
}
g.printHeader()
_, err := out.Write(g.out.Bytes())
return err
}
// pkgAlias creates and returns and import alias for a given package.
func (g *Generator) pkgAlias(pkgPath string) string {
if alias := g.imports[pkgPath]; alias != "" {
return alias
}
for i := 0; ; i++ {
alias := path.Base(pkgPath)
if i > 0 {
alias += fmt.Sprint(i)
}
exists := false
for _, v := range g.imports {
if v == alias {
exists = true
break
}
}
if !exists {
g.imports[pkgPath] = alias
return alias
}
}
}
// getType return the textual type name of given type that can be used in generated code.
func (g *Generator) getType(t reflect.Type) string {
if t.Name() == "" {
switch t.Kind() {
case reflect.Ptr:
return "*" + g.getType(t.Elem())
case reflect.Slice:
return "[]" + g.getType(t.Elem())
case reflect.Map:
return "map[" + g.getType(t.Key()) + "]" + g.getType(t.Elem())
}
}
if t.Name() == "" || t.PkgPath() == "" {
return t.String()
} else if t.PkgPath() == g.pkgPath {
return t.Name()
}
// TODO: unnamed structs.
return g.pkgAlias(t.PkgPath()) + "." + t.Name()
}
// uniqueVarName returns a file-unique name that can be used for generated variables.
func (g *Generator) uniqueVarName() string {
g.varCounter++
return fmt.Sprint("v", g.varCounter)
}
// safeName escapes unsafe characters in pkg/type name and returns a string that can be used
// in encoder/decoder names for the type.
func (g *Generator) safeName(t reflect.Type) string {
name := t.PkgPath()
if t.Name() == "" {
name += "anonymous"
} else {
name += "." + t.Name()
}
parts := []string{}
part := []rune{}
for _, c := range name {
if unicode.IsLetter(c) || unicode.IsDigit(c) {
part = append(part, c)
} else if len(part) > 0 {
parts = append(parts, string(part))
part = []rune{}
}
}
return joinFunctionNameParts(false, parts...)
}
// functionName returns a function name for a given type with a given prefix. If a function
// with this prefix already exists for a type, it is returned.
//
// Method is used to track encoder/decoder names for the type.
func (g *Generator) functionName(prefix string, t reflect.Type) string {
prefix = joinFunctionNameParts(true, "easyjson", g.hashString, prefix)
name := joinFunctionNameParts(true, prefix, g.safeName(t))
// Most of the names will be unique, try a shortcut first.
if e, ok := g.functionNames[name]; !ok || e == t {
g.functionNames[name] = t
return name
}
// Search if the function already exists.
for name1, t1 := range g.functionNames {
if t1 == t && strings.HasPrefix(name1, prefix) {
return name1
}
}
// Create a new name in the case of a clash.
for i := 1; ; i++ {
nm := fmt.Sprint(name, i)
if _, ok := g.functionNames[nm]; ok {
continue
}
g.functionNames[nm] = t
return nm
}
}
// DefaultFieldsNamer implements trivial naming policy equivalent to encoding/json.
type DefaultFieldNamer struct{}
func (DefaultFieldNamer) GetJSONFieldName(t reflect.Type, f reflect.StructField) string {
jsonName := strings.Split(f.Tag.Get("json"), ",")[0]
if jsonName != "" {
return jsonName
} else {
return f.Name
}
}
// SnakeCaseFieldNamer implements CamelCase to snake_case conversion for fields names.
type SnakeCaseFieldNamer struct{}
func camelToSnake(name string) string {
var ret bytes.Buffer
multipleUpper := false
var lastUpper rune
var beforeUpper rune
for _, c := range name {
// Non-lowercase character after uppercase is considered to be uppercase too.
isUpper := (unicode.IsUpper(c) || (lastUpper != 0 && !unicode.IsLower(c)))
if lastUpper != 0 {
// Output a delimiter if last character was either the first uppercase character
// in a row, or the last one in a row (e.g. 'S' in "HTTPServer").
// Do not output a delimiter at the beginning of the name.
firstInRow := !multipleUpper
lastInRow := !isUpper
if ret.Len() > 0 && (firstInRow || lastInRow) && beforeUpper != '_' {
ret.WriteByte('_')
}
ret.WriteRune(unicode.ToLower(lastUpper))
}
// Buffer uppercase char, do not output it yet as a delimiter may be required if the
// next character is lowercase.
if isUpper {
multipleUpper = (lastUpper != 0)
lastUpper = c
continue
}
ret.WriteRune(c)
lastUpper = 0
beforeUpper = c
multipleUpper = false
}
if lastUpper != 0 {
ret.WriteRune(unicode.ToLower(lastUpper))
}
return string(ret.Bytes())
}
func (SnakeCaseFieldNamer) GetJSONFieldName(t reflect.Type, f reflect.StructField) string {
jsonName := strings.Split(f.Tag.Get("json"), ",")[0]
if jsonName != "" {
return jsonName
}
return camelToSnake(f.Name)
}
func joinFunctionNameParts(keepFirst bool, parts ...string) string {
buf := bytes.NewBufferString("")
for i, part := range parts {
if i == 0 && keepFirst {
buf.WriteString(part)
} else {
if len(part) > 0 {
buf.WriteString(strings.ToUpper(string(part[0])))
}
if len(part) > 1 {
buf.WriteString(part[1:])
}
}
}
return buf.String()
}

View File

@@ -0,0 +1,49 @@
package gen
import (
"testing"
)
func TestCamelToSnake(t *testing.T) {
for i, test := range []struct {
In, Out string
}{
{"", ""},
{"A", "a"},
{"SimpleExample", "simple_example"},
{"internalField", "internal_field"},
{"SomeHTTPStuff", "some_http_stuff"},
{"WriteJSON", "write_json"},
{"HTTP2Server", "http2_server"},
{"Some_Mixed_Case", "some_mixed_case"},
{"do_nothing", "do_nothing"},
{"JSONHTTPRPCServer", "jsonhttprpc_server"}, // nothing can be done here without a dictionary
} {
got := camelToSnake(test.In)
if got != test.Out {
t.Errorf("[%d] camelToSnake(%s) = %s; want %s", i, test.In, got, test.Out)
}
}
}
func TestJoinFunctionNameParts(t *testing.T) {
for i, test := range []struct {
keepFirst bool
parts []string
out string
}{
{false, []string{}, ""},
{false, []string{"a"}, "A"},
{false, []string{"simple", "example"}, "SimpleExample"},
{true, []string{"first", "example"}, "firstExample"},
{false, []string{"some", "UPPER", "case"}, "SomeUPPERCase"},
{false, []string{"number", "123"}, "Number123"},
} {
got := joinFunctionNameParts(test.keepFirst, test.parts...)
if got != test.out {
t.Errorf("[%d] joinFunctionNameParts(%v) = %s; want %s", i, test.parts, got, test.out)
}
}
}

78
vendor/github.com/mailru/easyjson/helpers.go generated vendored Normal file
View File

@@ -0,0 +1,78 @@
// Package easyjson contains marshaler/unmarshaler interfaces and helper functions.
package easyjson
import (
"io"
"io/ioutil"
"net/http"
"strconv"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// Marshaler is an easyjson-compatible marshaler interface.
type Marshaler interface {
MarshalEasyJSON(w *jwriter.Writer)
}
// Marshaler is an easyjson-compatible unmarshaler interface.
type Unmarshaler interface {
UnmarshalEasyJSON(w *jlexer.Lexer)
}
// Optional defines an undefined-test method for a type to integrate with 'omitempty' logic.
type Optional interface {
IsDefined() bool
}
// Marshal returns data as a single byte slice. Method is suboptimal as the data is likely to be copied
// from a chain of smaller chunks.
func Marshal(v Marshaler) ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.BuildBytes()
}
// MarshalToWriter marshals the data to an io.Writer.
func MarshalToWriter(v Marshaler, w io.Writer) (written int, err error) {
jw := jwriter.Writer{}
v.MarshalEasyJSON(&jw)
return jw.DumpTo(w)
}
// MarshalToHTTPResponseWriter sets Content-Length and Content-Type headers for the
// http.ResponseWriter, and send the data to the writer. started will be equal to
// false if an error occurred before any http.ResponseWriter methods were actually
// invoked (in this case a 500 reply is possible).
func MarshalToHTTPResponseWriter(v Marshaler, w http.ResponseWriter) (started bool, written int, err error) {
jw := jwriter.Writer{}
v.MarshalEasyJSON(&jw)
if jw.Error != nil {
return false, 0, jw.Error
}
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Length", strconv.Itoa(jw.Size()))
started = true
written, err = jw.DumpTo(w)
return
}
// Unmarshal decodes the JSON in data into the object.
func Unmarshal(data []byte, v Unmarshaler) error {
l := jlexer.Lexer{Data: data}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// UnmarshalFromReader reads all the data in the reader and decodes as JSON into the object.
func UnmarshalFromReader(r io.Reader, v Unmarshaler) error {
data, err := ioutil.ReadAll(r)
if err != nil {
return err
}
l := jlexer.Lexer{Data: data}
v.UnmarshalEasyJSON(&l)
return l.Error()
}

15
vendor/github.com/mailru/easyjson/jlexer/error.go generated vendored Normal file
View File

@@ -0,0 +1,15 @@
package jlexer
import "fmt"
// LexerError implements the error interface and represents all possible errors that can be
// generated during parsing the JSON data.
type LexerError struct {
Reason string
Offset int
Data string
}
func (l *LexerError) Error() string {
return fmt.Sprintf("parse error: %s near offset %d of '%s'", l.Reason, l.Offset, l.Data)
}

956
vendor/github.com/mailru/easyjson/jlexer/lexer.go generated vendored Normal file
View File

@@ -0,0 +1,956 @@
// Package jlexer contains a JSON lexer implementation.
//
// It is expected that it is mostly used with generated parser code, so the interface is tuned
// for a parser that knows what kind of data is expected.
package jlexer
import (
"fmt"
"io"
"reflect"
"strconv"
"unicode/utf8"
"unsafe"
)
// tokenKind determines type of a token.
type tokenKind byte
const (
tokenUndef tokenKind = iota // No token.
tokenDelim // Delimiter: one of '{', '}', '[' or ']'.
tokenString // A string literal, e.g. "abc\u1234"
tokenNumber // Number literal, e.g. 1.5e5
tokenBool // Boolean literal: true or false.
tokenNull // null keyword.
)
// token describes a single token: type, position in the input and value.
type token struct {
kind tokenKind // Type of a token.
boolValue bool // Value if a boolean literal token.
byteValue []byte // Raw value of a token.
delimValue byte
}
// Lexer is a JSON lexer: it iterates over JSON tokens in a byte slice.
type Lexer struct {
Data []byte // Input data given to the lexer.
start int // Start of the current token.
pos int // Current unscanned position in the input stream.
token token // Last scanned token, if token.kind != tokenUndef.
firstElement bool // Whether current element is the first in array or an object.
wantSep byte // A comma or a colon character, which need to occur before a token.
err error // Error encountered during lexing, if any.
}
// fetchToken scans the input for the next token.
func (r *Lexer) fetchToken() {
r.token.kind = tokenUndef
r.start = r.pos
// Check if r.Data has r.pos element
// If it doesn't, it mean corrupted input data
if len(r.Data) < r.pos {
r.errParse("Unexpected end of data")
return
}
// Determine the type of a token by skipping whitespace and reading the
// first character.
for _, c := range r.Data[r.pos:] {
switch c {
case ':', ',':
if r.wantSep == c {
r.pos++
r.start++
r.wantSep = 0
} else {
r.errSyntax()
}
case ' ', '\t', '\r', '\n':
r.pos++
r.start++
case '"':
if r.wantSep != 0 {
r.errSyntax()
}
r.token.kind = tokenString
r.fetchString()
return
case '{', '[':
if r.wantSep != 0 {
r.errSyntax()
}
r.firstElement = true
r.token.kind = tokenDelim
r.token.delimValue = r.Data[r.pos]
r.pos++
return
case '}', ']':
if !r.firstElement && (r.wantSep != ',') {
r.errSyntax()
}
r.wantSep = 0
r.token.kind = tokenDelim
r.token.delimValue = r.Data[r.pos]
r.pos++
return
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-':
if r.wantSep != 0 {
r.errSyntax()
}
r.token.kind = tokenNumber
r.fetchNumber()
return
case 'n':
if r.wantSep != 0 {
r.errSyntax()
}
r.token.kind = tokenNull
r.fetchNull()
return
case 't':
if r.wantSep != 0 {
r.errSyntax()
}
r.token.kind = tokenBool
r.token.boolValue = true
r.fetchTrue()
return
case 'f':
if r.wantSep != 0 {
r.errSyntax()
}
r.token.kind = tokenBool
r.token.boolValue = false
r.fetchFalse()
return
default:
r.errSyntax()
return
}
}
r.err = io.EOF
return
}
// isTokenEnd returns true if the char can follow a non-delimiter token
func isTokenEnd(c byte) bool {
return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '[' || c == ']' || c == '{' || c == '}' || c == ',' || c == ':'
}
// fetchNull fetches and checks remaining bytes of null keyword.
func (r *Lexer) fetchNull() {
r.pos += 4
if r.pos > len(r.Data) ||
r.Data[r.pos-3] != 'u' ||
r.Data[r.pos-2] != 'l' ||
r.Data[r.pos-1] != 'l' ||
(r.pos != len(r.Data) && !isTokenEnd(r.Data[r.pos])) {
r.pos -= 4
r.errSyntax()
}
}
// fetchTrue fetches and checks remaining bytes of true keyword.
func (r *Lexer) fetchTrue() {
r.pos += 4
if r.pos > len(r.Data) ||
r.Data[r.pos-3] != 'r' ||
r.Data[r.pos-2] != 'u' ||
r.Data[r.pos-1] != 'e' ||
(r.pos != len(r.Data) && !isTokenEnd(r.Data[r.pos])) {
r.pos -= 4
r.errSyntax()
}
}
// fetchFalse fetches and checks remaining bytes of false keyword.
func (r *Lexer) fetchFalse() {
r.pos += 5
if r.pos > len(r.Data) ||
r.Data[r.pos-4] != 'a' ||
r.Data[r.pos-3] != 'l' ||
r.Data[r.pos-2] != 's' ||
r.Data[r.pos-1] != 'e' ||
(r.pos != len(r.Data) && !isTokenEnd(r.Data[r.pos])) {
r.pos -= 5
r.errSyntax()
}
}
// bytesToStr creates a string pointing at the slice to avoid copying.
//
// Warning: the string returned by the function should be used with care, as the whole input data
// chunk may be either blocked from being freed by GC because of a single string or the buffer.Data
// may be garbage-collected even when the string exists.
func bytesToStr(data []byte) string {
h := (*reflect.SliceHeader)(unsafe.Pointer(&data))
shdr := reflect.StringHeader{h.Data, h.Len}
return *(*string)(unsafe.Pointer(&shdr))
}
// fetchNumber scans a number literal token.
func (r *Lexer) fetchNumber() {
hasE := false
afterE := false
hasDot := false
r.pos++
for i, c := range r.Data[r.pos:] {
switch {
case c >= '0' && c <= '9':
afterE = false
case c == '.' && !hasDot:
hasDot = true
case (c == 'e' || c == 'E') && !hasE:
hasE = true
hasDot = true
afterE = true
case (c == '+' || c == '-') && afterE:
afterE = false
default:
r.pos += i
if !isTokenEnd(c) {
r.errSyntax()
} else {
r.token.byteValue = r.Data[r.start:r.pos]
}
return
}
}
r.pos = len(r.Data)
r.token.byteValue = r.Data[r.start:]
}
// findStringLen tries to scan into the string literal for ending quote char to determine required size.
// The size will be exact if no escapes are present and may be inexact if there are escaped chars.
func findStringLen(data []byte) (hasEscapes bool, length int) {
delta := 0
for i := 0; i < len(data); i++ {
switch data[i] {
case '\\':
i++
delta++
if i < len(data) && data[i] == 'u' {
delta++
}
case '"':
return (delta > 0), (i - delta)
}
}
return false, len(data)
}
// processEscape processes a single escape sequence and returns number of bytes processed.
func (r *Lexer) processEscape(data []byte) (int, error) {
if len(data) < 2 {
return 0, fmt.Errorf("syntax error at %v", string(data))
}
c := data[1]
switch c {
case '"', '/', '\\':
r.token.byteValue = append(r.token.byteValue, c)
return 2, nil
case 'b':
r.token.byteValue = append(r.token.byteValue, '\b')
return 2, nil
case 'f':
r.token.byteValue = append(r.token.byteValue, '\f')
return 2, nil
case 'n':
r.token.byteValue = append(r.token.byteValue, '\n')
return 2, nil
case 'r':
r.token.byteValue = append(r.token.byteValue, '\r')
return 2, nil
case 't':
r.token.byteValue = append(r.token.byteValue, '\t')
return 2, nil
case 'u':
default:
return 0, fmt.Errorf("syntax error")
}
var val rune
for i := 2; i < len(data) && i < 6; i++ {
var v byte
c = data[i]
switch c {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
v = c - '0'
case 'a', 'b', 'c', 'd', 'e', 'f':
v = c - 'a' + 10
case 'A', 'B', 'C', 'D', 'E', 'F':
v = c - 'A' + 10
default:
return 0, fmt.Errorf("syntax error")
}
val <<= 4
val |= rune(v)
}
l := utf8.RuneLen(val)
if l == -1 {
return 0, fmt.Errorf("invalid unicode escape")
}
var d [4]byte
utf8.EncodeRune(d[:], val)
r.token.byteValue = append(r.token.byteValue, d[:l]...)
return 6, nil
}
// fetchString scans a string literal token.
func (r *Lexer) fetchString() {
r.pos++
data := r.Data[r.pos:]
hasEscapes, length := findStringLen(data)
if !hasEscapes {
r.token.byteValue = data[:length]
r.pos += length + 1
return
}
r.token.byteValue = make([]byte, 0, length)
p := 0
for i := 0; i < len(data); {
switch data[i] {
case '"':
r.pos += i + 1
r.token.byteValue = append(r.token.byteValue, data[p:i]...)
i++
return
case '\\':
r.token.byteValue = append(r.token.byteValue, data[p:i]...)
off, err := r.processEscape(data[i:])
if err != nil {
r.errParse(err.Error())
return
}
i += off
p = i
default:
i++
}
}
r.errParse("unterminated string literal")
}
// scanToken scans the next token if no token is currently available in the lexer.
func (r *Lexer) scanToken() {
if r.token.kind != tokenUndef || r.err != nil {
return
}
r.fetchToken()
}
// consume resets the current token to allow scanning the next one.
func (r *Lexer) consume() {
r.token.kind = tokenUndef
r.token.delimValue = 0
}
// Ok returns true if no error (including io.EOF) was encountered during scanning.
func (r *Lexer) Ok() bool {
return r.err == nil
}
const maxErrorContextLen = 13
func (r *Lexer) errParse(what string) {
if r.err == nil {
var str string
if len(r.Data)-r.pos <= maxErrorContextLen {
str = string(r.Data)
} else {
str = string(r.Data[r.pos:r.pos+maxErrorContextLen-3]) + "..."
}
r.err = &LexerError{
Reason: what,
Offset: r.pos,
Data: str,
}
}
}
func (r *Lexer) errSyntax() {
r.errParse("syntax error")
}
func (r *Lexer) errInvalidToken(expected string) {
if r.err == nil {
var str string
if len(r.token.byteValue) <= maxErrorContextLen {
str = string(r.token.byteValue)
} else {
str = string(r.token.byteValue[:maxErrorContextLen-3]) + "..."
}
r.err = &LexerError{
Reason: fmt.Sprintf("expected %s", expected),
Offset: r.pos,
Data: str,
}
}
}
// Delim consumes a token and verifies that it is the given delimiter.
func (r *Lexer) Delim(c byte) {
if r.token.kind == tokenUndef && r.Ok() {
r.fetchToken()
}
if !r.Ok() || r.token.delimValue != c {
r.errInvalidToken(string([]byte{c}))
}
r.consume()
}
// IsDelim returns true if there was no scanning error and next token is the given delimiter.
func (r *Lexer) IsDelim(c byte) bool {
if r.token.kind == tokenUndef && r.Ok() {
r.fetchToken()
}
return !r.Ok() || r.token.delimValue == c
}
// Null verifies that the next token is null and consumes it.
func (r *Lexer) Null() {
if r.token.kind == tokenUndef && r.Ok() {
r.fetchToken()
}
if !r.Ok() || r.token.kind != tokenNull {
r.errInvalidToken("null")
}
r.consume()
}
// IsNull returns true if the next token is a null keyword.
func (r *Lexer) IsNull() bool {
if r.token.kind == tokenUndef && r.Ok() {
r.fetchToken()
}
return r.Ok() && r.token.kind == tokenNull
}
// Skip skips a single token.
func (r *Lexer) Skip() {
if r.token.kind == tokenUndef && r.Ok() {
r.fetchToken()
}
r.consume()
}
// SkipRecursive skips next array or object completely, or just skips a single token if not
// an array/object.
//
// Note: no syntax validation is performed on the skipped data.
func (r *Lexer) SkipRecursive() {
r.scanToken()
var start, end byte
if r.token.delimValue == '{' {
start, end = '{', '}'
} else if r.token.delimValue == '[' {
start, end = '[', ']'
} else {
r.consume()
return
}
r.consume()
level := 1
inQuotes := false
wasEscape := false
for i, c := range r.Data[r.pos:] {
switch {
case c == start && !inQuotes:
level++
case c == end && !inQuotes:
level--
if level == 0 {
r.pos += i + 1
return
}
case c == '\\' && inQuotes:
wasEscape = true
continue
case c == '"' && inQuotes:
inQuotes = wasEscape
case c == '"':
inQuotes = true
}
wasEscape = false
}
r.pos = len(r.Data)
r.err = io.EOF
}
// Raw fetches the next item recursively as a data slice
func (r *Lexer) Raw() []byte {
r.SkipRecursive()
if !r.Ok() {
return nil
}
return r.Data[r.start:r.pos]
}
// UnsafeString returns the string value if the token is a string literal.
//
// Warning: returned string may point to the input buffer, so the string should not outlive
// the input buffer. Intended pattern of usage is as an argument to a switch statement.
func (r *Lexer) UnsafeString() string {
if r.token.kind == tokenUndef && r.Ok() {
r.fetchToken()
}
if !r.Ok() || r.token.kind != tokenString {
r.errInvalidToken("string")
return ""
}
ret := bytesToStr(r.token.byteValue)
r.consume()
return ret
}
// String reads a string literal.
func (r *Lexer) String() string {
if r.token.kind == tokenUndef && r.Ok() {
r.fetchToken()
}
if !r.Ok() || r.token.kind != tokenString {
r.errInvalidToken("string")
return ""
}
ret := string(r.token.byteValue)
r.consume()
return ret
}
// Bool reads a true or false boolean keyword.
func (r *Lexer) Bool() bool {
if r.token.kind == tokenUndef && r.Ok() {
r.fetchToken()
}
if !r.Ok() || r.token.kind != tokenBool {
r.errInvalidToken("bool")
return false
}
ret := r.token.boolValue
r.consume()
return ret
}
func (r *Lexer) number() string {
if r.token.kind == tokenUndef && r.Ok() {
r.fetchToken()
}
if !r.Ok() || r.token.kind != tokenNumber {
r.errInvalidToken("number")
return ""
}
ret := bytesToStr(r.token.byteValue)
r.consume()
return ret
}
func (r *Lexer) Uint8() uint8 {
s := r.number()
if !r.Ok() {
return 0
}
n, err := strconv.ParseUint(s, 10, 8)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return uint8(n)
}
func (r *Lexer) Uint16() uint16 {
s := r.number()
if !r.Ok() {
return 0
}
n, err := strconv.ParseUint(s, 10, 16)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return uint16(n)
}
func (r *Lexer) Uint32() uint32 {
s := r.number()
if !r.Ok() {
return 0
}
n, err := strconv.ParseUint(s, 10, 32)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return uint32(n)
}
func (r *Lexer) Uint64() uint64 {
s := r.number()
if !r.Ok() {
return 0
}
n, err := strconv.ParseUint(s, 10, 64)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return n
}
func (r *Lexer) Uint() uint {
return uint(r.Uint64())
}
func (r *Lexer) Int8() int8 {
s := r.number()
if !r.Ok() {
return 0
}
n, err := strconv.ParseInt(s, 10, 8)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return int8(n)
}
func (r *Lexer) Int16() int16 {
s := r.number()
if !r.Ok() {
return 0
}
n, err := strconv.ParseInt(s, 10, 16)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return int16(n)
}
func (r *Lexer) Int32() int32 {
s := r.number()
if !r.Ok() {
return 0
}
n, err := strconv.ParseInt(s, 10, 32)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return int32(n)
}
func (r *Lexer) Int64() int64 {
s := r.number()
if !r.Ok() {
return 0
}
n, err := strconv.ParseInt(s, 10, 64)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return n
}
func (r *Lexer) Int() int {
return int(r.Int64())
}
func (r *Lexer) Uint8Str() uint8 {
s := r.UnsafeString()
if !r.Ok() {
return 0
}
n, err := strconv.ParseUint(s, 10, 8)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return uint8(n)
}
func (r *Lexer) Uint16Str() uint16 {
s := r.UnsafeString()
if !r.Ok() {
return 0
}
n, err := strconv.ParseUint(s, 10, 16)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return uint16(n)
}
func (r *Lexer) Uint32Str() uint32 {
s := r.UnsafeString()
if !r.Ok() {
return 0
}
n, err := strconv.ParseUint(s, 10, 32)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return uint32(n)
}
func (r *Lexer) Uint64Str() uint64 {
s := r.UnsafeString()
if !r.Ok() {
return 0
}
n, err := strconv.ParseUint(s, 10, 64)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return n
}
func (r *Lexer) UintStr() uint {
return uint(r.Uint64Str())
}
func (r *Lexer) Int8Str() int8 {
s := r.UnsafeString()
if !r.Ok() {
return 0
}
n, err := strconv.ParseInt(s, 10, 8)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return int8(n)
}
func (r *Lexer) Int16Str() int16 {
s := r.UnsafeString()
if !r.Ok() {
return 0
}
n, err := strconv.ParseInt(s, 10, 16)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return int16(n)
}
func (r *Lexer) Int32Str() int32 {
s := r.UnsafeString()
if !r.Ok() {
return 0
}
n, err := strconv.ParseInt(s, 10, 32)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return int32(n)
}
func (r *Lexer) Int64Str() int64 {
s := r.UnsafeString()
if !r.Ok() {
return 0
}
n, err := strconv.ParseInt(s, 10, 64)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return n
}
func (r *Lexer) IntStr() int {
return int(r.Int64Str())
}
func (r *Lexer) Float32() float32 {
s := r.number()
if !r.Ok() {
return 0
}
n, err := strconv.ParseFloat(s, 32)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return float32(n)
}
func (r *Lexer) Float64() float64 {
s := r.number()
if !r.Ok() {
return 0
}
n, err := strconv.ParseFloat(s, 64)
if err != nil {
r.err = &LexerError{
Reason: err.Error(),
}
}
return n
}
func (r *Lexer) Error() error {
return r.err
}
func (r *Lexer) AddError(e error) {
if r.err == nil {
r.err = e
}
}
// Interface fetches an interface{} analogous to the 'encoding/json' package.
func (r *Lexer) Interface() interface{} {
if r.token.kind == tokenUndef && r.Ok() {
r.fetchToken()
}
if !r.Ok() {
return nil
}
switch r.token.kind {
case tokenString:
return r.String()
case tokenNumber:
return r.Float64()
case tokenBool:
return r.Bool()
case tokenNull:
r.Null()
return nil
}
if r.token.delimValue == '{' {
r.consume()
ret := map[string]interface{}{}
for !r.IsDelim('}') {
key := r.String()
r.WantColon()
ret[key] = r.Interface()
r.WantComma()
}
r.Delim('}')
if r.Ok() {
return ret
} else {
return nil
}
} else if r.token.delimValue == '[' {
r.consume()
var ret []interface{}
for !r.IsDelim(']') {
ret = append(ret, r.Interface())
r.WantComma()
}
r.Delim(']')
if r.Ok() {
return ret
} else {
return nil
}
}
r.errSyntax()
return nil
}
// WantComma requires a comma to be present before fetching next token.
func (r *Lexer) WantComma() {
r.wantSep = ','
r.firstElement = false
}
// WantColon requires a colon to be present before fetching next token.
func (r *Lexer) WantColon() {
r.wantSep = ':'
r.firstElement = false
}

192
vendor/github.com/mailru/easyjson/jlexer/lexer_test.go generated vendored Normal file
View File

@@ -0,0 +1,192 @@
package jlexer
import (
"reflect"
"testing"
)
func TestString(t *testing.T) {
for i, test := range []struct {
toParse string
want string
wantError bool
}{
{toParse: `"simple string"`, want: "simple string"},
{toParse: " \r\r\n\t " + `"test"`, want: "test"},
{toParse: `"\n\t\"\/\\\f\r"`, want: "\n\t\"/\\\f\r"},
{toParse: `"\u0020"`, want: " "},
{toParse: `"\u0020-\t"`, want: " -\t"},
{toParse: `"\ufffd\uFFFD"`, want: "\ufffd\ufffd"},
{toParse: `"test"junk`, want: "test"},
{toParse: `5`, wantError: true}, // not a string
{toParse: `"\x"`, wantError: true}, // invalid escape
{toParse: `"\ud800"`, wantError: true}, // invalid utf-8 char
} {
l := Lexer{Data: []byte(test.toParse)}
got := l.String()
if got != test.want {
t.Errorf("[%d, %q] String() = %v; want %v", i, test.toParse, got, test.want)
}
err := l.Error()
if err != nil && !test.wantError {
t.Errorf("[%d, %q] String() error: %v", i, test.toParse, err)
} else if err == nil && test.wantError {
t.Errorf("[%d, %q] String() ok; want error", i, test.toParse)
}
}
}
func TestNumber(t *testing.T) {
for i, test := range []struct {
toParse string
want string
wantError bool
}{
{toParse: "123", want: "123"},
{toParse: "-123", want: "-123"},
{toParse: "\r\n12.35", want: "12.35"},
{toParse: "12.35e+1", want: "12.35e+1"},
{toParse: "12.35e-15", want: "12.35e-15"},
{toParse: "12.35E-15", want: "12.35E-15"},
{toParse: "12.35E15", want: "12.35E15"},
{toParse: `"a"`, wantError: true},
{toParse: "123junk", wantError: true},
{toParse: "1.2.3", wantError: true},
{toParse: "1e2e3", wantError: true},
{toParse: "1e2.3", wantError: true},
} {
l := Lexer{Data: []byte(test.toParse)}
got := l.number()
if got != test.want {
t.Errorf("[%d, %q] number() = %v; want %v", i, test.toParse, got, test.want)
}
err := l.Error()
if err != nil && !test.wantError {
t.Errorf("[%d, %q] number() error: %v", i, test.toParse, err)
} else if err == nil && test.wantError {
t.Errorf("[%d, %q] number() ok; want error", i, test.toParse)
}
}
}
func TestBool(t *testing.T) {
for i, test := range []struct {
toParse string
want bool
wantError bool
}{
{toParse: "true", want: true},
{toParse: "false", want: false},
{toParse: "1", wantError: true},
{toParse: "truejunk", wantError: true},
{toParse: `false"junk"`, wantError: true},
{toParse: "True", wantError: true},
{toParse: "False", wantError: true},
} {
l := Lexer{Data: []byte(test.toParse)}
got := l.Bool()
if got != test.want {
t.Errorf("[%d, %q] Bool() = %v; want %v", i, test.toParse, got, test.want)
}
err := l.Error()
if err != nil && !test.wantError {
t.Errorf("[%d, %q] Bool() error: %v", i, test.toParse, err)
} else if err == nil && test.wantError {
t.Errorf("[%d, %q] Bool() ok; want error", i, test.toParse)
}
}
}
func TestSkipRecursive(t *testing.T) {
for i, test := range []struct {
toParse string
left string
wantError bool
}{
{toParse: "5, 4", left: ", 4"},
{toParse: "[5, 6], 4", left: ", 4"},
{toParse: "[5, [7,8]]: 4", left: ": 4"},
{toParse: `{"a":1}, 4`, left: ", 4"},
{toParse: `{"a":1, "b":{"c": 5}, "e":[12,15]}, 4`, left: ", 4"},
// array start/end chars in a string
{toParse: `[5, "]"], 4`, left: ", 4"},
{toParse: `[5, "\"]"], 4`, left: ", 4"},
{toParse: `[5, "["], 4`, left: ", 4"},
{toParse: `[5, "\"["], 4`, left: ", 4"},
// object start/end chars in a string
{toParse: `{"a}":1}, 4`, left: ", 4"},
{toParse: `{"a\"}":1}, 4`, left: ", 4"},
{toParse: `{"a{":1}, 4`, left: ", 4"},
{toParse: `{"a\"{":1}, 4`, left: ", 4"},
} {
l := Lexer{Data: []byte(test.toParse)}
l.SkipRecursive()
got := string(l.Data[l.pos:])
if got != test.left {
t.Errorf("[%d, %q] SkipRecursive() left = %v; want %v", i, test.toParse, got, test.left)
}
err := l.Error()
if err != nil && !test.wantError {
t.Errorf("[%d, %q] SkipRecursive() error: %v", i, test.toParse, err)
} else if err == nil && test.wantError {
t.Errorf("[%d, %q] SkipRecursive() ok; want error", i, test.toParse)
}
}
}
func TestInterface(t *testing.T) {
for i, test := range []struct {
toParse string
want interface{}
wantError bool
}{
{toParse: "null", want: nil},
{toParse: "true", want: true},
{toParse: `"a"`, want: "a"},
{toParse: "5", want: float64(5)},
{toParse: `{}`, want: map[string]interface{}{}},
{toParse: `[]`, want: []interface{}(nil)},
{toParse: `{"a": "b"}`, want: map[string]interface{}{"a": "b"}},
{toParse: `[5]`, want: []interface{}{float64(5)}},
{toParse: `{"a":5 , "b" : "string"}`, want: map[string]interface{}{"a": float64(5), "b": "string"}},
{toParse: `["a", 5 , null, true]`, want: []interface{}{"a", float64(5), nil, true}},
{toParse: `{"a" "b"}`, wantError: true},
{toParse: `{"a": "b",}`, wantError: true},
{toParse: `{"a":"b","c" "b"}`, wantError: true},
{toParse: `{"a": "b","c":"d",}`, wantError: true},
{toParse: `{,}`, wantError: true},
{toParse: `[1, 2,]`, wantError: true},
{toParse: `[1 2]`, wantError: true},
{toParse: `[,]`, wantError: true},
} {
l := Lexer{Data: []byte(test.toParse)}
got := l.Interface()
if !reflect.DeepEqual(got, test.want) {
t.Errorf("[%d, %q] Interface() = %v; want %v", i, test.toParse, got, test.want)
}
err := l.Error()
if err != nil && !test.wantError {
t.Errorf("[%d, %q] Interface() error: %v", i, test.toParse, err)
} else if err == nil && test.wantError {
t.Errorf("[%d, %q] Interface() ok; want error", i, test.toParse)
}
}
}

273
vendor/github.com/mailru/easyjson/jwriter/writer.go generated vendored Normal file
View File

@@ -0,0 +1,273 @@
// Package jwriter contains a JSON writer.
package jwriter
import (
"io"
"strconv"
"unicode/utf8"
"github.com/mailru/easyjson/buffer"
)
// Writer is a JSON writer.
type Writer struct {
Error error
Buffer buffer.Buffer
}
// Size returns the size of the data that was written out.
func (w *Writer) Size() int {
return w.Buffer.Size()
}
// DumpTo outputs the data to given io.Writer, resetting the buffer.
func (w *Writer) DumpTo(out io.Writer) (written int, err error) {
return w.Buffer.DumpTo(out)
}
// BuildBytes returns writer data as a single byte slice.
func (w *Writer) BuildBytes() ([]byte, error) {
if w.Error != nil {
return nil, w.Error
}
return w.Buffer.BuildBytes(), nil
}
// RawByte appends raw binary data to the buffer.
func (w *Writer) RawByte(c byte) {
w.Buffer.AppendByte(c)
}
// RawByte appends raw binary data to the buffer.
func (w *Writer) RawString(s string) {
w.Buffer.AppendString(s)
}
// RawByte appends raw binary data to the buffer or sets the error if it is given. Useful for
// calling with results of MarshalJSON-like functions.
func (w *Writer) Raw(data []byte, err error) {
switch {
case w.Error != nil:
return
case err != nil:
w.Error = err
case len(data) > 0:
w.Buffer.AppendBytes(data)
default:
w.RawString("null")
}
}
func (w *Writer) Uint8(n uint8) {
w.Buffer.EnsureSpace(3)
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
}
func (w *Writer) Uint16(n uint16) {
w.Buffer.EnsureSpace(5)
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
}
func (w *Writer) Uint32(n uint32) {
w.Buffer.EnsureSpace(10)
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
}
func (w *Writer) Uint(n uint) {
w.Buffer.EnsureSpace(20)
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
}
func (w *Writer) Uint64(n uint64) {
w.Buffer.EnsureSpace(20)
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, n, 10)
}
func (w *Writer) Int8(n int8) {
w.Buffer.EnsureSpace(4)
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
}
func (w *Writer) Int16(n int16) {
w.Buffer.EnsureSpace(6)
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
}
func (w *Writer) Int32(n int32) {
w.Buffer.EnsureSpace(11)
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
}
func (w *Writer) Int(n int) {
w.Buffer.EnsureSpace(21)
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
}
func (w *Writer) Int64(n int64) {
w.Buffer.EnsureSpace(21)
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, n, 10)
}
func (w *Writer) Uint8Str(n uint8) {
w.Buffer.EnsureSpace(3)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}
func (w *Writer) Uint16Str(n uint16) {
w.Buffer.EnsureSpace(5)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}
func (w *Writer) Uint32Str(n uint32) {
w.Buffer.EnsureSpace(10)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}
func (w *Writer) UintStr(n uint) {
w.Buffer.EnsureSpace(20)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}
func (w *Writer) Uint64Str(n uint64) {
w.Buffer.EnsureSpace(20)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, n, 10)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}
func (w *Writer) Int8Str(n int8) {
w.Buffer.EnsureSpace(4)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}
func (w *Writer) Int16Str(n int16) {
w.Buffer.EnsureSpace(6)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}
func (w *Writer) Int32Str(n int32) {
w.Buffer.EnsureSpace(11)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}
func (w *Writer) IntStr(n int) {
w.Buffer.EnsureSpace(21)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}
func (w *Writer) Int64Str(n int64) {
w.Buffer.EnsureSpace(21)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, n, 10)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}
func (w *Writer) Float32(n float32) {
w.Buffer.EnsureSpace(20)
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 32)
}
func (w *Writer) Float64(n float64) {
w.Buffer.EnsureSpace(20)
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, n, 'g', -1, 64)
}
func (w *Writer) Bool(v bool) {
w.Buffer.EnsureSpace(5)
if v {
w.Buffer.Buf = append(w.Buffer.Buf, "true"...)
} else {
w.Buffer.Buf = append(w.Buffer.Buf, "false"...)
}
}
const chars = "0123456789abcdef"
func (w *Writer) String(s string) {
w.Buffer.AppendByte('"')
// Portions of the string that contain no escapes are appended as
// byte slices.
p := 0 // last non-escape symbol
for i := 0; i < len(s); {
// single-with character
if c := s[i]; c < utf8.RuneSelf {
var escape byte
switch c {
case '\t':
escape = 't'
case '\r':
escape = 'r'
case '\n':
escape = 'n'
case '\\':
escape = '\\'
case '"':
escape = '"'
case '<', '>':
// do nothing
default:
if c >= 0x20 {
// no escaping is required
i++
continue
}
}
if escape != 0 {
w.Buffer.AppendString(s[p:i])
w.Buffer.AppendByte('\\')
w.Buffer.AppendByte(escape)
} else {
w.Buffer.AppendString(s[p:i])
w.Buffer.AppendString(`\u00`)
w.Buffer.AppendByte(chars[c>>4])
w.Buffer.AppendByte(chars[c&0xf])
}
i++
p = i
continue
}
// broken utf
runeValue, runeWidth := utf8.DecodeRuneInString(s[i:])
if runeValue == utf8.RuneError && runeWidth == 1 {
w.Buffer.AppendString(s[p:i])
w.Buffer.AppendString(`\ufffd`)
i++
p = i
continue
}
// jsonp stuff - tab separator and line separator
if runeValue == '\u2028' || runeValue == '\u2029' {
w.Buffer.AppendString(s[p:i])
w.Buffer.AppendString(`\u202`)
w.Buffer.AppendByte(chars[runeValue&0xf])
i += runeWidth
p = i
continue
}
i += runeWidth
}
w.Buffer.AppendString(s[p:])
w.Buffer.AppendByte('"')
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Bool struct {
V bool
Defined bool
}
// Creates an optional type with a given value.
func OBool(v bool) Bool {
return Bool{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Bool) Get(deflt bool) bool {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Bool) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Bool(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Bool) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Bool{}
} else {
v.V = l.Bool()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Bool) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Bool) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Bool) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Bool) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Float32 struct {
V float32
Defined bool
}
// Creates an optional type with a given value.
func OFloat32(v float32) Float32 {
return Float32{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Float32) Get(deflt float32) float32 {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Float32) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Float32(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Float32) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Float32{}
} else {
v.V = l.Float32()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Float32) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Float32) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Float32) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Float32) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Float64 struct {
V float64
Defined bool
}
// Creates an optional type with a given value.
func OFloat64(v float64) Float64 {
return Float64{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Float64) Get(deflt float64) float64 {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Float64) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Float64(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Float64) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Float64{}
} else {
v.V = l.Float64()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Float64) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Float64) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Float64) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Float64) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Int struct {
V int
Defined bool
}
// Creates an optional type with a given value.
func OInt(v int) Int {
return Int{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Int) Get(deflt int) int {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Int) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Int(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Int) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Int{}
} else {
v.V = l.Int()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Int) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Int) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Int) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Int) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Int16 struct {
V int16
Defined bool
}
// Creates an optional type with a given value.
func OInt16(v int16) Int16 {
return Int16{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Int16) Get(deflt int16) int16 {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Int16) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Int16(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Int16) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Int16{}
} else {
v.V = l.Int16()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Int16) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Int16) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Int16) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Int16) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Int32 struct {
V int32
Defined bool
}
// Creates an optional type with a given value.
func OInt32(v int32) Int32 {
return Int32{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Int32) Get(deflt int32) int32 {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Int32) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Int32(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Int32) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Int32{}
} else {
v.V = l.Int32()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Int32) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Int32) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Int32) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Int32) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Int64 struct {
V int64
Defined bool
}
// Creates an optional type with a given value.
func OInt64(v int64) Int64 {
return Int64{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Int64) Get(deflt int64) int64 {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Int64) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Int64(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Int64) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Int64{}
} else {
v.V = l.Int64()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Int64) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Int64) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Int64) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Int64) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Int8 struct {
V int8
Defined bool
}
// Creates an optional type with a given value.
func OInt8(v int8) Int8 {
return Int8{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Int8) Get(deflt int8) int8 {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Int8) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Int8(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Int8) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Int8{}
} else {
v.V = l.Int8()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Int8) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Int8) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Int8) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Int8) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type String struct {
V string
Defined bool
}
// Creates an optional type with a given value.
func OString(v string) String {
return String{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v String) Get(deflt string) string {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v String) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.String(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *String) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = String{}
} else {
v.V = l.String()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *String) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *String) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v String) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v String) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Uint struct {
V uint
Defined bool
}
// Creates an optional type with a given value.
func OUint(v uint) Uint {
return Uint{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Uint) Get(deflt uint) uint {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Uint) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Uint(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Uint) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Uint{}
} else {
v.V = l.Uint()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Uint) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Uint) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Uint) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Uint) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Uint16 struct {
V uint16
Defined bool
}
// Creates an optional type with a given value.
func OUint16(v uint16) Uint16 {
return Uint16{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Uint16) Get(deflt uint16) uint16 {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Uint16) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Uint16(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Uint16) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Uint16{}
} else {
v.V = l.Uint16()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Uint16) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Uint16) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Uint16) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Uint16) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Uint32 struct {
V uint32
Defined bool
}
// Creates an optional type with a given value.
func OUint32(v uint32) Uint32 {
return Uint32{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Uint32) Get(deflt uint32) uint32 {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Uint32) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Uint32(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Uint32) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Uint32{}
} else {
v.V = l.Uint32()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Uint32) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Uint32) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Uint32) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Uint32) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Uint64 struct {
V uint64
Defined bool
}
// Creates an optional type with a given value.
func OUint64(v uint64) Uint64 {
return Uint64{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Uint64) Get(deflt uint64) uint64 {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Uint64) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Uint64(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Uint64) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Uint64{}
} else {
v.V = l.Uint64()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Uint64) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Uint64) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Uint64) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Uint64) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

View File

@@ -0,0 +1,79 @@
// generated by gotemplate
package opt
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Uint8 struct {
V uint8
Defined bool
}
// Creates an optional type with a given value.
func OUint8(v uint8) Uint8 {
return Uint8{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Uint8) Get(deflt uint8) uint8 {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Uint8) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Uint8(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Uint8) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Uint8{}
} else {
v.V = l.Uint8()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Uint8) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Uint8) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Uint8) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Uint8) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

80
vendor/github.com/mailru/easyjson/opt/optional/opt.go generated vendored Normal file
View File

@@ -0,0 +1,80 @@
// +build none
package optional
import (
"fmt"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// template type Optional(A)
type A int
// A 'gotemplate'-based type for providing optional semantics without using pointers.
type Optional struct {
V A
Defined bool
}
// Creates an optional type with a given value.
func OOptional(v A) Optional {
return Optional{V: v, Defined: true}
}
// Get returns the value or given default in the case the value is undefined.
func (v Optional) Get(deflt A) A {
if !v.Defined {
return deflt
}
return v.V
}
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v Optional) MarshalEasyJSON(w *jwriter.Writer) {
if v.Defined {
w.Optional(v.V)
} else {
w.RawString("null")
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *Optional) UnmarshalEasyJSON(l *jlexer.Lexer) {
if l.IsNull() {
l.Skip()
*v = Optional{}
} else {
v.V = l.Optional()
v.Defined = true
}
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Optional) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalJSON implements a standard json marshaler interface.
func (v *Optional) UnmarshalJSON(data []byte) error {
l := jlexer.Lexer{}
v.UnmarshalEasyJSON(&l)
return l.Error()
}
// IsDefined returns whether the value is defined, a function is required so that it can
// be used in an interface.
func (v Optional) IsDefined() bool {
return v.Defined
}
// String implements a stringer interface using fmt.Sprint for the value.
func (v Optional) String() string {
if !v.Defined {
return "<undefined>"
}
return fmt.Sprint(v.V)
}

22
vendor/github.com/mailru/easyjson/opt/opts.go generated vendored Normal file
View File

@@ -0,0 +1,22 @@
package opt
//go:generate sed -i "s/\\+build none/generated by gotemplate/" optional/opt.go
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" Int(int)
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" Uint(uint)
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" Int8(int8)
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" Int16(int16)
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" Int32(int32)
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" Int64(int64)
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" Uint8(uint8)
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" Uint16(uint16)
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" Uint32(uint32)
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" Uint64(uint64)
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" Float32(float32)
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" Float64(float64)
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" Bool(bool)
//go:generate gotemplate "github.com/mailru/easyjson/opt/optional" String(string)
//go:generate sed -i "s/generated by gotemplate/+build none/" optional/opt.go

78
vendor/github.com/mailru/easyjson/parser/parser.go generated vendored Normal file
View File

@@ -0,0 +1,78 @@
package parser
import (
"go/ast"
"go/parser"
"go/token"
"strings"
)
const structComment = "easyjson:json"
type Parser struct {
PkgPath string
PkgName string
StructNames []string
AllStructs bool
}
type visitor struct {
*Parser
name string
explicit bool
}
func (p *Parser) needType(comments string) bool {
for _, v := range strings.Split(comments, "\n") {
if strings.HasPrefix(v, structComment) {
return true
}
}
return false
}
func (v *visitor) Visit(n ast.Node) (w ast.Visitor) {
switch n := n.(type) {
case *ast.File:
v.PkgName = n.Name.String()
return v
case *ast.GenDecl:
v.explicit = v.needType(n.Doc.Text())
if !v.explicit && !v.AllStructs {
return nil
}
return v
case *ast.TypeSpec:
v.name = n.Name.String()
// Allow to specify non-structs explicitly independent of '-all' flag.
if v.explicit {
v.StructNames = append(v.StructNames, v.name)
return nil
}
return v
case *ast.StructType:
v.StructNames = append(v.StructNames, v.name)
return nil
}
return nil
}
func (p *Parser) Parse(fname string) error {
var err error
if p.PkgPath, err = getPkgPath(fname); err != nil {
return err
}
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments)
if err != nil {
return err
}
ast.Walk(&visitor{Parser: p}, f)
return nil
}

View File

@@ -0,0 +1,29 @@
// +build !windows
package parser
import (
"fmt"
"os"
"path"
"strings"
)
func getPkgPath(fname string) (string, error) {
if !path.IsAbs(fname) {
pwd, err := os.Getwd()
if err != nil {
return "", err
}
fname = path.Join(pwd, fname)
}
for _, p := range strings.Split(os.Getenv("GOPATH"), ":") {
prefix := path.Join(p, "src") + "/"
if rel := strings.TrimPrefix(fname, prefix); rel != fname {
return path.Dir(rel), nil
}
}
return "", fmt.Errorf("file '%v' is not in GOPATH", fname)
}

View File

@@ -0,0 +1,33 @@
package parser
import (
"fmt"
"os"
"path"
"strings"
)
func normalizePath(path string) string {
return strings.Replace(path, "\\", "/", -1)
}
func getPkgPath(fname string) (string, error) {
if !path.IsAbs(fname) {
pwd, err := os.Getwd()
if err != nil {
return "", err
}
fname = path.Join(pwd, fname)
}
fname = normalizePath(fname)
for _, p := range strings.Split(os.Getenv("GOPATH"), ";") {
prefix := path.Join(normalizePath(p), "src") + "/"
if rel := strings.TrimPrefix(fname, prefix); rel != fname {
return path.Dir(rel), nil
}
}
return "", fmt.Errorf("file '%v' is not in GOPATH", fname)
}

45
vendor/github.com/mailru/easyjson/raw.go generated vendored Normal file
View File

@@ -0,0 +1,45 @@
package easyjson
import (
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
// RawMessage is a raw piece of JSON (number, string, bool, object, array or null) that is extracted
// without parsing and output as is during marshalling.
type RawMessage []byte
// MarshalEasyJSON does JSON marshaling using easyjson interface.
func (v *RawMessage) MarshalEasyJSON(w *jwriter.Writer) {
if len(*v) == 0 {
w.RawString("null")
} else {
w.Raw(*v, nil)
}
}
// UnmarshalEasyJSON does JSON unmarshaling using easyjson interface.
func (v *RawMessage) UnmarshalEasyJSON(l *jlexer.Lexer) {
*v = RawMessage(l.Raw())
}
// UnmarshalJSON implements encoding/json.Unmarshaler interface.
func (v *RawMessage) UnmarshalJSON(data []byte) error {
*v = data
return nil
}
var nullBytes = []byte("null")
// MarshalJSON implements encoding/json.Marshaler interface.
func (v RawMessage) MarshalJSON() ([]byte, error) {
if len(v) == 0 {
return nullBytes, nil
}
return v, nil
}
// IsDefined is required for integration with omitempty easyjson logic.
func (v *RawMessage) IsDefined() bool {
return len(*v) > 0
}

133
vendor/github.com/mailru/easyjson/tests/basic_test.go generated vendored Normal file
View File

@@ -0,0 +1,133 @@
package tests
import (
"reflect"
"testing"
"encoding/json"
"github.com/mailru/easyjson"
"github.com/mailru/easyjson/jwriter"
)
type testType interface {
json.Marshaler
json.Unmarshaler
}
var testCases = []struct {
Decoded testType
Encoded string
}{
{&primitiveTypesValue, primitiveTypesString},
{&namedPrimitiveTypesValue, namedPrimitiveTypesString},
{&structsValue, structsString},
{&omitEmptyValue, omitEmptyString},
{&snakeStructValue, snakeStructString},
{&omitEmptyDefaultValue, omitEmptyDefaultString},
{&optsValue, optsString},
{&rawValue, rawString},
{&stdMarshalerValue, stdMarshalerString},
{&unexportedStructValue, unexportedStructString},
{&excludedFieldValue, excludedFieldString},
{&mapsValue, mapsString},
{&deepNestValue, deepNestString},
{&IntsValue, IntsString},
}
func TestMarshal(t *testing.T) {
for i, test := range testCases {
data, err := test.Decoded.MarshalJSON()
if err != nil {
t.Errorf("[%d, %T] MarshalJSON() error: %v", i, test.Decoded, err)
}
got := string(data)
if got != test.Encoded {
t.Errorf("[%d, %T] MarshalJSON(): got \n%v\n\t\t want \n%v", i, test.Decoded, got, test.Encoded)
}
}
}
func TestUnmarshal(t *testing.T) {
for i, test := range testCases {
v1 := reflect.New(reflect.TypeOf(test.Decoded).Elem()).Interface()
v := v1.(testType)
err := v.UnmarshalJSON([]byte(test.Encoded))
if err != nil {
t.Errorf("[%d, %T] UnmarshalJSON() error: %v", i, test.Decoded, err)
}
if !reflect.DeepEqual(v, test.Decoded) {
t.Errorf("[%d, %T] UnmarshalJSON(): got \n%+v\n\t\t want \n%+v", i, test.Decoded, v, test.Decoded)
}
}
}
func TestRawMessageSTD(t *testing.T) {
type T struct {
F easyjson.RawMessage
Fnil easyjson.RawMessage
}
val := T{F: easyjson.RawMessage([]byte(`"test"`))}
str := `{"F":"test","Fnil":null}`
data, err := json.Marshal(val)
if err != nil {
t.Errorf("json.Marshal() error: %v", err)
}
got := string(data)
if got != str {
t.Errorf("json.Marshal() = %v; want %v", got, str)
}
wantV := T{F: easyjson.RawMessage([]byte(`"test"`)), Fnil: easyjson.RawMessage([]byte("null"))}
var gotV T
err = json.Unmarshal([]byte(str), &gotV)
if err != nil {
t.Errorf("json.Unmarshal() error: %v", err)
}
if !reflect.DeepEqual(gotV, wantV) {
t.Errorf("json.Unmarshal() = %v; want %v", gotV, wantV)
}
}
func TestParseNull(t *testing.T) {
var got, want SubStruct
if err := easyjson.Unmarshal([]byte("null"), &got); err != nil {
t.Errorf("Unmarshal() error: %v", err)
}
if !reflect.DeepEqual(got, want) {
t.Errorf("Unmarshal() = %+v; want %+v", got, want)
}
}
var testSpecialCases = []struct {
EncodedString string
Value string
}{
{`"Username \u003cuser@example.com\u003e"`, `Username <user@example.com>`},
{`"Username\ufffd"`, "Username\xc5"},
{`естzтест"`, естzтест"},
{`"тест\ufffdтест"`, "тест\xc5тест"},
{`"绿茶"`, "绿茶"},
{`"绿\ufffd茶"`, "绿\xc5茶"},
{`"тест\u2028"`, "тест\xE2\x80\xA8"},
{`"\\\r\n\t\""`, "\\\r\n\t\""},
{`"ü"`, "ü"},
}
func TestSpecialCases(t *testing.T) {
for i, test := range testSpecialCases {
w := jwriter.Writer{}
w.String(test.Value)
got := string(w.Buffer.BuildBytes())
if got != test.EncodedString {
t.Errorf("[%d] Encoded() = %+v; want %+v", i, got, test.EncodedString)
}
}
}

545
vendor/github.com/mailru/easyjson/tests/data.go generated vendored Normal file
View File

@@ -0,0 +1,545 @@
package tests
import (
"fmt"
"math"
"time"
"github.com/mailru/easyjson"
"github.com/mailru/easyjson/opt"
)
type PrimitiveTypes struct {
String string
Bool bool
Int int
Int8 int8
Int16 int16
Int32 int32
Int64 int64
Uint uint
Uint8 uint8
Uint16 uint16
Uint32 uint32
Uint64 uint64
IntString int `json:",string"`
Int8String int8 `json:",string"`
Int16String int16 `json:",string"`
Int32String int32 `json:",string"`
Int64String int64 `json:",string"`
UintString uint `json:",string"`
Uint8String uint8 `json:",string"`
Uint16String uint16 `json:",string"`
Uint32String uint32 `json:",string"`
Uint64String uint64 `json:",string"`
Float32 float32
Float64 float64
Ptr *string
PtrNil *string
}
var str = "bla"
var primitiveTypesValue = PrimitiveTypes{
String: "test", Bool: true,
Int: math.MinInt32,
Int8: math.MinInt8,
Int16: math.MinInt16,
Int32: math.MinInt32,
Int64: math.MinInt64,
Uint: math.MaxUint32,
Uint8: math.MaxUint8,
Uint16: math.MaxUint16,
Uint32: math.MaxUint32,
Uint64: math.MaxUint64,
IntString: math.MinInt32,
Int8String: math.MinInt8,
Int16String: math.MinInt16,
Int32String: math.MinInt32,
Int64String: math.MinInt64,
UintString: math.MaxUint32,
Uint8String: math.MaxUint8,
Uint16String: math.MaxUint16,
Uint32String: math.MaxUint32,
Uint64String: math.MaxUint64,
Float32: 1.5,
Float64: math.MaxFloat64,
Ptr: &str,
}
var primitiveTypesString = "{" +
`"String":"test","Bool":true,` +
`"Int":` + fmt.Sprint(math.MinInt32) + `,` +
`"Int8":` + fmt.Sprint(math.MinInt8) + `,` +
`"Int16":` + fmt.Sprint(math.MinInt16) + `,` +
`"Int32":` + fmt.Sprint(math.MinInt32) + `,` +
`"Int64":` + fmt.Sprint(int64(math.MinInt64)) + `,` +
`"Uint":` + fmt.Sprint(math.MaxUint32) + `,` +
`"Uint8":` + fmt.Sprint(math.MaxUint8) + `,` +
`"Uint16":` + fmt.Sprint(math.MaxUint16) + `,` +
`"Uint32":` + fmt.Sprint(math.MaxUint32) + `,` +
`"Uint64":` + fmt.Sprint(uint64(math.MaxUint64)) + `,` +
`"IntString":"` + fmt.Sprint(math.MinInt32) + `",` +
`"Int8String":"` + fmt.Sprint(math.MinInt8) + `",` +
`"Int16String":"` + fmt.Sprint(math.MinInt16) + `",` +
`"Int32String":"` + fmt.Sprint(math.MinInt32) + `",` +
`"Int64String":"` + fmt.Sprint(int64(math.MinInt64)) + `",` +
`"UintString":"` + fmt.Sprint(math.MaxUint32) + `",` +
`"Uint8String":"` + fmt.Sprint(math.MaxUint8) + `",` +
`"Uint16String":"` + fmt.Sprint(math.MaxUint16) + `",` +
`"Uint32String":"` + fmt.Sprint(math.MaxUint32) + `",` +
`"Uint64String":"` + fmt.Sprint(uint64(math.MaxUint64)) + `",` +
`"Float32":` + fmt.Sprint(1.5) + `,` +
`"Float64":` + fmt.Sprint(math.MaxFloat64) + `,` +
`"Ptr":"bla",` +
`"PtrNil":null` +
"}"
type (
NamedString string
NamedBool bool
NamedInt int
NamedInt8 int8
NamedInt16 int16
NamedInt32 int32
NamedInt64 int64
NamedUint uint
NamedUint8 uint8
NamedUint16 uint16
NamedUint32 uint32
NamedUint64 uint64
NamedFloat32 float32
NamedFloat64 float64
NamedStrPtr *string
)
type NamedPrimitiveTypes struct {
String NamedString
Bool NamedBool
Int NamedInt
Int8 NamedInt8
Int16 NamedInt16
Int32 NamedInt32
Int64 NamedInt64
Uint NamedUint
Uint8 NamedUint8
Uint16 NamedUint16
Uint32 NamedUint32
Uint64 NamedUint64
Float32 NamedFloat32
Float64 NamedFloat64
Ptr NamedStrPtr
PtrNil NamedStrPtr
}
var namedPrimitiveTypesValue = NamedPrimitiveTypes{
String: "test",
Bool: true,
Int: math.MinInt32,
Int8: math.MinInt8,
Int16: math.MinInt16,
Int32: math.MinInt32,
Int64: math.MinInt64,
Uint: math.MaxUint32,
Uint8: math.MaxUint8,
Uint16: math.MaxUint16,
Uint32: math.MaxUint32,
Uint64: math.MaxUint64,
Float32: 1.5,
Float64: math.MaxFloat64,
Ptr: NamedStrPtr(&str),
}
var namedPrimitiveTypesString = "{" +
`"String":"test",` +
`"Bool":true,` +
`"Int":` + fmt.Sprint(math.MinInt32) + `,` +
`"Int8":` + fmt.Sprint(math.MinInt8) + `,` +
`"Int16":` + fmt.Sprint(math.MinInt16) + `,` +
`"Int32":` + fmt.Sprint(math.MinInt32) + `,` +
`"Int64":` + fmt.Sprint(int64(math.MinInt64)) + `,` +
`"Uint":` + fmt.Sprint(math.MaxUint32) + `,` +
`"Uint8":` + fmt.Sprint(math.MaxUint8) + `,` +
`"Uint16":` + fmt.Sprint(math.MaxUint16) + `,` +
`"Uint32":` + fmt.Sprint(math.MaxUint32) + `,` +
`"Uint64":` + fmt.Sprint(uint64(math.MaxUint64)) + `,` +
`"Float32":` + fmt.Sprint(1.5) + `,` +
`"Float64":` + fmt.Sprint(math.MaxFloat64) + `,` +
`"Ptr":"bla",` +
`"PtrNil":null` +
"}"
type SubStruct struct {
Value string
Value2 string
unexpored bool
}
type SubP struct {
V string
}
type SubStructAlias SubStruct
type Structs struct {
SubStruct
*SubP
Value2 int
Sub1 SubStruct `json:"substruct"`
Sub2 *SubStruct
SubNil *SubStruct
SubSlice []SubStruct
SubSliceNil []SubStruct
SubPtrSlice []*SubStruct
SubPtrSliceNil []*SubStruct
SubA1 SubStructAlias
SubA2 *SubStructAlias
Anonymous struct {
V string
I int
}
Anonymous1 *struct {
V string
}
AnonymousSlice []struct{ V int }
AnonymousPtrSlice []*struct{ V int }
Slice []string
unexported bool
}
var structsValue = Structs{
SubStruct: SubStruct{Value: "test"},
SubP: &SubP{V: "subp"},
Value2: 5,
Sub1: SubStruct{Value: "test1", Value2: "v"},
Sub2: &SubStruct{Value: "test2", Value2: "v2"},
SubSlice: []SubStruct{
{Value: "s1"},
{Value: "s2"},
},
SubPtrSlice: []*SubStruct{
{Value: "p1"},
{Value: "p2"},
},
SubA1: SubStructAlias{Value: "test3", Value2: "v3"},
SubA2: &SubStructAlias{Value: "test4", Value2: "v4"},
Anonymous: struct {
V string
I int
}{V: "bla", I: 5},
Anonymous1: &struct {
V string
}{V: "bla1"},
AnonymousSlice: []struct{ V int }{{1}, {2}},
AnonymousPtrSlice: []*struct{ V int }{{3}, {4}},
Slice: []string{"test5", "test6"},
}
var structsString = "{" +
`"Value2":5,` +
`"substruct":{"Value":"test1","Value2":"v"},` +
`"Sub2":{"Value":"test2","Value2":"v2"},` +
`"SubNil":null,` +
`"SubSlice":[{"Value":"s1","Value2":""},{"Value":"s2","Value2":""}],` +
`"SubSliceNil":[],` +
`"SubPtrSlice":[{"Value":"p1","Value2":""},{"Value":"p2","Value2":""}],` +
`"SubPtrSliceNil":[],` +
`"SubA1":{"Value":"test3","Value2":"v3"},` +
`"SubA2":{"Value":"test4","Value2":"v4"},` +
`"Anonymous":{"V":"bla","I":5},` +
`"Anonymous1":{"V":"bla1"},` +
`"AnonymousSlice":[{"V":1},{"V":2}],` +
`"AnonymousPtrSlice":[{"V":3},{"V":4}],` +
`"Slice":["test5","test6"],` +
// Embedded fields go last.
`"V":"subp",` +
`"Value":"test"` +
"}"
type OmitEmpty struct {
// NOTE: first field is empty to test comma printing.
StrE, StrNE string `json:",omitempty"`
PtrE, PtrNE *string `json:",omitempty"`
IntNE int `json:"intField,omitempty"`
IntE int `json:",omitempty"`
// NOTE: omitempty has no effect on non-pointer struct fields.
SubE, SubNE SubStruct `json:",omitempty"`
SubPE, SubPNE *SubStruct `json:",omitempty"`
}
var omitEmptyValue = OmitEmpty{
StrNE: "str",
PtrNE: &str,
IntNE: 6,
SubNE: SubStruct{Value: "1", Value2: "2"},
SubPNE: &SubStruct{Value: "3", Value2: "4"},
}
var omitEmptyString = "{" +
`"StrNE":"str",` +
`"PtrNE":"bla",` +
`"intField":6,` +
`"SubE":{"Value":"","Value2":""},` +
`"SubNE":{"Value":"1","Value2":"2"},` +
`"SubPNE":{"Value":"3","Value2":"4"}` +
"}"
type Opts struct {
StrNull opt.String
StrEmpty opt.String
Str opt.String
StrOmitempty opt.String `json:",omitempty"`
IntNull opt.Int
IntZero opt.Int
Int opt.Int
}
var optsValue = Opts{
StrEmpty: opt.OString(""),
Str: opt.OString("test"),
IntZero: opt.OInt(0),
Int: opt.OInt(5),
}
var optsString = `{` +
`"StrNull":null,` +
`"StrEmpty":"",` +
`"Str":"test",` +
`"IntNull":null,` +
`"IntZero":0,` +
`"Int":5` +
`}`
type Raw struct {
Field easyjson.RawMessage
Field2 string
}
var rawValue = Raw{
Field: []byte(`{"a" : "b"}`),
Field2: "test",
}
var rawString = `{` +
`"Field":{"a" : "b"},` +
`"Field2":"test"` +
`}`
type StdMarshaler struct {
T time.Time
}
var stdMarshalerValue = StdMarshaler{T: time.Date(2016, 01, 02, 14, 15, 10, 0, time.UTC)}
var stdMarshalerString = `{"T":"2016-01-02T14:15:10Z"}`
type unexportedStruct struct {
Value string
}
var unexportedStructValue = unexportedStruct{"test"}
var unexportedStructString = `{"Value":"test"}`
type ExcludedField struct {
Process bool `json:"process"`
DoNotProcess bool `json:"-"`
DoNotProcess1 bool `json:"-"`
}
var excludedFieldValue = ExcludedField{
Process: true,
DoNotProcess: false,
DoNotProcess1: false,
}
var excludedFieldString = `{"process":true}`
type Str string
type Maps struct {
Map map[string]string
InterfaceMap map[string]interface{}
NilMap map[string]string
CustomMap map[Str]Str
}
var mapsValue = Maps{
Map: map[string]string{"A": "b"}, // only one item since map iteration is randomized
InterfaceMap: map[string]interface{}{"G": float64(1)},
CustomMap: map[Str]Str{"c": "d"},
}
var mapsString = `{` +
`"Map":{"A":"b"},` +
`"InterfaceMap":{"G":1},` +
`"NilMap":null,` +
`"CustomMap":{"c":"d"}` +
`}`
type NamedSlice []Str
type NamedMap map[Str]Str
type DeepNest struct {
SliceMap map[Str][]Str
SliceMap1 map[Str][]Str
NamedSliceMap map[Str]NamedSlice
NamedMapMap map[Str]NamedMap
MapSlice []map[Str]Str
NamedSliceSlice []NamedSlice
NamedMapSlice []NamedMap
NamedStringSlice []NamedString
}
var deepNestValue = DeepNest{
SliceMap: map[Str][]Str{
"testSliceMap": []Str{
"0",
"1",
},
},
SliceMap1: map[Str][]Str{
"testSliceMap1": nil,
},
NamedSliceMap: map[Str]NamedSlice{
"testNamedSliceMap": NamedSlice{
"2",
"3",
},
},
NamedMapMap: map[Str]NamedMap{
"testNamedMapMap": NamedMap{
"key1": "value1",
},
},
MapSlice: []map[Str]Str{
map[Str]Str{
"testMapSlice": "someValue",
},
},
NamedSliceSlice: []NamedSlice{
NamedSlice{
"someValue1",
"someValue2",
},
NamedSlice{
"someValue3",
"someValue4",
},
},
NamedMapSlice: []NamedMap{
NamedMap{
"key2": "value2",
},
NamedMap{
"key3": "value3",
},
},
NamedStringSlice: []NamedString{
"value4", "value5",
},
}
var deepNestString = `{` +
`"SliceMap":{` +
`"testSliceMap":["0","1"]` +
`},` +
`"SliceMap1":{` +
`"testSliceMap1":[]` +
`},` +
`"NamedSliceMap":{` +
`"testNamedSliceMap":["2","3"]` +
`},` +
`"NamedMapMap":{` +
`"testNamedMapMap":{"key1":"value1"}` +
`},` +
`"MapSlice":[` +
`{"testMapSlice":"someValue"}` +
`],` +
`"NamedSliceSlice":[` +
`["someValue1","someValue2"],` +
`["someValue3","someValue4"]` +
`],` +
`"NamedMapSlice":[` +
`{"key2":"value2"},` +
`{"key3":"value3"}` +
`],` +
`"NamedStringSlice":["value4","value5"]` +
`}`
//easyjson:json
type Ints []int
var IntsValue = Ints{1, 2, 3, 4, 5}
var IntsString = `[1,2,3,4,5]`
type RequiredOptionalStruct struct {
FirstName string `json:"first_name,required"`
Lastname string `json:"last_name"`
}

3
vendor/github.com/mailru/easyjson/tests/nothing.go generated vendored Normal file
View File

@@ -0,0 +1,3 @@
package tests
// No structs in this file

12
vendor/github.com/mailru/easyjson/tests/omitempty.go generated vendored Normal file
View File

@@ -0,0 +1,12 @@
package tests
//easyjson:json
type OmitEmptyDefault struct {
Field string
Str string
Str1 string `json:"s,!omitempty"`
Str2 string `json:",!omitempty"`
}
var omitEmptyDefaultValue = OmitEmptyDefault{Field: "test"}
var omitEmptyDefaultString = `{"Field":"test","s":"","Str2":""}`

View File

@@ -0,0 +1,28 @@
package tests
import (
"testing"
"fmt"
)
func TestRequiredField(t *testing.T) {
cases := []struct{ json, errorMessage string }{
{`{"first_name":"Foo", "last_name": "Bar"}`, ""},
{`{"last_name":"Bar"}`, "key 'first_name' is required"},
{"{}", "key 'first_name' is required"},
}
for _, tc := range cases {
var v RequiredOptionalStruct
err := v.UnmarshalJSON([]byte(tc.json))
if tc.errorMessage == "" {
if err != nil {
t.Errorf("%s. UnmarshallJSON didn`t expect error: %v", tc.json, err)
}
} else {
if fmt.Sprintf("%v", err) != tc.errorMessage {
t.Errorf("%s. UnmarshallJSON expected error: %v. got: %v", tc.json, tc.errorMessage, err)
}
}
}
}

10
vendor/github.com/mailru/easyjson/tests/snake.go generated vendored Normal file
View File

@@ -0,0 +1,10 @@
package tests
//easyjson:json
type SnakeStruct struct {
WeirdHTTPStuff bool
CustomNamedField string `json:"cUsToM"`
}
var snakeStructValue SnakeStruct
var snakeStructString = `{"weird_http_stuff":false,"cUsToM":""}`