initial commit
This commit is contained in:
27
vendor/gopkg.in/square/go-jose.v2/json/LICENSE
generated
vendored
Normal file
27
vendor/gopkg.in/square/go-jose.v2/json/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
13
vendor/gopkg.in/square/go-jose.v2/json/README.md
generated
vendored
Normal file
13
vendor/gopkg.in/square/go-jose.v2/json/README.md
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Safe JSON
|
||||
|
||||
This repository contains a fork of the `encoding/json` package from Go 1.6.
|
||||
|
||||
The following changes were made:
|
||||
|
||||
* Object deserialization uses case-sensitive member name matching instead of
|
||||
[case-insensitive matching](https://www.ietf.org/mail-archive/web/json/current/msg03763.html).
|
||||
This is to avoid differences in the interpretation of JOSE messages between
|
||||
go-jose and libraries written in other languages.
|
||||
* When deserializing a JSON object, we check for duplicate keys and reject the
|
||||
input whenever we detect a duplicate. Rather than trying to work with malformed
|
||||
data, we prefer to reject it right away.
|
||||
223
vendor/gopkg.in/square/go-jose.v2/json/bench_test.go
generated
vendored
Normal file
223
vendor/gopkg.in/square/go-jose.v2/json/bench_test.go
generated
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Large data benchmark.
|
||||
// The JSON data is a summary of agl's changes in the
|
||||
// go, webkit, and chromium open source projects.
|
||||
// We benchmark converting between the JSON form
|
||||
// and in-memory data structures.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type codeResponse struct {
|
||||
Tree *codeNode `json:"tree"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
type codeNode struct {
|
||||
Name string `json:"name"`
|
||||
Kids []*codeNode `json:"kids"`
|
||||
CLWeight float64 `json:"cl_weight"`
|
||||
Touches int `json:"touches"`
|
||||
MinT int64 `json:"min_t"`
|
||||
MaxT int64 `json:"max_t"`
|
||||
MeanT int64 `json:"mean_t"`
|
||||
}
|
||||
|
||||
var codeJSON []byte
|
||||
var codeStruct codeResponse
|
||||
|
||||
func codeInit() {
|
||||
f, err := os.Open("testdata/code.json.gz")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
gz, err := gzip.NewReader(f)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
data, err := ioutil.ReadAll(gz)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
codeJSON = data
|
||||
|
||||
if err := Unmarshal(codeJSON, &codeStruct); err != nil {
|
||||
panic("unmarshal code.json: " + err.Error())
|
||||
}
|
||||
|
||||
if data, err = Marshal(&codeStruct); err != nil {
|
||||
panic("marshal code.json: " + err.Error())
|
||||
}
|
||||
|
||||
if !bytes.Equal(data, codeJSON) {
|
||||
println("different lengths", len(data), len(codeJSON))
|
||||
for i := 0; i < len(data) && i < len(codeJSON); i++ {
|
||||
if data[i] != codeJSON[i] {
|
||||
println("re-marshal: changed at byte", i)
|
||||
println("orig: ", string(codeJSON[i-10:i+10]))
|
||||
println("new: ", string(data[i-10:i+10]))
|
||||
break
|
||||
}
|
||||
}
|
||||
panic("re-marshal code.json: different result")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCodeEncoder(b *testing.B) {
|
||||
if codeJSON == nil {
|
||||
b.StopTimer()
|
||||
codeInit()
|
||||
b.StartTimer()
|
||||
}
|
||||
enc := NewEncoder(ioutil.Discard)
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err := enc.Encode(&codeStruct); err != nil {
|
||||
b.Fatal("Encode:", err)
|
||||
}
|
||||
}
|
||||
b.SetBytes(int64(len(codeJSON)))
|
||||
}
|
||||
|
||||
func BenchmarkCodeMarshal(b *testing.B) {
|
||||
if codeJSON == nil {
|
||||
b.StopTimer()
|
||||
codeInit()
|
||||
b.StartTimer()
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := Marshal(&codeStruct); err != nil {
|
||||
b.Fatal("Marshal:", err)
|
||||
}
|
||||
}
|
||||
b.SetBytes(int64(len(codeJSON)))
|
||||
}
|
||||
|
||||
func BenchmarkCodeDecoder(b *testing.B) {
|
||||
if codeJSON == nil {
|
||||
b.StopTimer()
|
||||
codeInit()
|
||||
b.StartTimer()
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
dec := NewDecoder(&buf)
|
||||
var r codeResponse
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf.Write(codeJSON)
|
||||
// hide EOF
|
||||
buf.WriteByte('\n')
|
||||
buf.WriteByte('\n')
|
||||
buf.WriteByte('\n')
|
||||
if err := dec.Decode(&r); err != nil {
|
||||
b.Fatal("Decode:", err)
|
||||
}
|
||||
}
|
||||
b.SetBytes(int64(len(codeJSON)))
|
||||
}
|
||||
|
||||
func BenchmarkDecoderStream(b *testing.B) {
|
||||
b.StopTimer()
|
||||
var buf bytes.Buffer
|
||||
dec := NewDecoder(&buf)
|
||||
buf.WriteString(`"` + strings.Repeat("x", 1000000) + `"` + "\n\n\n")
|
||||
var x interface{}
|
||||
if err := dec.Decode(&x); err != nil {
|
||||
b.Fatal("Decode:", err)
|
||||
}
|
||||
ones := strings.Repeat(" 1\n", 300000) + "\n\n\n"
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if i%300000 == 0 {
|
||||
buf.WriteString(ones)
|
||||
}
|
||||
x = nil
|
||||
if err := dec.Decode(&x); err != nil || x != 1.0 {
|
||||
b.Fatalf("Decode: %v after %d", err, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCodeUnmarshal(b *testing.B) {
|
||||
if codeJSON == nil {
|
||||
b.StopTimer()
|
||||
codeInit()
|
||||
b.StartTimer()
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
var r codeResponse
|
||||
if err := Unmarshal(codeJSON, &r); err != nil {
|
||||
b.Fatal("Unmmarshal:", err)
|
||||
}
|
||||
}
|
||||
b.SetBytes(int64(len(codeJSON)))
|
||||
}
|
||||
|
||||
func BenchmarkCodeUnmarshalReuse(b *testing.B) {
|
||||
if codeJSON == nil {
|
||||
b.StopTimer()
|
||||
codeInit()
|
||||
b.StartTimer()
|
||||
}
|
||||
var r codeResponse
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err := Unmarshal(codeJSON, &r); err != nil {
|
||||
b.Fatal("Unmmarshal:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalString(b *testing.B) {
|
||||
data := []byte(`"hello, world"`)
|
||||
var s string
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err := Unmarshal(data, &s); err != nil {
|
||||
b.Fatal("Unmarshal:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalFloat64(b *testing.B) {
|
||||
var f float64
|
||||
data := []byte(`3.14`)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err := Unmarshal(data, &f); err != nil {
|
||||
b.Fatal("Unmarshal:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalInt64(b *testing.B) {
|
||||
var x int64
|
||||
data := []byte(`3`)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err := Unmarshal(data, &x); err != nil {
|
||||
b.Fatal("Unmarshal:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIssue10335(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
var s struct{}
|
||||
j := []byte(`{"a":{ }}`)
|
||||
for n := 0; n < b.N; n++ {
|
||||
if err := Unmarshal(j, &s); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
1183
vendor/gopkg.in/square/go-jose.v2/json/decode.go
generated
vendored
Normal file
1183
vendor/gopkg.in/square/go-jose.v2/json/decode.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1474
vendor/gopkg.in/square/go-jose.v2/json/decode_test.go
generated
vendored
Normal file
1474
vendor/gopkg.in/square/go-jose.v2/json/decode_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1197
vendor/gopkg.in/square/go-jose.v2/json/encode.go
generated
vendored
Normal file
1197
vendor/gopkg.in/square/go-jose.v2/json/encode.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
538
vendor/gopkg.in/square/go-jose.v2/json/encode_test.go
generated
vendored
Normal file
538
vendor/gopkg.in/square/go-jose.v2/json/encode_test.go
generated
vendored
Normal file
@@ -0,0 +1,538 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type Optionals struct {
|
||||
Sr string `json:"sr"`
|
||||
So string `json:"so,omitempty"`
|
||||
Sw string `json:"-"`
|
||||
|
||||
Ir int `json:"omitempty"` // actually named omitempty, not an option
|
||||
Io int `json:"io,omitempty"`
|
||||
|
||||
Slr []string `json:"slr,random"`
|
||||
Slo []string `json:"slo,omitempty"`
|
||||
|
||||
Mr map[string]interface{} `json:"mr"`
|
||||
Mo map[string]interface{} `json:",omitempty"`
|
||||
|
||||
Fr float64 `json:"fr"`
|
||||
Fo float64 `json:"fo,omitempty"`
|
||||
|
||||
Br bool `json:"br"`
|
||||
Bo bool `json:"bo,omitempty"`
|
||||
|
||||
Ur uint `json:"ur"`
|
||||
Uo uint `json:"uo,omitempty"`
|
||||
|
||||
Str struct{} `json:"str"`
|
||||
Sto struct{} `json:"sto,omitempty"`
|
||||
}
|
||||
|
||||
var optionalsExpected = `{
|
||||
"sr": "",
|
||||
"omitempty": 0,
|
||||
"slr": null,
|
||||
"mr": {},
|
||||
"fr": 0,
|
||||
"br": false,
|
||||
"ur": 0,
|
||||
"str": {},
|
||||
"sto": {}
|
||||
}`
|
||||
|
||||
func TestOmitEmpty(t *testing.T) {
|
||||
var o Optionals
|
||||
o.Sw = "something"
|
||||
o.Mr = map[string]interface{}{}
|
||||
o.Mo = map[string]interface{}{}
|
||||
|
||||
got, err := MarshalIndent(&o, "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := string(got); got != optionalsExpected {
|
||||
t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected)
|
||||
}
|
||||
}
|
||||
|
||||
type StringTag struct {
|
||||
BoolStr bool `json:",string"`
|
||||
IntStr int64 `json:",string"`
|
||||
StrStr string `json:",string"`
|
||||
}
|
||||
|
||||
var stringTagExpected = `{
|
||||
"BoolStr": "true",
|
||||
"IntStr": "42",
|
||||
"StrStr": "\"xzbit\""
|
||||
}`
|
||||
|
||||
func TestStringTag(t *testing.T) {
|
||||
var s StringTag
|
||||
s.BoolStr = true
|
||||
s.IntStr = 42
|
||||
s.StrStr = "xzbit"
|
||||
got, err := MarshalIndent(&s, "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := string(got); got != stringTagExpected {
|
||||
t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected)
|
||||
}
|
||||
|
||||
// Verify that it round-trips.
|
||||
var s2 StringTag
|
||||
err = NewDecoder(bytes.NewReader(got)).Decode(&s2)
|
||||
if err != nil {
|
||||
t.Fatalf("Decode: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(s, s2) {
|
||||
t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2)
|
||||
}
|
||||
}
|
||||
|
||||
// byte slices are special even if they're renamed types.
|
||||
type renamedByte byte
|
||||
type renamedByteSlice []byte
|
||||
type renamedRenamedByteSlice []renamedByte
|
||||
|
||||
func TestEncodeRenamedByteSlice(t *testing.T) {
|
||||
s := renamedByteSlice("abc")
|
||||
result, err := Marshal(s)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expect := `"YWJj"`
|
||||
if string(result) != expect {
|
||||
t.Errorf(" got %s want %s", result, expect)
|
||||
}
|
||||
r := renamedRenamedByteSlice("abc")
|
||||
result, err = Marshal(r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(result) != expect {
|
||||
t.Errorf(" got %s want %s", result, expect)
|
||||
}
|
||||
}
|
||||
|
||||
var unsupportedValues = []interface{}{
|
||||
math.NaN(),
|
||||
math.Inf(-1),
|
||||
math.Inf(1),
|
||||
}
|
||||
|
||||
func TestUnsupportedValues(t *testing.T) {
|
||||
for _, v := range unsupportedValues {
|
||||
if _, err := Marshal(v); err != nil {
|
||||
if _, ok := err.(*UnsupportedValueError); !ok {
|
||||
t.Errorf("for %v, got %T want UnsupportedValueError", v, err)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("for %v, expected error", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ref has Marshaler and Unmarshaler methods with pointer receiver.
|
||||
type Ref int
|
||||
|
||||
func (*Ref) MarshalJSON() ([]byte, error) {
|
||||
return []byte(`"ref"`), nil
|
||||
}
|
||||
|
||||
func (r *Ref) UnmarshalJSON([]byte) error {
|
||||
*r = 12
|
||||
return nil
|
||||
}
|
||||
|
||||
// Val has Marshaler methods with value receiver.
|
||||
type Val int
|
||||
|
||||
func (Val) MarshalJSON() ([]byte, error) {
|
||||
return []byte(`"val"`), nil
|
||||
}
|
||||
|
||||
// RefText has Marshaler and Unmarshaler methods with pointer receiver.
|
||||
type RefText int
|
||||
|
||||
func (*RefText) MarshalText() ([]byte, error) {
|
||||
return []byte(`"ref"`), nil
|
||||
}
|
||||
|
||||
func (r *RefText) UnmarshalText([]byte) error {
|
||||
*r = 13
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValText has Marshaler methods with value receiver.
|
||||
type ValText int
|
||||
|
||||
func (ValText) MarshalText() ([]byte, error) {
|
||||
return []byte(`"val"`), nil
|
||||
}
|
||||
|
||||
func TestRefValMarshal(t *testing.T) {
|
||||
var s = struct {
|
||||
R0 Ref
|
||||
R1 *Ref
|
||||
R2 RefText
|
||||
R3 *RefText
|
||||
V0 Val
|
||||
V1 *Val
|
||||
V2 ValText
|
||||
V3 *ValText
|
||||
}{
|
||||
R0: 12,
|
||||
R1: new(Ref),
|
||||
R2: 14,
|
||||
R3: new(RefText),
|
||||
V0: 13,
|
||||
V1: new(Val),
|
||||
V2: 15,
|
||||
V3: new(ValText),
|
||||
}
|
||||
const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`
|
||||
b, err := Marshal(&s)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal: %v", err)
|
||||
}
|
||||
if got := string(b); got != want {
|
||||
t.Errorf("got %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// C implements Marshaler and returns unescaped JSON.
|
||||
type C int
|
||||
|
||||
func (C) MarshalJSON() ([]byte, error) {
|
||||
return []byte(`"<&>"`), nil
|
||||
}
|
||||
|
||||
// CText implements Marshaler and returns unescaped text.
|
||||
type CText int
|
||||
|
||||
func (CText) MarshalText() ([]byte, error) {
|
||||
return []byte(`"<&>"`), nil
|
||||
}
|
||||
|
||||
func TestMarshalerEscaping(t *testing.T) {
|
||||
var c C
|
||||
want := `"\u003c\u0026\u003e"`
|
||||
b, err := Marshal(c)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal(c): %v", err)
|
||||
}
|
||||
if got := string(b); got != want {
|
||||
t.Errorf("Marshal(c) = %#q, want %#q", got, want)
|
||||
}
|
||||
|
||||
var ct CText
|
||||
want = `"\"\u003c\u0026\u003e\""`
|
||||
b, err = Marshal(ct)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal(ct): %v", err)
|
||||
}
|
||||
if got := string(b); got != want {
|
||||
t.Errorf("Marshal(ct) = %#q, want %#q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
type IntType int
|
||||
|
||||
type MyStruct struct {
|
||||
IntType
|
||||
}
|
||||
|
||||
func TestAnonymousNonstruct(t *testing.T) {
|
||||
var i IntType = 11
|
||||
a := MyStruct{i}
|
||||
const want = `{"IntType":11}`
|
||||
|
||||
b, err := Marshal(a)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal: %v", err)
|
||||
}
|
||||
if got := string(b); got != want {
|
||||
t.Errorf("got %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
type BugA struct {
|
||||
S string
|
||||
}
|
||||
|
||||
type BugB struct {
|
||||
BugA
|
||||
S string
|
||||
}
|
||||
|
||||
type BugC struct {
|
||||
S string
|
||||
}
|
||||
|
||||
// Legal Go: We never use the repeated embedded field (S).
|
||||
type BugX struct {
|
||||
A int
|
||||
BugA
|
||||
BugB
|
||||
}
|
||||
|
||||
// Issue 5245.
|
||||
func TestEmbeddedBug(t *testing.T) {
|
||||
v := BugB{
|
||||
BugA{"A"},
|
||||
"B",
|
||||
}
|
||||
b, err := Marshal(v)
|
||||
if err != nil {
|
||||
t.Fatal("Marshal:", err)
|
||||
}
|
||||
want := `{"S":"B"}`
|
||||
got := string(b)
|
||||
if got != want {
|
||||
t.Fatalf("Marshal: got %s want %s", got, want)
|
||||
}
|
||||
// Now check that the duplicate field, S, does not appear.
|
||||
x := BugX{
|
||||
A: 23,
|
||||
}
|
||||
b, err = Marshal(x)
|
||||
if err != nil {
|
||||
t.Fatal("Marshal:", err)
|
||||
}
|
||||
want = `{"A":23}`
|
||||
got = string(b)
|
||||
if got != want {
|
||||
t.Fatalf("Marshal: got %s want %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
type BugD struct { // Same as BugA after tagging.
|
||||
XXX string `json:"S"`
|
||||
}
|
||||
|
||||
// BugD's tagged S field should dominate BugA's.
|
||||
type BugY struct {
|
||||
BugA
|
||||
BugD
|
||||
}
|
||||
|
||||
// Test that a field with a tag dominates untagged fields.
|
||||
func TestTaggedFieldDominates(t *testing.T) {
|
||||
v := BugY{
|
||||
BugA{"BugA"},
|
||||
BugD{"BugD"},
|
||||
}
|
||||
b, err := Marshal(v)
|
||||
if err != nil {
|
||||
t.Fatal("Marshal:", err)
|
||||
}
|
||||
want := `{"S":"BugD"}`
|
||||
got := string(b)
|
||||
if got != want {
|
||||
t.Fatalf("Marshal: got %s want %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// There are no tags here, so S should not appear.
|
||||
type BugZ struct {
|
||||
BugA
|
||||
BugC
|
||||
BugY // Contains a tagged S field through BugD; should not dominate.
|
||||
}
|
||||
|
||||
func TestDuplicatedFieldDisappears(t *testing.T) {
|
||||
v := BugZ{
|
||||
BugA{"BugA"},
|
||||
BugC{"BugC"},
|
||||
BugY{
|
||||
BugA{"nested BugA"},
|
||||
BugD{"nested BugD"},
|
||||
},
|
||||
}
|
||||
b, err := Marshal(v)
|
||||
if err != nil {
|
||||
t.Fatal("Marshal:", err)
|
||||
}
|
||||
want := `{}`
|
||||
got := string(b)
|
||||
if got != want {
|
||||
t.Fatalf("Marshal: got %s want %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringBytes(t *testing.T) {
|
||||
// Test that encodeState.stringBytes and encodeState.string use the same encoding.
|
||||
es := &encodeState{}
|
||||
var r []rune
|
||||
for i := '\u0000'; i <= unicode.MaxRune; i++ {
|
||||
r = append(r, i)
|
||||
}
|
||||
s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too
|
||||
es.string(s)
|
||||
|
||||
esBytes := &encodeState{}
|
||||
esBytes.stringBytes([]byte(s))
|
||||
|
||||
enc := es.Buffer.String()
|
||||
encBytes := esBytes.Buffer.String()
|
||||
if enc != encBytes {
|
||||
i := 0
|
||||
for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] {
|
||||
i++
|
||||
}
|
||||
enc = enc[i:]
|
||||
encBytes = encBytes[i:]
|
||||
i = 0
|
||||
for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] {
|
||||
i++
|
||||
}
|
||||
enc = enc[:len(enc)-i]
|
||||
encBytes = encBytes[:len(encBytes)-i]
|
||||
|
||||
if len(enc) > 20 {
|
||||
enc = enc[:20] + "..."
|
||||
}
|
||||
if len(encBytes) > 20 {
|
||||
encBytes = encBytes[:20] + "..."
|
||||
}
|
||||
|
||||
t.Errorf("encodings differ at %#q vs %#q", enc, encBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue6458(t *testing.T) {
|
||||
type Foo struct {
|
||||
M RawMessage
|
||||
}
|
||||
x := Foo{RawMessage(`"foo"`)}
|
||||
|
||||
b, err := Marshal(&x)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if want := `{"M":"foo"}`; string(b) != want {
|
||||
t.Errorf("Marshal(&x) = %#q; want %#q", b, want)
|
||||
}
|
||||
|
||||
b, err = Marshal(x)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if want := `{"M":"ImZvbyI="}`; string(b) != want {
|
||||
t.Errorf("Marshal(x) = %#q; want %#q", b, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue10281(t *testing.T) {
|
||||
type Foo struct {
|
||||
N Number
|
||||
}
|
||||
x := Foo{Number(`invalid`)}
|
||||
|
||||
b, err := Marshal(&x)
|
||||
if err == nil {
|
||||
t.Errorf("Marshal(&x) = %#q; want error", b)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTMLEscape(t *testing.T) {
|
||||
var b, want bytes.Buffer
|
||||
m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}`
|
||||
want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`))
|
||||
HTMLEscape(&b, []byte(m))
|
||||
if !bytes.Equal(b.Bytes(), want.Bytes()) {
|
||||
t.Errorf("HTMLEscape(&b, []byte(m)) = %s; want %s", b.Bytes(), want.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
// golang.org/issue/8582
|
||||
func TestEncodePointerString(t *testing.T) {
|
||||
type stringPointer struct {
|
||||
N *int64 `json:"n,string"`
|
||||
}
|
||||
var n int64 = 42
|
||||
b, err := Marshal(stringPointer{N: &n})
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal: %v", err)
|
||||
}
|
||||
if got, want := string(b), `{"n":"42"}`; got != want {
|
||||
t.Errorf("Marshal = %s, want %s", got, want)
|
||||
}
|
||||
var back stringPointer
|
||||
err = Unmarshal(b, &back)
|
||||
if err != nil {
|
||||
t.Fatalf("Unmarshal: %v", err)
|
||||
}
|
||||
if back.N == nil {
|
||||
t.Fatalf("Unmarshalled nil N field")
|
||||
}
|
||||
if *back.N != 42 {
|
||||
t.Fatalf("*N = %d; want 42", *back.N)
|
||||
}
|
||||
}
|
||||
|
||||
var encodeStringTests = []struct {
|
||||
in string
|
||||
out string
|
||||
}{
|
||||
{"\x00", `"\u0000"`},
|
||||
{"\x01", `"\u0001"`},
|
||||
{"\x02", `"\u0002"`},
|
||||
{"\x03", `"\u0003"`},
|
||||
{"\x04", `"\u0004"`},
|
||||
{"\x05", `"\u0005"`},
|
||||
{"\x06", `"\u0006"`},
|
||||
{"\x07", `"\u0007"`},
|
||||
{"\x08", `"\u0008"`},
|
||||
{"\x09", `"\t"`},
|
||||
{"\x0a", `"\n"`},
|
||||
{"\x0b", `"\u000b"`},
|
||||
{"\x0c", `"\u000c"`},
|
||||
{"\x0d", `"\r"`},
|
||||
{"\x0e", `"\u000e"`},
|
||||
{"\x0f", `"\u000f"`},
|
||||
{"\x10", `"\u0010"`},
|
||||
{"\x11", `"\u0011"`},
|
||||
{"\x12", `"\u0012"`},
|
||||
{"\x13", `"\u0013"`},
|
||||
{"\x14", `"\u0014"`},
|
||||
{"\x15", `"\u0015"`},
|
||||
{"\x16", `"\u0016"`},
|
||||
{"\x17", `"\u0017"`},
|
||||
{"\x18", `"\u0018"`},
|
||||
{"\x19", `"\u0019"`},
|
||||
{"\x1a", `"\u001a"`},
|
||||
{"\x1b", `"\u001b"`},
|
||||
{"\x1c", `"\u001c"`},
|
||||
{"\x1d", `"\u001d"`},
|
||||
{"\x1e", `"\u001e"`},
|
||||
{"\x1f", `"\u001f"`},
|
||||
}
|
||||
|
||||
func TestEncodeString(t *testing.T) {
|
||||
for _, tt := range encodeStringTests {
|
||||
b, err := Marshal(tt.in)
|
||||
if err != nil {
|
||||
t.Errorf("Marshal(%q): %v", tt.in, err)
|
||||
continue
|
||||
}
|
||||
out := string(b)
|
||||
if out != tt.out {
|
||||
t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
141
vendor/gopkg.in/square/go-jose.v2/json/indent.go
generated
vendored
Normal file
141
vendor/gopkg.in/square/go-jose.v2/json/indent.go
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import "bytes"
|
||||
|
||||
// Compact appends to dst the JSON-encoded src with
|
||||
// insignificant space characters elided.
|
||||
func Compact(dst *bytes.Buffer, src []byte) error {
|
||||
return compact(dst, src, false)
|
||||
}
|
||||
|
||||
func compact(dst *bytes.Buffer, src []byte, escape bool) error {
|
||||
origLen := dst.Len()
|
||||
var scan scanner
|
||||
scan.reset()
|
||||
start := 0
|
||||
for i, c := range src {
|
||||
if escape && (c == '<' || c == '>' || c == '&') {
|
||||
if start < i {
|
||||
dst.Write(src[start:i])
|
||||
}
|
||||
dst.WriteString(`\u00`)
|
||||
dst.WriteByte(hex[c>>4])
|
||||
dst.WriteByte(hex[c&0xF])
|
||||
start = i + 1
|
||||
}
|
||||
// Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
|
||||
if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
|
||||
if start < i {
|
||||
dst.Write(src[start:i])
|
||||
}
|
||||
dst.WriteString(`\u202`)
|
||||
dst.WriteByte(hex[src[i+2]&0xF])
|
||||
start = i + 3
|
||||
}
|
||||
v := scan.step(&scan, c)
|
||||
if v >= scanSkipSpace {
|
||||
if v == scanError {
|
||||
break
|
||||
}
|
||||
if start < i {
|
||||
dst.Write(src[start:i])
|
||||
}
|
||||
start = i + 1
|
||||
}
|
||||
}
|
||||
if scan.eof() == scanError {
|
||||
dst.Truncate(origLen)
|
||||
return scan.err
|
||||
}
|
||||
if start < len(src) {
|
||||
dst.Write(src[start:])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newline(dst *bytes.Buffer, prefix, indent string, depth int) {
|
||||
dst.WriteByte('\n')
|
||||
dst.WriteString(prefix)
|
||||
for i := 0; i < depth; i++ {
|
||||
dst.WriteString(indent)
|
||||
}
|
||||
}
|
||||
|
||||
// Indent appends to dst an indented form of the JSON-encoded src.
|
||||
// Each element in a JSON object or array begins on a new,
|
||||
// indented line beginning with prefix followed by one or more
|
||||
// copies of indent according to the indentation nesting.
|
||||
// The data appended to dst does not begin with the prefix nor
|
||||
// any indentation, to make it easier to embed inside other formatted JSON data.
|
||||
// Although leading space characters (space, tab, carriage return, newline)
|
||||
// at the beginning of src are dropped, trailing space characters
|
||||
// at the end of src are preserved and copied to dst.
|
||||
// For example, if src has no trailing spaces, neither will dst;
|
||||
// if src ends in a trailing newline, so will dst.
|
||||
func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
|
||||
origLen := dst.Len()
|
||||
var scan scanner
|
||||
scan.reset()
|
||||
needIndent := false
|
||||
depth := 0
|
||||
for _, c := range src {
|
||||
scan.bytes++
|
||||
v := scan.step(&scan, c)
|
||||
if v == scanSkipSpace {
|
||||
continue
|
||||
}
|
||||
if v == scanError {
|
||||
break
|
||||
}
|
||||
if needIndent && v != scanEndObject && v != scanEndArray {
|
||||
needIndent = false
|
||||
depth++
|
||||
newline(dst, prefix, indent, depth)
|
||||
}
|
||||
|
||||
// Emit semantically uninteresting bytes
|
||||
// (in particular, punctuation in strings) unmodified.
|
||||
if v == scanContinue {
|
||||
dst.WriteByte(c)
|
||||
continue
|
||||
}
|
||||
|
||||
// Add spacing around real punctuation.
|
||||
switch c {
|
||||
case '{', '[':
|
||||
// delay indent so that empty object and array are formatted as {} and [].
|
||||
needIndent = true
|
||||
dst.WriteByte(c)
|
||||
|
||||
case ',':
|
||||
dst.WriteByte(c)
|
||||
newline(dst, prefix, indent, depth)
|
||||
|
||||
case ':':
|
||||
dst.WriteByte(c)
|
||||
dst.WriteByte(' ')
|
||||
|
||||
case '}', ']':
|
||||
if needIndent {
|
||||
// suppress indent in empty object/array
|
||||
needIndent = false
|
||||
} else {
|
||||
depth--
|
||||
newline(dst, prefix, indent, depth)
|
||||
}
|
||||
dst.WriteByte(c)
|
||||
|
||||
default:
|
||||
dst.WriteByte(c)
|
||||
}
|
||||
}
|
||||
if scan.eof() == scanError {
|
||||
dst.Truncate(origLen)
|
||||
return scan.err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
133
vendor/gopkg.in/square/go-jose.v2/json/number_test.go
generated
vendored
Normal file
133
vendor/gopkg.in/square/go-jose.v2/json/number_test.go
generated
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNumberIsValid(t *testing.T) {
|
||||
// From: http://stackoverflow.com/a/13340826
|
||||
var jsonNumberRegexp = regexp.MustCompile(`^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$`)
|
||||
|
||||
validTests := []string{
|
||||
"0",
|
||||
"-0",
|
||||
"1",
|
||||
"-1",
|
||||
"0.1",
|
||||
"-0.1",
|
||||
"1234",
|
||||
"-1234",
|
||||
"12.34",
|
||||
"-12.34",
|
||||
"12E0",
|
||||
"12E1",
|
||||
"12e34",
|
||||
"12E-0",
|
||||
"12e+1",
|
||||
"12e-34",
|
||||
"-12E0",
|
||||
"-12E1",
|
||||
"-12e34",
|
||||
"-12E-0",
|
||||
"-12e+1",
|
||||
"-12e-34",
|
||||
"1.2E0",
|
||||
"1.2E1",
|
||||
"1.2e34",
|
||||
"1.2E-0",
|
||||
"1.2e+1",
|
||||
"1.2e-34",
|
||||
"-1.2E0",
|
||||
"-1.2E1",
|
||||
"-1.2e34",
|
||||
"-1.2E-0",
|
||||
"-1.2e+1",
|
||||
"-1.2e-34",
|
||||
"0E0",
|
||||
"0E1",
|
||||
"0e34",
|
||||
"0E-0",
|
||||
"0e+1",
|
||||
"0e-34",
|
||||
"-0E0",
|
||||
"-0E1",
|
||||
"-0e34",
|
||||
"-0E-0",
|
||||
"-0e+1",
|
||||
"-0e-34",
|
||||
}
|
||||
|
||||
for _, test := range validTests {
|
||||
if !isValidNumber(test) {
|
||||
t.Errorf("%s should be valid", test)
|
||||
}
|
||||
|
||||
var f float64
|
||||
if err := Unmarshal([]byte(test), &f); err != nil {
|
||||
t.Errorf("%s should be valid but Unmarshal failed: %v", test, err)
|
||||
}
|
||||
|
||||
if !jsonNumberRegexp.MatchString(test) {
|
||||
t.Errorf("%s should be valid but regexp does not match", test)
|
||||
}
|
||||
}
|
||||
|
||||
invalidTests := []string{
|
||||
"",
|
||||
"invalid",
|
||||
"1.0.1",
|
||||
"1..1",
|
||||
"-1-2",
|
||||
"012a42",
|
||||
"01.2",
|
||||
"012",
|
||||
"12E12.12",
|
||||
"1e2e3",
|
||||
"1e+-2",
|
||||
"1e--23",
|
||||
"1e",
|
||||
"e1",
|
||||
"1e+",
|
||||
"1ea",
|
||||
"1a",
|
||||
"1.a",
|
||||
"1.",
|
||||
"01",
|
||||
"1.e1",
|
||||
}
|
||||
|
||||
for _, test := range invalidTests {
|
||||
if isValidNumber(test) {
|
||||
t.Errorf("%s should be invalid", test)
|
||||
}
|
||||
|
||||
var f float64
|
||||
if err := Unmarshal([]byte(test), &f); err == nil {
|
||||
t.Errorf("%s should be invalid but unmarshal wrote %v", test, f)
|
||||
}
|
||||
|
||||
if jsonNumberRegexp.MatchString(test) {
|
||||
t.Errorf("%s should be invalid but matches regexp", test)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNumberIsValid(b *testing.B) {
|
||||
s := "-61657.61667E+61673"
|
||||
for i := 0; i < b.N; i++ {
|
||||
isValidNumber(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNumberIsValidRegexp(b *testing.B) {
|
||||
var jsonNumberRegexp = regexp.MustCompile(`^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$`)
|
||||
s := "-61657.61667E+61673"
|
||||
for i := 0; i < b.N; i++ {
|
||||
jsonNumberRegexp.MatchString(s)
|
||||
}
|
||||
}
|
||||
623
vendor/gopkg.in/square/go-jose.v2/json/scanner.go
generated
vendored
Normal file
623
vendor/gopkg.in/square/go-jose.v2/json/scanner.go
generated
vendored
Normal file
@@ -0,0 +1,623 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
// JSON value parser state machine.
|
||||
// Just about at the limit of what is reasonable to write by hand.
|
||||
// Some parts are a bit tedious, but overall it nicely factors out the
|
||||
// otherwise common code from the multiple scanning functions
|
||||
// in this package (Compact, Indent, checkValid, nextValue, etc).
|
||||
//
|
||||
// This file starts with two simple examples using the scanner
|
||||
// before diving into the scanner itself.
|
||||
|
||||
import "strconv"
|
||||
|
||||
// checkValid verifies that data is valid JSON-encoded data.
|
||||
// scan is passed in for use by checkValid to avoid an allocation.
|
||||
func checkValid(data []byte, scan *scanner) error {
|
||||
scan.reset()
|
||||
for _, c := range data {
|
||||
scan.bytes++
|
||||
if scan.step(scan, c) == scanError {
|
||||
return scan.err
|
||||
}
|
||||
}
|
||||
if scan.eof() == scanError {
|
||||
return scan.err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// nextValue splits data after the next whole JSON value,
|
||||
// returning that value and the bytes that follow it as separate slices.
|
||||
// scan is passed in for use by nextValue to avoid an allocation.
|
||||
func nextValue(data []byte, scan *scanner) (value, rest []byte, err error) {
|
||||
scan.reset()
|
||||
for i, c := range data {
|
||||
v := scan.step(scan, c)
|
||||
if v >= scanEndObject {
|
||||
switch v {
|
||||
// probe the scanner with a space to determine whether we will
|
||||
// get scanEnd on the next character. Otherwise, if the next character
|
||||
// is not a space, scanEndTop allocates a needless error.
|
||||
case scanEndObject, scanEndArray:
|
||||
if scan.step(scan, ' ') == scanEnd {
|
||||
return data[:i+1], data[i+1:], nil
|
||||
}
|
||||
case scanError:
|
||||
return nil, nil, scan.err
|
||||
case scanEnd:
|
||||
return data[:i], data[i:], nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if scan.eof() == scanError {
|
||||
return nil, nil, scan.err
|
||||
}
|
||||
return data, nil, nil
|
||||
}
|
||||
|
||||
// A SyntaxError is a description of a JSON syntax error.
|
||||
type SyntaxError struct {
|
||||
msg string // description of error
|
||||
Offset int64 // error occurred after reading Offset bytes
|
||||
}
|
||||
|
||||
func (e *SyntaxError) Error() string { return e.msg }
|
||||
|
||||
// A scanner is a JSON scanning state machine.
|
||||
// Callers call scan.reset() and then pass bytes in one at a time
|
||||
// by calling scan.step(&scan, c) for each byte.
|
||||
// The return value, referred to as an opcode, tells the
|
||||
// caller about significant parsing events like beginning
|
||||
// and ending literals, objects, and arrays, so that the
|
||||
// caller can follow along if it wishes.
|
||||
// The return value scanEnd indicates that a single top-level
|
||||
// JSON value has been completed, *before* the byte that
|
||||
// just got passed in. (The indication must be delayed in order
|
||||
// to recognize the end of numbers: is 123 a whole value or
|
||||
// the beginning of 12345e+6?).
|
||||
type scanner struct {
|
||||
// The step is a func to be called to execute the next transition.
|
||||
// Also tried using an integer constant and a single func
|
||||
// with a switch, but using the func directly was 10% faster
|
||||
// on a 64-bit Mac Mini, and it's nicer to read.
|
||||
step func(*scanner, byte) int
|
||||
|
||||
// Reached end of top-level value.
|
||||
endTop bool
|
||||
|
||||
// Stack of what we're in the middle of - array values, object keys, object values.
|
||||
parseState []int
|
||||
|
||||
// Error that happened, if any.
|
||||
err error
|
||||
|
||||
// 1-byte redo (see undo method)
|
||||
redo bool
|
||||
redoCode int
|
||||
redoState func(*scanner, byte) int
|
||||
|
||||
// total bytes consumed, updated by decoder.Decode
|
||||
bytes int64
|
||||
}
|
||||
|
||||
// These values are returned by the state transition functions
|
||||
// assigned to scanner.state and the method scanner.eof.
|
||||
// They give details about the current state of the scan that
|
||||
// callers might be interested to know about.
|
||||
// It is okay to ignore the return value of any particular
|
||||
// call to scanner.state: if one call returns scanError,
|
||||
// every subsequent call will return scanError too.
|
||||
const (
|
||||
// Continue.
|
||||
scanContinue = iota // uninteresting byte
|
||||
scanBeginLiteral // end implied by next result != scanContinue
|
||||
scanBeginObject // begin object
|
||||
scanObjectKey // just finished object key (string)
|
||||
scanObjectValue // just finished non-last object value
|
||||
scanEndObject // end object (implies scanObjectValue if possible)
|
||||
scanBeginArray // begin array
|
||||
scanArrayValue // just finished array value
|
||||
scanEndArray // end array (implies scanArrayValue if possible)
|
||||
scanSkipSpace // space byte; can skip; known to be last "continue" result
|
||||
|
||||
// Stop.
|
||||
scanEnd // top-level value ended *before* this byte; known to be first "stop" result
|
||||
scanError // hit an error, scanner.err.
|
||||
)
|
||||
|
||||
// These values are stored in the parseState stack.
|
||||
// They give the current state of a composite value
|
||||
// being scanned. If the parser is inside a nested value
|
||||
// the parseState describes the nested state, outermost at entry 0.
|
||||
const (
|
||||
parseObjectKey = iota // parsing object key (before colon)
|
||||
parseObjectValue // parsing object value (after colon)
|
||||
parseArrayValue // parsing array value
|
||||
)
|
||||
|
||||
// reset prepares the scanner for use.
|
||||
// It must be called before calling s.step.
|
||||
func (s *scanner) reset() {
|
||||
s.step = stateBeginValue
|
||||
s.parseState = s.parseState[0:0]
|
||||
s.err = nil
|
||||
s.redo = false
|
||||
s.endTop = false
|
||||
}
|
||||
|
||||
// eof tells the scanner that the end of input has been reached.
|
||||
// It returns a scan status just as s.step does.
|
||||
func (s *scanner) eof() int {
|
||||
if s.err != nil {
|
||||
return scanError
|
||||
}
|
||||
if s.endTop {
|
||||
return scanEnd
|
||||
}
|
||||
s.step(s, ' ')
|
||||
if s.endTop {
|
||||
return scanEnd
|
||||
}
|
||||
if s.err == nil {
|
||||
s.err = &SyntaxError{"unexpected end of JSON input", s.bytes}
|
||||
}
|
||||
return scanError
|
||||
}
|
||||
|
||||
// pushParseState pushes a new parse state p onto the parse stack.
|
||||
func (s *scanner) pushParseState(p int) {
|
||||
s.parseState = append(s.parseState, p)
|
||||
}
|
||||
|
||||
// popParseState pops a parse state (already obtained) off the stack
|
||||
// and updates s.step accordingly.
|
||||
func (s *scanner) popParseState() {
|
||||
n := len(s.parseState) - 1
|
||||
s.parseState = s.parseState[0:n]
|
||||
s.redo = false
|
||||
if n == 0 {
|
||||
s.step = stateEndTop
|
||||
s.endTop = true
|
||||
} else {
|
||||
s.step = stateEndValue
|
||||
}
|
||||
}
|
||||
|
||||
func isSpace(c byte) bool {
|
||||
return c == ' ' || c == '\t' || c == '\r' || c == '\n'
|
||||
}
|
||||
|
||||
// stateBeginValueOrEmpty is the state after reading `[`.
|
||||
func stateBeginValueOrEmpty(s *scanner, c byte) int {
|
||||
if c <= ' ' && isSpace(c) {
|
||||
return scanSkipSpace
|
||||
}
|
||||
if c == ']' {
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
return stateBeginValue(s, c)
|
||||
}
|
||||
|
||||
// stateBeginValue is the state at the beginning of the input.
|
||||
func stateBeginValue(s *scanner, c byte) int {
|
||||
if c <= ' ' && isSpace(c) {
|
||||
return scanSkipSpace
|
||||
}
|
||||
switch c {
|
||||
case '{':
|
||||
s.step = stateBeginStringOrEmpty
|
||||
s.pushParseState(parseObjectKey)
|
||||
return scanBeginObject
|
||||
case '[':
|
||||
s.step = stateBeginValueOrEmpty
|
||||
s.pushParseState(parseArrayValue)
|
||||
return scanBeginArray
|
||||
case '"':
|
||||
s.step = stateInString
|
||||
return scanBeginLiteral
|
||||
case '-':
|
||||
s.step = stateNeg
|
||||
return scanBeginLiteral
|
||||
case '0': // beginning of 0.123
|
||||
s.step = state0
|
||||
return scanBeginLiteral
|
||||
case 't': // beginning of true
|
||||
s.step = stateT
|
||||
return scanBeginLiteral
|
||||
case 'f': // beginning of false
|
||||
s.step = stateF
|
||||
return scanBeginLiteral
|
||||
case 'n': // beginning of null
|
||||
s.step = stateN
|
||||
return scanBeginLiteral
|
||||
}
|
||||
if '1' <= c && c <= '9' { // beginning of 1234.5
|
||||
s.step = state1
|
||||
return scanBeginLiteral
|
||||
}
|
||||
return s.error(c, "looking for beginning of value")
|
||||
}
|
||||
|
||||
// stateBeginStringOrEmpty is the state after reading `{`.
|
||||
func stateBeginStringOrEmpty(s *scanner, c byte) int {
|
||||
if c <= ' ' && isSpace(c) {
|
||||
return scanSkipSpace
|
||||
}
|
||||
if c == '}' {
|
||||
n := len(s.parseState)
|
||||
s.parseState[n-1] = parseObjectValue
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
return stateBeginString(s, c)
|
||||
}
|
||||
|
||||
// stateBeginString is the state after reading `{"key": value,`.
|
||||
func stateBeginString(s *scanner, c byte) int {
|
||||
if c <= ' ' && isSpace(c) {
|
||||
return scanSkipSpace
|
||||
}
|
||||
if c == '"' {
|
||||
s.step = stateInString
|
||||
return scanBeginLiteral
|
||||
}
|
||||
return s.error(c, "looking for beginning of object key string")
|
||||
}
|
||||
|
||||
// stateEndValue is the state after completing a value,
|
||||
// such as after reading `{}` or `true` or `["x"`.
|
||||
func stateEndValue(s *scanner, c byte) int {
|
||||
n := len(s.parseState)
|
||||
if n == 0 {
|
||||
// Completed top-level before the current byte.
|
||||
s.step = stateEndTop
|
||||
s.endTop = true
|
||||
return stateEndTop(s, c)
|
||||
}
|
||||
if c <= ' ' && isSpace(c) {
|
||||
s.step = stateEndValue
|
||||
return scanSkipSpace
|
||||
}
|
||||
ps := s.parseState[n-1]
|
||||
switch ps {
|
||||
case parseObjectKey:
|
||||
if c == ':' {
|
||||
s.parseState[n-1] = parseObjectValue
|
||||
s.step = stateBeginValue
|
||||
return scanObjectKey
|
||||
}
|
||||
return s.error(c, "after object key")
|
||||
case parseObjectValue:
|
||||
if c == ',' {
|
||||
s.parseState[n-1] = parseObjectKey
|
||||
s.step = stateBeginString
|
||||
return scanObjectValue
|
||||
}
|
||||
if c == '}' {
|
||||
s.popParseState()
|
||||
return scanEndObject
|
||||
}
|
||||
return s.error(c, "after object key:value pair")
|
||||
case parseArrayValue:
|
||||
if c == ',' {
|
||||
s.step = stateBeginValue
|
||||
return scanArrayValue
|
||||
}
|
||||
if c == ']' {
|
||||
s.popParseState()
|
||||
return scanEndArray
|
||||
}
|
||||
return s.error(c, "after array element")
|
||||
}
|
||||
return s.error(c, "")
|
||||
}
|
||||
|
||||
// stateEndTop is the state after finishing the top-level value,
|
||||
// such as after reading `{}` or `[1,2,3]`.
|
||||
// Only space characters should be seen now.
|
||||
func stateEndTop(s *scanner, c byte) int {
|
||||
if c != ' ' && c != '\t' && c != '\r' && c != '\n' {
|
||||
// Complain about non-space byte on next call.
|
||||
s.error(c, "after top-level value")
|
||||
}
|
||||
return scanEnd
|
||||
}
|
||||
|
||||
// stateInString is the state after reading `"`.
|
||||
func stateInString(s *scanner, c byte) int {
|
||||
if c == '"' {
|
||||
s.step = stateEndValue
|
||||
return scanContinue
|
||||
}
|
||||
if c == '\\' {
|
||||
s.step = stateInStringEsc
|
||||
return scanContinue
|
||||
}
|
||||
if c < 0x20 {
|
||||
return s.error(c, "in string literal")
|
||||
}
|
||||
return scanContinue
|
||||
}
|
||||
|
||||
// stateInStringEsc is the state after reading `"\` during a quoted string.
|
||||
func stateInStringEsc(s *scanner, c byte) int {
|
||||
switch c {
|
||||
case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
|
||||
s.step = stateInString
|
||||
return scanContinue
|
||||
case 'u':
|
||||
s.step = stateInStringEscU
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in string escape code")
|
||||
}
|
||||
|
||||
// stateInStringEscU is the state after reading `"\u` during a quoted string.
|
||||
func stateInStringEscU(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
|
||||
s.step = stateInStringEscU1
|
||||
return scanContinue
|
||||
}
|
||||
// numbers
|
||||
return s.error(c, "in \\u hexadecimal character escape")
|
||||
}
|
||||
|
||||
// stateInStringEscU1 is the state after reading `"\u1` during a quoted string.
|
||||
func stateInStringEscU1(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
|
||||
s.step = stateInStringEscU12
|
||||
return scanContinue
|
||||
}
|
||||
// numbers
|
||||
return s.error(c, "in \\u hexadecimal character escape")
|
||||
}
|
||||
|
||||
// stateInStringEscU12 is the state after reading `"\u12` during a quoted string.
|
||||
func stateInStringEscU12(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
|
||||
s.step = stateInStringEscU123
|
||||
return scanContinue
|
||||
}
|
||||
// numbers
|
||||
return s.error(c, "in \\u hexadecimal character escape")
|
||||
}
|
||||
|
||||
// stateInStringEscU123 is the state after reading `"\u123` during a quoted string.
|
||||
func stateInStringEscU123(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
|
||||
s.step = stateInString
|
||||
return scanContinue
|
||||
}
|
||||
// numbers
|
||||
return s.error(c, "in \\u hexadecimal character escape")
|
||||
}
|
||||
|
||||
// stateNeg is the state after reading `-` during a number.
|
||||
func stateNeg(s *scanner, c byte) int {
|
||||
if c == '0' {
|
||||
s.step = state0
|
||||
return scanContinue
|
||||
}
|
||||
if '1' <= c && c <= '9' {
|
||||
s.step = state1
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in numeric literal")
|
||||
}
|
||||
|
||||
// state1 is the state after reading a non-zero integer during a number,
|
||||
// such as after reading `1` or `100` but not `0`.
|
||||
func state1(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
s.step = state1
|
||||
return scanContinue
|
||||
}
|
||||
return state0(s, c)
|
||||
}
|
||||
|
||||
// state0 is the state after reading `0` during a number.
|
||||
func state0(s *scanner, c byte) int {
|
||||
if c == '.' {
|
||||
s.step = stateDot
|
||||
return scanContinue
|
||||
}
|
||||
if c == 'e' || c == 'E' {
|
||||
s.step = stateE
|
||||
return scanContinue
|
||||
}
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
|
||||
// stateDot is the state after reading the integer and decimal point in a number,
|
||||
// such as after reading `1.`.
|
||||
func stateDot(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
s.step = stateDot0
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "after decimal point in numeric literal")
|
||||
}
|
||||
|
||||
// stateDot0 is the state after reading the integer, decimal point, and subsequent
|
||||
// digits of a number, such as after reading `3.14`.
|
||||
func stateDot0(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
return scanContinue
|
||||
}
|
||||
if c == 'e' || c == 'E' {
|
||||
s.step = stateE
|
||||
return scanContinue
|
||||
}
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
|
||||
// stateE is the state after reading the mantissa and e in a number,
|
||||
// such as after reading `314e` or `0.314e`.
|
||||
func stateE(s *scanner, c byte) int {
|
||||
if c == '+' || c == '-' {
|
||||
s.step = stateESign
|
||||
return scanContinue
|
||||
}
|
||||
return stateESign(s, c)
|
||||
}
|
||||
|
||||
// stateESign is the state after reading the mantissa, e, and sign in a number,
|
||||
// such as after reading `314e-` or `0.314e+`.
|
||||
func stateESign(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
s.step = stateE0
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in exponent of numeric literal")
|
||||
}
|
||||
|
||||
// stateE0 is the state after reading the mantissa, e, optional sign,
|
||||
// and at least one digit of the exponent in a number,
|
||||
// such as after reading `314e-2` or `0.314e+1` or `3.14e0`.
|
||||
func stateE0(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
return scanContinue
|
||||
}
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
|
||||
// stateT is the state after reading `t`.
|
||||
func stateT(s *scanner, c byte) int {
|
||||
if c == 'r' {
|
||||
s.step = stateTr
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal true (expecting 'r')")
|
||||
}
|
||||
|
||||
// stateTr is the state after reading `tr`.
|
||||
func stateTr(s *scanner, c byte) int {
|
||||
if c == 'u' {
|
||||
s.step = stateTru
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal true (expecting 'u')")
|
||||
}
|
||||
|
||||
// stateTru is the state after reading `tru`.
|
||||
func stateTru(s *scanner, c byte) int {
|
||||
if c == 'e' {
|
||||
s.step = stateEndValue
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal true (expecting 'e')")
|
||||
}
|
||||
|
||||
// stateF is the state after reading `f`.
|
||||
func stateF(s *scanner, c byte) int {
|
||||
if c == 'a' {
|
||||
s.step = stateFa
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal false (expecting 'a')")
|
||||
}
|
||||
|
||||
// stateFa is the state after reading `fa`.
|
||||
func stateFa(s *scanner, c byte) int {
|
||||
if c == 'l' {
|
||||
s.step = stateFal
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal false (expecting 'l')")
|
||||
}
|
||||
|
||||
// stateFal is the state after reading `fal`.
|
||||
func stateFal(s *scanner, c byte) int {
|
||||
if c == 's' {
|
||||
s.step = stateFals
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal false (expecting 's')")
|
||||
}
|
||||
|
||||
// stateFals is the state after reading `fals`.
|
||||
func stateFals(s *scanner, c byte) int {
|
||||
if c == 'e' {
|
||||
s.step = stateEndValue
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal false (expecting 'e')")
|
||||
}
|
||||
|
||||
// stateN is the state after reading `n`.
|
||||
func stateN(s *scanner, c byte) int {
|
||||
if c == 'u' {
|
||||
s.step = stateNu
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal null (expecting 'u')")
|
||||
}
|
||||
|
||||
// stateNu is the state after reading `nu`.
|
||||
func stateNu(s *scanner, c byte) int {
|
||||
if c == 'l' {
|
||||
s.step = stateNul
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal null (expecting 'l')")
|
||||
}
|
||||
|
||||
// stateNul is the state after reading `nul`.
|
||||
func stateNul(s *scanner, c byte) int {
|
||||
if c == 'l' {
|
||||
s.step = stateEndValue
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal null (expecting 'l')")
|
||||
}
|
||||
|
||||
// stateError is the state after reaching a syntax error,
|
||||
// such as after reading `[1}` or `5.1.2`.
|
||||
func stateError(s *scanner, c byte) int {
|
||||
return scanError
|
||||
}
|
||||
|
||||
// error records an error and switches to the error state.
|
||||
func (s *scanner) error(c byte, context string) int {
|
||||
s.step = stateError
|
||||
s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes}
|
||||
return scanError
|
||||
}
|
||||
|
||||
// quoteChar formats c as a quoted character literal
|
||||
func quoteChar(c byte) string {
|
||||
// special cases - different from quoted strings
|
||||
if c == '\'' {
|
||||
return `'\''`
|
||||
}
|
||||
if c == '"' {
|
||||
return `'"'`
|
||||
}
|
||||
|
||||
// use quoted string with different quotation marks
|
||||
s := strconv.Quote(string(c))
|
||||
return "'" + s[1:len(s)-1] + "'"
|
||||
}
|
||||
|
||||
// undo causes the scanner to return scanCode from the next state transition.
|
||||
// This gives callers a simple 1-byte undo mechanism.
|
||||
func (s *scanner) undo(scanCode int) {
|
||||
if s.redo {
|
||||
panic("json: invalid use of scanner")
|
||||
}
|
||||
s.redoCode = scanCode
|
||||
s.redoState = s.step
|
||||
s.step = stateRedo
|
||||
s.redo = true
|
||||
}
|
||||
|
||||
// stateRedo helps implement the scanner's 1-byte undo.
|
||||
func stateRedo(s *scanner, c byte) int {
|
||||
s.redo = false
|
||||
s.step = s.redoState
|
||||
return s.redoCode
|
||||
}
|
||||
316
vendor/gopkg.in/square/go-jose.v2/json/scanner_test.go
generated
vendored
Normal file
316
vendor/gopkg.in/square/go-jose.v2/json/scanner_test.go
generated
vendored
Normal file
@@ -0,0 +1,316 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Tests of simple examples.
|
||||
|
||||
type example struct {
|
||||
compact string
|
||||
indent string
|
||||
}
|
||||
|
||||
var examples = []example{
|
||||
{`1`, `1`},
|
||||
{`{}`, `{}`},
|
||||
{`[]`, `[]`},
|
||||
{`{"":2}`, "{\n\t\"\": 2\n}"},
|
||||
{`[3]`, "[\n\t3\n]"},
|
||||
{`[1,2,3]`, "[\n\t1,\n\t2,\n\t3\n]"},
|
||||
{`{"x":1}`, "{\n\t\"x\": 1\n}"},
|
||||
{ex1, ex1i},
|
||||
}
|
||||
|
||||
var ex1 = `[true,false,null,"x",1,1.5,0,-5e+2]`
|
||||
|
||||
var ex1i = `[
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
"x",
|
||||
1,
|
||||
1.5,
|
||||
0,
|
||||
-5e+2
|
||||
]`
|
||||
|
||||
func TestCompact(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
for _, tt := range examples {
|
||||
buf.Reset()
|
||||
if err := Compact(&buf, []byte(tt.compact)); err != nil {
|
||||
t.Errorf("Compact(%#q): %v", tt.compact, err)
|
||||
} else if s := buf.String(); s != tt.compact {
|
||||
t.Errorf("Compact(%#q) = %#q, want original", tt.compact, s)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
if err := Compact(&buf, []byte(tt.indent)); err != nil {
|
||||
t.Errorf("Compact(%#q): %v", tt.indent, err)
|
||||
continue
|
||||
} else if s := buf.String(); s != tt.compact {
|
||||
t.Errorf("Compact(%#q) = %#q, want %#q", tt.indent, s, tt.compact)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompactSeparators(t *testing.T) {
|
||||
// U+2028 and U+2029 should be escaped inside strings.
|
||||
// They should not appear outside strings.
|
||||
tests := []struct {
|
||||
in, compact string
|
||||
}{
|
||||
{"{\"\u2028\": 1}", `{"\u2028":1}`},
|
||||
{"{\"\u2029\" :2}", `{"\u2029":2}`},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
var buf bytes.Buffer
|
||||
if err := Compact(&buf, []byte(tt.in)); err != nil {
|
||||
t.Errorf("Compact(%q): %v", tt.in, err)
|
||||
} else if s := buf.String(); s != tt.compact {
|
||||
t.Errorf("Compact(%q) = %q, want %q", tt.in, s, tt.compact)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndent(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
for _, tt := range examples {
|
||||
buf.Reset()
|
||||
if err := Indent(&buf, []byte(tt.indent), "", "\t"); err != nil {
|
||||
t.Errorf("Indent(%#q): %v", tt.indent, err)
|
||||
} else if s := buf.String(); s != tt.indent {
|
||||
t.Errorf("Indent(%#q) = %#q, want original", tt.indent, s)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
if err := Indent(&buf, []byte(tt.compact), "", "\t"); err != nil {
|
||||
t.Errorf("Indent(%#q): %v", tt.compact, err)
|
||||
continue
|
||||
} else if s := buf.String(); s != tt.indent {
|
||||
t.Errorf("Indent(%#q) = %#q, want %#q", tt.compact, s, tt.indent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests of a large random structure.
|
||||
|
||||
func TestCompactBig(t *testing.T) {
|
||||
initBig()
|
||||
var buf bytes.Buffer
|
||||
if err := Compact(&buf, jsonBig); err != nil {
|
||||
t.Fatalf("Compact: %v", err)
|
||||
}
|
||||
b := buf.Bytes()
|
||||
if !bytes.Equal(b, jsonBig) {
|
||||
t.Error("Compact(jsonBig) != jsonBig")
|
||||
diff(t, b, jsonBig)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndentBig(t *testing.T) {
|
||||
initBig()
|
||||
var buf bytes.Buffer
|
||||
if err := Indent(&buf, jsonBig, "", "\t"); err != nil {
|
||||
t.Fatalf("Indent1: %v", err)
|
||||
}
|
||||
b := buf.Bytes()
|
||||
if len(b) == len(jsonBig) {
|
||||
// jsonBig is compact (no unnecessary spaces);
|
||||
// indenting should make it bigger
|
||||
t.Fatalf("Indent(jsonBig) did not get bigger")
|
||||
}
|
||||
|
||||
// should be idempotent
|
||||
var buf1 bytes.Buffer
|
||||
if err := Indent(&buf1, b, "", "\t"); err != nil {
|
||||
t.Fatalf("Indent2: %v", err)
|
||||
}
|
||||
b1 := buf1.Bytes()
|
||||
if !bytes.Equal(b1, b) {
|
||||
t.Error("Indent(Indent(jsonBig)) != Indent(jsonBig)")
|
||||
diff(t, b1, b)
|
||||
return
|
||||
}
|
||||
|
||||
// should get back to original
|
||||
buf1.Reset()
|
||||
if err := Compact(&buf1, b); err != nil {
|
||||
t.Fatalf("Compact: %v", err)
|
||||
}
|
||||
b1 = buf1.Bytes()
|
||||
if !bytes.Equal(b1, jsonBig) {
|
||||
t.Error("Compact(Indent(jsonBig)) != jsonBig")
|
||||
diff(t, b1, jsonBig)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
type indentErrorTest struct {
|
||||
in string
|
||||
err error
|
||||
}
|
||||
|
||||
var indentErrorTests = []indentErrorTest{
|
||||
{`{"X": "foo", "Y"}`, &SyntaxError{"invalid character '}' after object key", 17}},
|
||||
{`{"X": "foo" "Y": "bar"}`, &SyntaxError{"invalid character '\"' after object key:value pair", 13}},
|
||||
}
|
||||
|
||||
func TestIndentErrors(t *testing.T) {
|
||||
for i, tt := range indentErrorTests {
|
||||
slice := make([]uint8, 0)
|
||||
buf := bytes.NewBuffer(slice)
|
||||
if err := Indent(buf, []uint8(tt.in), "", ""); err != nil {
|
||||
if !reflect.DeepEqual(err, tt.err) {
|
||||
t.Errorf("#%d: Indent: %#v", i, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNextValueBig(t *testing.T) {
|
||||
initBig()
|
||||
var scan scanner
|
||||
item, rest, err := nextValue(jsonBig, &scan)
|
||||
if err != nil {
|
||||
t.Fatalf("nextValue: %s", err)
|
||||
}
|
||||
if len(item) != len(jsonBig) || &item[0] != &jsonBig[0] {
|
||||
t.Errorf("invalid item: %d %d", len(item), len(jsonBig))
|
||||
}
|
||||
if len(rest) != 0 {
|
||||
t.Errorf("invalid rest: %d", len(rest))
|
||||
}
|
||||
|
||||
item, rest, err = nextValue(append(jsonBig, "HELLO WORLD"...), &scan)
|
||||
if err != nil {
|
||||
t.Fatalf("nextValue extra: %s", err)
|
||||
}
|
||||
if len(item) != len(jsonBig) {
|
||||
t.Errorf("invalid item: %d %d", len(item), len(jsonBig))
|
||||
}
|
||||
if string(rest) != "HELLO WORLD" {
|
||||
t.Errorf("invalid rest: %d", len(rest))
|
||||
}
|
||||
}
|
||||
|
||||
var benchScan scanner
|
||||
|
||||
func BenchmarkSkipValue(b *testing.B) {
|
||||
initBig()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
nextValue(jsonBig, &benchScan)
|
||||
}
|
||||
b.SetBytes(int64(len(jsonBig)))
|
||||
}
|
||||
|
||||
func diff(t *testing.T, a, b []byte) {
|
||||
for i := 0; ; i++ {
|
||||
if i >= len(a) || i >= len(b) || a[i] != b[i] {
|
||||
j := i - 10
|
||||
if j < 0 {
|
||||
j = 0
|
||||
}
|
||||
t.Errorf("diverge at %d: «%s» vs «%s»", i, trim(a[j:]), trim(b[j:]))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func trim(b []byte) []byte {
|
||||
if len(b) > 20 {
|
||||
return b[0:20]
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// Generate a random JSON object.
|
||||
|
||||
var jsonBig []byte
|
||||
|
||||
func initBig() {
|
||||
n := 10000
|
||||
if testing.Short() {
|
||||
n = 100
|
||||
}
|
||||
b, err := Marshal(genValue(n))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
jsonBig = b
|
||||
}
|
||||
|
||||
func genValue(n int) interface{} {
|
||||
if n > 1 {
|
||||
switch rand.Intn(2) {
|
||||
case 0:
|
||||
return genArray(n)
|
||||
case 1:
|
||||
return genMap(n)
|
||||
}
|
||||
}
|
||||
switch rand.Intn(3) {
|
||||
case 0:
|
||||
return rand.Intn(2) == 0
|
||||
case 1:
|
||||
return rand.NormFloat64()
|
||||
case 2:
|
||||
return genString(30)
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func genString(stddev float64) string {
|
||||
n := int(math.Abs(rand.NormFloat64()*stddev + stddev/2))
|
||||
c := make([]rune, n)
|
||||
for i := range c {
|
||||
f := math.Abs(rand.NormFloat64()*64 + 32)
|
||||
if f > 0x10ffff {
|
||||
f = 0x10ffff
|
||||
}
|
||||
c[i] = rune(f)
|
||||
}
|
||||
return string(c)
|
||||
}
|
||||
|
||||
func genArray(n int) []interface{} {
|
||||
f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2)))
|
||||
if f > n {
|
||||
f = n
|
||||
}
|
||||
if f < 1 {
|
||||
f = 1
|
||||
}
|
||||
x := make([]interface{}, f)
|
||||
for i := range x {
|
||||
x[i] = genValue(((i+1)*n)/f - (i*n)/f)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func genMap(n int) map[string]interface{} {
|
||||
f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2)))
|
||||
if f > n {
|
||||
f = n
|
||||
}
|
||||
if n > 0 && f == 0 {
|
||||
f = 1
|
||||
}
|
||||
x := make(map[string]interface{})
|
||||
for i := 0; i < f; i++ {
|
||||
x[genString(10)] = genValue(((i+1)*n)/f - (i*n)/f)
|
||||
}
|
||||
return x
|
||||
}
|
||||
480
vendor/gopkg.in/square/go-jose.v2/json/stream.go
generated
vendored
Normal file
480
vendor/gopkg.in/square/go-jose.v2/json/stream.go
generated
vendored
Normal file
@@ -0,0 +1,480 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
// A Decoder reads and decodes JSON objects from an input stream.
|
||||
type Decoder struct {
|
||||
r io.Reader
|
||||
buf []byte
|
||||
d decodeState
|
||||
scanp int // start of unread data in buf
|
||||
scan scanner
|
||||
err error
|
||||
|
||||
tokenState int
|
||||
tokenStack []int
|
||||
}
|
||||
|
||||
// NewDecoder returns a new decoder that reads from r.
|
||||
//
|
||||
// The decoder introduces its own buffering and may
|
||||
// read data from r beyond the JSON values requested.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
return &Decoder{r: r}
|
||||
}
|
||||
|
||||
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
|
||||
// Number instead of as a float64.
|
||||
func (dec *Decoder) UseNumber() { dec.d.useNumber = true }
|
||||
|
||||
// Decode reads the next JSON-encoded value from its
|
||||
// input and stores it in the value pointed to by v.
|
||||
//
|
||||
// See the documentation for Unmarshal for details about
|
||||
// the conversion of JSON into a Go value.
|
||||
func (dec *Decoder) Decode(v interface{}) error {
|
||||
if dec.err != nil {
|
||||
return dec.err
|
||||
}
|
||||
|
||||
if err := dec.tokenPrepareForDecode(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !dec.tokenValueAllowed() {
|
||||
return &SyntaxError{msg: "not at beginning of value"}
|
||||
}
|
||||
|
||||
// Read whole value into buffer.
|
||||
n, err := dec.readValue()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dec.d.init(dec.buf[dec.scanp : dec.scanp+n])
|
||||
dec.scanp += n
|
||||
|
||||
// Don't save err from unmarshal into dec.err:
|
||||
// the connection is still usable since we read a complete JSON
|
||||
// object from it before the error happened.
|
||||
err = dec.d.unmarshal(v)
|
||||
|
||||
// fixup token streaming state
|
||||
dec.tokenValueEnd()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Buffered returns a reader of the data remaining in the Decoder's
|
||||
// buffer. The reader is valid until the next call to Decode.
|
||||
func (dec *Decoder) Buffered() io.Reader {
|
||||
return bytes.NewReader(dec.buf[dec.scanp:])
|
||||
}
|
||||
|
||||
// readValue reads a JSON value into dec.buf.
|
||||
// It returns the length of the encoding.
|
||||
func (dec *Decoder) readValue() (int, error) {
|
||||
dec.scan.reset()
|
||||
|
||||
scanp := dec.scanp
|
||||
var err error
|
||||
Input:
|
||||
for {
|
||||
// Look in the buffer for a new value.
|
||||
for i, c := range dec.buf[scanp:] {
|
||||
dec.scan.bytes++
|
||||
v := dec.scan.step(&dec.scan, c)
|
||||
if v == scanEnd {
|
||||
scanp += i
|
||||
break Input
|
||||
}
|
||||
// scanEnd is delayed one byte.
|
||||
// We might block trying to get that byte from src,
|
||||
// so instead invent a space byte.
|
||||
if (v == scanEndObject || v == scanEndArray) && dec.scan.step(&dec.scan, ' ') == scanEnd {
|
||||
scanp += i + 1
|
||||
break Input
|
||||
}
|
||||
if v == scanError {
|
||||
dec.err = dec.scan.err
|
||||
return 0, dec.scan.err
|
||||
}
|
||||
}
|
||||
scanp = len(dec.buf)
|
||||
|
||||
// Did the last read have an error?
|
||||
// Delayed until now to allow buffer scan.
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if dec.scan.step(&dec.scan, ' ') == scanEnd {
|
||||
break Input
|
||||
}
|
||||
if nonSpace(dec.buf) {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
}
|
||||
dec.err = err
|
||||
return 0, err
|
||||
}
|
||||
|
||||
n := scanp - dec.scanp
|
||||
err = dec.refill()
|
||||
scanp = dec.scanp + n
|
||||
}
|
||||
return scanp - dec.scanp, nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) refill() error {
|
||||
// Make room to read more into the buffer.
|
||||
// First slide down data already consumed.
|
||||
if dec.scanp > 0 {
|
||||
n := copy(dec.buf, dec.buf[dec.scanp:])
|
||||
dec.buf = dec.buf[:n]
|
||||
dec.scanp = 0
|
||||
}
|
||||
|
||||
// Grow buffer if not large enough.
|
||||
const minRead = 512
|
||||
if cap(dec.buf)-len(dec.buf) < minRead {
|
||||
newBuf := make([]byte, len(dec.buf), 2*cap(dec.buf)+minRead)
|
||||
copy(newBuf, dec.buf)
|
||||
dec.buf = newBuf
|
||||
}
|
||||
|
||||
// Read. Delay error for next iteration (after scan).
|
||||
n, err := dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)])
|
||||
dec.buf = dec.buf[0 : len(dec.buf)+n]
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func nonSpace(b []byte) bool {
|
||||
for _, c := range b {
|
||||
if !isSpace(c) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// An Encoder writes JSON objects to an output stream.
|
||||
type Encoder struct {
|
||||
w io.Writer
|
||||
err error
|
||||
}
|
||||
|
||||
// NewEncoder returns a new encoder that writes to w.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
return &Encoder{w: w}
|
||||
}
|
||||
|
||||
// Encode writes the JSON encoding of v to the stream,
|
||||
// followed by a newline character.
|
||||
//
|
||||
// See the documentation for Marshal for details about the
|
||||
// conversion of Go values to JSON.
|
||||
func (enc *Encoder) Encode(v interface{}) error {
|
||||
if enc.err != nil {
|
||||
return enc.err
|
||||
}
|
||||
e := newEncodeState()
|
||||
err := e.marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Terminate each value with a newline.
|
||||
// This makes the output look a little nicer
|
||||
// when debugging, and some kind of space
|
||||
// is required if the encoded value was a number,
|
||||
// so that the reader knows there aren't more
|
||||
// digits coming.
|
||||
e.WriteByte('\n')
|
||||
|
||||
if _, err = enc.w.Write(e.Bytes()); err != nil {
|
||||
enc.err = err
|
||||
}
|
||||
encodeStatePool.Put(e)
|
||||
return err
|
||||
}
|
||||
|
||||
// RawMessage is a raw encoded JSON object.
|
||||
// It implements Marshaler and Unmarshaler and can
|
||||
// be used to delay JSON decoding or precompute a JSON encoding.
|
||||
type RawMessage []byte
|
||||
|
||||
// MarshalJSON returns *m as the JSON encoding of m.
|
||||
func (m *RawMessage) MarshalJSON() ([]byte, error) {
|
||||
return *m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets *m to a copy of data.
|
||||
func (m *RawMessage) UnmarshalJSON(data []byte) error {
|
||||
if m == nil {
|
||||
return errors.New("json.RawMessage: UnmarshalJSON on nil pointer")
|
||||
}
|
||||
*m = append((*m)[0:0], data...)
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ Marshaler = (*RawMessage)(nil)
|
||||
var _ Unmarshaler = (*RawMessage)(nil)
|
||||
|
||||
// A Token holds a value of one of these types:
|
||||
//
|
||||
// Delim, for the four JSON delimiters [ ] { }
|
||||
// bool, for JSON booleans
|
||||
// float64, for JSON numbers
|
||||
// Number, for JSON numbers
|
||||
// string, for JSON string literals
|
||||
// nil, for JSON null
|
||||
//
|
||||
type Token interface{}
|
||||
|
||||
const (
|
||||
tokenTopValue = iota
|
||||
tokenArrayStart
|
||||
tokenArrayValue
|
||||
tokenArrayComma
|
||||
tokenObjectStart
|
||||
tokenObjectKey
|
||||
tokenObjectColon
|
||||
tokenObjectValue
|
||||
tokenObjectComma
|
||||
)
|
||||
|
||||
// advance tokenstate from a separator state to a value state
|
||||
func (dec *Decoder) tokenPrepareForDecode() error {
|
||||
// Note: Not calling peek before switch, to avoid
|
||||
// putting peek into the standard Decode path.
|
||||
// peek is only called when using the Token API.
|
||||
switch dec.tokenState {
|
||||
case tokenArrayComma:
|
||||
c, err := dec.peek()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c != ',' {
|
||||
return &SyntaxError{"expected comma after array element", 0}
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenArrayValue
|
||||
case tokenObjectColon:
|
||||
c, err := dec.peek()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c != ':' {
|
||||
return &SyntaxError{"expected colon after object key", 0}
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenObjectValue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) tokenValueAllowed() bool {
|
||||
switch dec.tokenState {
|
||||
case tokenTopValue, tokenArrayStart, tokenArrayValue, tokenObjectValue:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (dec *Decoder) tokenValueEnd() {
|
||||
switch dec.tokenState {
|
||||
case tokenArrayStart, tokenArrayValue:
|
||||
dec.tokenState = tokenArrayComma
|
||||
case tokenObjectValue:
|
||||
dec.tokenState = tokenObjectComma
|
||||
}
|
||||
}
|
||||
|
||||
// A Delim is a JSON array or object delimiter, one of [ ] { or }.
|
||||
type Delim rune
|
||||
|
||||
func (d Delim) String() string {
|
||||
return string(d)
|
||||
}
|
||||
|
||||
// Token returns the next JSON token in the input stream.
|
||||
// At the end of the input stream, Token returns nil, io.EOF.
|
||||
//
|
||||
// Token guarantees that the delimiters [ ] { } it returns are
|
||||
// properly nested and matched: if Token encounters an unexpected
|
||||
// delimiter in the input, it will return an error.
|
||||
//
|
||||
// The input stream consists of basic JSON values—bool, string,
|
||||
// number, and null—along with delimiters [ ] { } of type Delim
|
||||
// to mark the start and end of arrays and objects.
|
||||
// Commas and colons are elided.
|
||||
func (dec *Decoder) Token() (Token, error) {
|
||||
for {
|
||||
c, err := dec.peek()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch c {
|
||||
case '[':
|
||||
if !dec.tokenValueAllowed() {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenStack = append(dec.tokenStack, dec.tokenState)
|
||||
dec.tokenState = tokenArrayStart
|
||||
return Delim('['), nil
|
||||
|
||||
case ']':
|
||||
if dec.tokenState != tokenArrayStart && dec.tokenState != tokenArrayComma {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = dec.tokenStack[len(dec.tokenStack)-1]
|
||||
dec.tokenStack = dec.tokenStack[:len(dec.tokenStack)-1]
|
||||
dec.tokenValueEnd()
|
||||
return Delim(']'), nil
|
||||
|
||||
case '{':
|
||||
if !dec.tokenValueAllowed() {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenStack = append(dec.tokenStack, dec.tokenState)
|
||||
dec.tokenState = tokenObjectStart
|
||||
return Delim('{'), nil
|
||||
|
||||
case '}':
|
||||
if dec.tokenState != tokenObjectStart && dec.tokenState != tokenObjectComma {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = dec.tokenStack[len(dec.tokenStack)-1]
|
||||
dec.tokenStack = dec.tokenStack[:len(dec.tokenStack)-1]
|
||||
dec.tokenValueEnd()
|
||||
return Delim('}'), nil
|
||||
|
||||
case ':':
|
||||
if dec.tokenState != tokenObjectColon {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenObjectValue
|
||||
continue
|
||||
|
||||
case ',':
|
||||
if dec.tokenState == tokenArrayComma {
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenArrayValue
|
||||
continue
|
||||
}
|
||||
if dec.tokenState == tokenObjectComma {
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenObjectKey
|
||||
continue
|
||||
}
|
||||
return dec.tokenError(c)
|
||||
|
||||
case '"':
|
||||
if dec.tokenState == tokenObjectStart || dec.tokenState == tokenObjectKey {
|
||||
var x string
|
||||
old := dec.tokenState
|
||||
dec.tokenState = tokenTopValue
|
||||
err := dec.Decode(&x)
|
||||
dec.tokenState = old
|
||||
if err != nil {
|
||||
clearOffset(err)
|
||||
return nil, err
|
||||
}
|
||||
dec.tokenState = tokenObjectColon
|
||||
return x, nil
|
||||
}
|
||||
fallthrough
|
||||
|
||||
default:
|
||||
if !dec.tokenValueAllowed() {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
var x interface{}
|
||||
if err := dec.Decode(&x); err != nil {
|
||||
clearOffset(err)
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func clearOffset(err error) {
|
||||
if s, ok := err.(*SyntaxError); ok {
|
||||
s.Offset = 0
|
||||
}
|
||||
}
|
||||
|
||||
func (dec *Decoder) tokenError(c byte) (Token, error) {
|
||||
var context string
|
||||
switch dec.tokenState {
|
||||
case tokenTopValue:
|
||||
context = " looking for beginning of value"
|
||||
case tokenArrayStart, tokenArrayValue, tokenObjectValue:
|
||||
context = " looking for beginning of value"
|
||||
case tokenArrayComma:
|
||||
context = " after array element"
|
||||
case tokenObjectKey:
|
||||
context = " looking for beginning of object key string"
|
||||
case tokenObjectColon:
|
||||
context = " after object key"
|
||||
case tokenObjectComma:
|
||||
context = " after object key:value pair"
|
||||
}
|
||||
return nil, &SyntaxError{"invalid character " + quoteChar(c) + " " + context, 0}
|
||||
}
|
||||
|
||||
// More reports whether there is another element in the
|
||||
// current array or object being parsed.
|
||||
func (dec *Decoder) More() bool {
|
||||
c, err := dec.peek()
|
||||
return err == nil && c != ']' && c != '}'
|
||||
}
|
||||
|
||||
func (dec *Decoder) peek() (byte, error) {
|
||||
var err error
|
||||
for {
|
||||
for i := dec.scanp; i < len(dec.buf); i++ {
|
||||
c := dec.buf[i]
|
||||
if isSpace(c) {
|
||||
continue
|
||||
}
|
||||
dec.scanp = i
|
||||
return c, nil
|
||||
}
|
||||
// buffer has been scanned, now report any error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
err = dec.refill()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TODO
|
||||
|
||||
// EncodeToken writes the given JSON token to the stream.
|
||||
// It returns an error if the delimiters [ ] { } are not properly used.
|
||||
//
|
||||
// EncodeToken does not call Flush, because usually it is part of
|
||||
// a larger operation such as Encode, and those will call Flush when finished.
|
||||
// Callers that create an Encoder and then invoke EncodeToken directly,
|
||||
// without using Encode, need to call Flush when finished to ensure that
|
||||
// the JSON is written to the underlying writer.
|
||||
func (e *Encoder) EncodeToken(t Token) error {
|
||||
...
|
||||
}
|
||||
|
||||
*/
|
||||
354
vendor/gopkg.in/square/go-jose.v2/json/stream_test.go
generated
vendored
Normal file
354
vendor/gopkg.in/square/go-jose.v2/json/stream_test.go
generated
vendored
Normal file
@@ -0,0 +1,354 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Test values for the stream test.
|
||||
// One of each JSON kind.
|
||||
var streamTest = []interface{}{
|
||||
0.1,
|
||||
"hello",
|
||||
nil,
|
||||
true,
|
||||
false,
|
||||
[]interface{}{"a", "b", "c"},
|
||||
map[string]interface{}{"K": "Kelvin", "ß": "long s"},
|
||||
3.14, // another value to make sure something can follow map
|
||||
}
|
||||
|
||||
var streamEncoded = `0.1
|
||||
"hello"
|
||||
null
|
||||
true
|
||||
false
|
||||
["a","b","c"]
|
||||
{"ß":"long s","K":"Kelvin"}
|
||||
3.14
|
||||
`
|
||||
|
||||
func TestEncoder(t *testing.T) {
|
||||
for i := 0; i <= len(streamTest); i++ {
|
||||
var buf bytes.Buffer
|
||||
enc := NewEncoder(&buf)
|
||||
for j, v := range streamTest[0:i] {
|
||||
if err := enc.Encode(v); err != nil {
|
||||
t.Fatalf("encode #%d: %v", j, err)
|
||||
}
|
||||
}
|
||||
if have, want := buf.String(), nlines(streamEncoded, i); have != want {
|
||||
t.Errorf("encoding %d items: mismatch", i)
|
||||
diff(t, []byte(have), []byte(want))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecoder(t *testing.T) {
|
||||
for i := 0; i <= len(streamTest); i++ {
|
||||
// Use stream without newlines as input,
|
||||
// just to stress the decoder even more.
|
||||
// Our test input does not include back-to-back numbers.
|
||||
// Otherwise stripping the newlines would
|
||||
// merge two adjacent JSON values.
|
||||
var buf bytes.Buffer
|
||||
for _, c := range nlines(streamEncoded, i) {
|
||||
if c != '\n' {
|
||||
buf.WriteRune(c)
|
||||
}
|
||||
}
|
||||
out := make([]interface{}, i)
|
||||
dec := NewDecoder(&buf)
|
||||
for j := range out {
|
||||
if err := dec.Decode(&out[j]); err != nil {
|
||||
t.Fatalf("decode #%d/%d: %v", j, i, err)
|
||||
}
|
||||
}
|
||||
if !reflect.DeepEqual(out, streamTest[0:i]) {
|
||||
t.Errorf("decoding %d items: mismatch", i)
|
||||
for j := range out {
|
||||
if !reflect.DeepEqual(out[j], streamTest[j]) {
|
||||
t.Errorf("#%d: have %v want %v", j, out[j], streamTest[j])
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecoderBuffered(t *testing.T) {
|
||||
r := strings.NewReader(`{"Name": "Gopher"} extra `)
|
||||
var m struct {
|
||||
Name string
|
||||
}
|
||||
d := NewDecoder(r)
|
||||
err := d.Decode(&m)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if m.Name != "Gopher" {
|
||||
t.Errorf("Name = %q; want Gopher", m.Name)
|
||||
}
|
||||
rest, err := ioutil.ReadAll(d.Buffered())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if g, w := string(rest), " extra "; g != w {
|
||||
t.Errorf("Remaining = %q; want %q", g, w)
|
||||
}
|
||||
}
|
||||
|
||||
func nlines(s string, n int) string {
|
||||
if n <= 0 {
|
||||
return ""
|
||||
}
|
||||
for i, c := range s {
|
||||
if c == '\n' {
|
||||
if n--; n == 0 {
|
||||
return s[0 : i+1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func TestRawMessage(t *testing.T) {
|
||||
// TODO(rsc): Should not need the * in *RawMessage
|
||||
var data struct {
|
||||
X float64
|
||||
Id *RawMessage
|
||||
Y float32
|
||||
}
|
||||
const raw = `["\u0056",null]`
|
||||
const msg = `{"X":0.1,"Id":["\u0056",null],"Y":0.2}`
|
||||
err := Unmarshal([]byte(msg), &data)
|
||||
if err != nil {
|
||||
t.Fatalf("Unmarshal: %v", err)
|
||||
}
|
||||
if string([]byte(*data.Id)) != raw {
|
||||
t.Fatalf("Raw mismatch: have %#q want %#q", []byte(*data.Id), raw)
|
||||
}
|
||||
b, err := Marshal(&data)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal: %v", err)
|
||||
}
|
||||
if string(b) != msg {
|
||||
t.Fatalf("Marshal: have %#q want %#q", b, msg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNullRawMessage(t *testing.T) {
|
||||
// TODO(rsc): Should not need the * in *RawMessage
|
||||
var data struct {
|
||||
X float64
|
||||
Id *RawMessage
|
||||
Y float32
|
||||
}
|
||||
data.Id = new(RawMessage)
|
||||
const msg = `{"X":0.1,"Id":null,"Y":0.2}`
|
||||
err := Unmarshal([]byte(msg), &data)
|
||||
if err != nil {
|
||||
t.Fatalf("Unmarshal: %v", err)
|
||||
}
|
||||
if data.Id != nil {
|
||||
t.Fatalf("Raw mismatch: have non-nil, want nil")
|
||||
}
|
||||
b, err := Marshal(&data)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal: %v", err)
|
||||
}
|
||||
if string(b) != msg {
|
||||
t.Fatalf("Marshal: have %#q want %#q", b, msg)
|
||||
}
|
||||
}
|
||||
|
||||
var blockingTests = []string{
|
||||
`{"x": 1}`,
|
||||
`[1, 2, 3]`,
|
||||
}
|
||||
|
||||
func TestBlocking(t *testing.T) {
|
||||
for _, enc := range blockingTests {
|
||||
r, w := net.Pipe()
|
||||
go w.Write([]byte(enc))
|
||||
var val interface{}
|
||||
|
||||
// If Decode reads beyond what w.Write writes above,
|
||||
// it will block, and the test will deadlock.
|
||||
if err := NewDecoder(r).Decode(&val); err != nil {
|
||||
t.Errorf("decoding %s: %v", enc, err)
|
||||
}
|
||||
r.Close()
|
||||
w.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncoderEncode(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
type T struct {
|
||||
X, Y string
|
||||
}
|
||||
v := &T{"foo", "bar"}
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err := NewEncoder(ioutil.Discard).Encode(v); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type tokenStreamCase struct {
|
||||
json string
|
||||
expTokens []interface{}
|
||||
}
|
||||
|
||||
type decodeThis struct {
|
||||
v interface{}
|
||||
}
|
||||
|
||||
var tokenStreamCases []tokenStreamCase = []tokenStreamCase{
|
||||
// streaming token cases
|
||||
{json: `10`, expTokens: []interface{}{float64(10)}},
|
||||
{json: ` [10] `, expTokens: []interface{}{
|
||||
Delim('['), float64(10), Delim(']')}},
|
||||
{json: ` [false,10,"b"] `, expTokens: []interface{}{
|
||||
Delim('['), false, float64(10), "b", Delim(']')}},
|
||||
{json: `{ "a": 1 }`, expTokens: []interface{}{
|
||||
Delim('{'), "a", float64(1), Delim('}')}},
|
||||
{json: `{"a": 1, "b":"3"}`, expTokens: []interface{}{
|
||||
Delim('{'), "a", float64(1), "b", "3", Delim('}')}},
|
||||
{json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{
|
||||
Delim('['),
|
||||
Delim('{'), "a", float64(1), Delim('}'),
|
||||
Delim('{'), "a", float64(2), Delim('}'),
|
||||
Delim(']')}},
|
||||
{json: `{"obj": {"a": 1}}`, expTokens: []interface{}{
|
||||
Delim('{'), "obj", Delim('{'), "a", float64(1), Delim('}'),
|
||||
Delim('}')}},
|
||||
{json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{
|
||||
Delim('{'), "obj", Delim('['),
|
||||
Delim('{'), "a", float64(1), Delim('}'),
|
||||
Delim(']'), Delim('}')}},
|
||||
|
||||
// streaming tokens with intermittent Decode()
|
||||
{json: `{ "a": 1 }`, expTokens: []interface{}{
|
||||
Delim('{'), "a",
|
||||
decodeThis{float64(1)},
|
||||
Delim('}')}},
|
||||
{json: ` [ { "a" : 1 } ] `, expTokens: []interface{}{
|
||||
Delim('['),
|
||||
decodeThis{map[string]interface{}{"a": float64(1)}},
|
||||
Delim(']')}},
|
||||
{json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{
|
||||
Delim('['),
|
||||
decodeThis{map[string]interface{}{"a": float64(1)}},
|
||||
decodeThis{map[string]interface{}{"a": float64(2)}},
|
||||
Delim(']')}},
|
||||
{json: `{ "obj" : [ { "a" : 1 } ] }`, expTokens: []interface{}{
|
||||
Delim('{'), "obj", Delim('['),
|
||||
decodeThis{map[string]interface{}{"a": float64(1)}},
|
||||
Delim(']'), Delim('}')}},
|
||||
|
||||
{json: `{"obj": {"a": 1}}`, expTokens: []interface{}{
|
||||
Delim('{'), "obj",
|
||||
decodeThis{map[string]interface{}{"a": float64(1)}},
|
||||
Delim('}')}},
|
||||
{json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{
|
||||
Delim('{'), "obj",
|
||||
decodeThis{[]interface{}{
|
||||
map[string]interface{}{"a": float64(1)},
|
||||
}},
|
||||
Delim('}')}},
|
||||
{json: ` [{"a": 1} {"a": 2}] `, expTokens: []interface{}{
|
||||
Delim('['),
|
||||
decodeThis{map[string]interface{}{"a": float64(1)}},
|
||||
decodeThis{&SyntaxError{"expected comma after array element", 0}},
|
||||
}},
|
||||
{json: `{ "a" 1 }`, expTokens: []interface{}{
|
||||
Delim('{'), "a",
|
||||
decodeThis{&SyntaxError{"expected colon after object key", 0}},
|
||||
}},
|
||||
}
|
||||
|
||||
func TestDecodeInStream(t *testing.T) {
|
||||
|
||||
for ci, tcase := range tokenStreamCases {
|
||||
|
||||
dec := NewDecoder(strings.NewReader(tcase.json))
|
||||
for i, etk := range tcase.expTokens {
|
||||
|
||||
var tk interface{}
|
||||
var err error
|
||||
|
||||
if dt, ok := etk.(decodeThis); ok {
|
||||
etk = dt.v
|
||||
err = dec.Decode(&tk)
|
||||
} else {
|
||||
tk, err = dec.Token()
|
||||
}
|
||||
if experr, ok := etk.(error); ok {
|
||||
if err == nil || err.Error() != experr.Error() {
|
||||
t.Errorf("case %v: Expected error %v in %q, but was %v", ci, experr, tcase.json, err)
|
||||
}
|
||||
break
|
||||
} else if err == io.EOF {
|
||||
t.Errorf("case %v: Unexpected EOF in %q", ci, tcase.json)
|
||||
break
|
||||
} else if err != nil {
|
||||
t.Errorf("case %v: Unexpected error '%v' in %q", ci, err, tcase.json)
|
||||
break
|
||||
}
|
||||
if !reflect.DeepEqual(tk, etk) {
|
||||
t.Errorf(`case %v: %q @ %v expected %T(%v) was %T(%v)`, ci, tcase.json, i, etk, etk, tk, tk)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Test from golang.org/issue/11893
|
||||
func TestHTTPDecoding(t *testing.T) {
|
||||
const raw = `{ "foo": "bar" }`
|
||||
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte(raw))
|
||||
}))
|
||||
defer ts.Close()
|
||||
res, err := http.Get(ts.URL)
|
||||
if err != nil {
|
||||
log.Fatalf("GET failed: %v", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
foo := struct {
|
||||
Foo string `json:"foo"`
|
||||
}{}
|
||||
|
||||
d := NewDecoder(res.Body)
|
||||
err = d.Decode(&foo)
|
||||
if err != nil {
|
||||
t.Fatalf("Decode: %v", err)
|
||||
}
|
||||
if foo.Foo != "bar" {
|
||||
t.Errorf("decoded %q; want \"bar\"", foo.Foo)
|
||||
}
|
||||
|
||||
// make sure we get the EOF the second time
|
||||
err = d.Decode(&foo)
|
||||
if err != io.EOF {
|
||||
t.Errorf("err = %v; want io.EOF", err)
|
||||
}
|
||||
}
|
||||
115
vendor/gopkg.in/square/go-jose.v2/json/tagkey_test.go
generated
vendored
Normal file
115
vendor/gopkg.in/square/go-jose.v2/json/tagkey_test.go
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type basicLatin2xTag struct {
|
||||
V string `json:"$%-/"`
|
||||
}
|
||||
|
||||
type basicLatin3xTag struct {
|
||||
V string `json:"0123456789"`
|
||||
}
|
||||
|
||||
type basicLatin4xTag struct {
|
||||
V string `json:"ABCDEFGHIJKLMO"`
|
||||
}
|
||||
|
||||
type basicLatin5xTag struct {
|
||||
V string `json:"PQRSTUVWXYZ_"`
|
||||
}
|
||||
|
||||
type basicLatin6xTag struct {
|
||||
V string `json:"abcdefghijklmno"`
|
||||
}
|
||||
|
||||
type basicLatin7xTag struct {
|
||||
V string `json:"pqrstuvwxyz"`
|
||||
}
|
||||
|
||||
type miscPlaneTag struct {
|
||||
V string `json:"色は匂へど"`
|
||||
}
|
||||
|
||||
type percentSlashTag struct {
|
||||
V string `json:"text/html%"` // https://golang.org/issue/2718
|
||||
}
|
||||
|
||||
type punctuationTag struct {
|
||||
V string `json:"!#$%&()*+-./:<=>?@[]^_{|}~"` // https://golang.org/issue/3546
|
||||
}
|
||||
|
||||
type emptyTag struct {
|
||||
W string
|
||||
}
|
||||
|
||||
type misnamedTag struct {
|
||||
X string `jsom:"Misnamed"`
|
||||
}
|
||||
|
||||
type badFormatTag struct {
|
||||
Y string `:"BadFormat"`
|
||||
}
|
||||
|
||||
type badCodeTag struct {
|
||||
Z string `json:" !\"#&'()*+,."`
|
||||
}
|
||||
|
||||
type spaceTag struct {
|
||||
Q string `json:"With space"`
|
||||
}
|
||||
|
||||
type unicodeTag struct {
|
||||
W string `json:"Ελλάδα"`
|
||||
}
|
||||
|
||||
var structTagObjectKeyTests = []struct {
|
||||
raw interface{}
|
||||
value string
|
||||
key string
|
||||
}{
|
||||
{basicLatin2xTag{"2x"}, "2x", "$%-/"},
|
||||
{basicLatin3xTag{"3x"}, "3x", "0123456789"},
|
||||
{basicLatin4xTag{"4x"}, "4x", "ABCDEFGHIJKLMO"},
|
||||
{basicLatin5xTag{"5x"}, "5x", "PQRSTUVWXYZ_"},
|
||||
{basicLatin6xTag{"6x"}, "6x", "abcdefghijklmno"},
|
||||
{basicLatin7xTag{"7x"}, "7x", "pqrstuvwxyz"},
|
||||
{miscPlaneTag{"いろはにほへと"}, "いろはにほへと", "色は匂へど"},
|
||||
{emptyTag{"Pour Moi"}, "Pour Moi", "W"},
|
||||
{misnamedTag{"Animal Kingdom"}, "Animal Kingdom", "X"},
|
||||
{badFormatTag{"Orfevre"}, "Orfevre", "Y"},
|
||||
{badCodeTag{"Reliable Man"}, "Reliable Man", "Z"},
|
||||
{percentSlashTag{"brut"}, "brut", "text/html%"},
|
||||
{punctuationTag{"Union Rags"}, "Union Rags", "!#$%&()*+-./:<=>?@[]^_{|}~"},
|
||||
{spaceTag{"Perreddu"}, "Perreddu", "With space"},
|
||||
{unicodeTag{"Loukanikos"}, "Loukanikos", "Ελλάδα"},
|
||||
}
|
||||
|
||||
func TestStructTagObjectKey(t *testing.T) {
|
||||
for _, tt := range structTagObjectKeyTests {
|
||||
b, err := Marshal(tt.raw)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal(%#q) failed: %v", tt.raw, err)
|
||||
}
|
||||
var f interface{}
|
||||
err = Unmarshal(b, &f)
|
||||
if err != nil {
|
||||
t.Fatalf("Unmarshal(%#q) failed: %v", b, err)
|
||||
}
|
||||
for i, v := range f.(map[string]interface{}) {
|
||||
switch i {
|
||||
case tt.key:
|
||||
if s, ok := v.(string); !ok || s != tt.value {
|
||||
t.Fatalf("Unexpected value: %#q, want %v", s, tt.value)
|
||||
}
|
||||
default:
|
||||
t.Fatalf("Unexpected key: %#q, from %#q", i, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
vendor/gopkg.in/square/go-jose.v2/json/tags.go
generated
vendored
Normal file
44
vendor/gopkg.in/square/go-jose.v2/json/tags.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// tagOptions is the string following a comma in a struct field's "json"
|
||||
// tag, or the empty string. It does not include the leading comma.
|
||||
type tagOptions string
|
||||
|
||||
// parseTag splits a struct field's json tag into its name and
|
||||
// comma-separated options.
|
||||
func parseTag(tag string) (string, tagOptions) {
|
||||
if idx := strings.Index(tag, ","); idx != -1 {
|
||||
return tag[:idx], tagOptions(tag[idx+1:])
|
||||
}
|
||||
return tag, tagOptions("")
|
||||
}
|
||||
|
||||
// Contains reports whether a comma-separated list of options
|
||||
// contains a particular substr flag. substr must be surrounded by a
|
||||
// string boundary or commas.
|
||||
func (o tagOptions) Contains(optionName string) bool {
|
||||
if len(o) == 0 {
|
||||
return false
|
||||
}
|
||||
s := string(o)
|
||||
for s != "" {
|
||||
var next string
|
||||
i := strings.Index(s, ",")
|
||||
if i >= 0 {
|
||||
s, next = s[:i], s[i+1:]
|
||||
}
|
||||
if s == optionName {
|
||||
return true
|
||||
}
|
||||
s = next
|
||||
}
|
||||
return false
|
||||
}
|
||||
28
vendor/gopkg.in/square/go-jose.v2/json/tags_test.go
generated
vendored
Normal file
28
vendor/gopkg.in/square/go-jose.v2/json/tags_test.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTagParsing(t *testing.T) {
|
||||
name, opts := parseTag("field,foobar,foo")
|
||||
if name != "field" {
|
||||
t.Fatalf("name = %q, want field", name)
|
||||
}
|
||||
for _, tt := range []struct {
|
||||
opt string
|
||||
want bool
|
||||
}{
|
||||
{"foobar", true},
|
||||
{"foo", true},
|
||||
{"bar", false},
|
||||
} {
|
||||
if opts.Contains(tt.opt) != tt.want {
|
||||
t.Errorf("Contains(%q) = %v", tt.opt, !tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
vendor/gopkg.in/square/go-jose.v2/json/testdata/code.json.gz
generated
vendored
Normal file
BIN
vendor/gopkg.in/square/go-jose.v2/json/testdata/code.json.gz
generated
vendored
Normal file
Binary file not shown.
Reference in New Issue
Block a user