aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/aws/smithy-go/encoding/json
diff options
context:
space:
mode:
authorvitalyisaev <vitalyisaev@ydb.tech>2023-12-12 21:55:07 +0300
committervitalyisaev <vitalyisaev@ydb.tech>2023-12-12 22:25:10 +0300
commit4967f99474a4040ba150eb04995de06342252718 (patch)
treec9c118836513a8fab6e9fcfb25be5d404338bca7 /vendor/github.com/aws/smithy-go/encoding/json
parent2ce9cccb9b0bdd4cd7a3491dc5cbf8687cda51de (diff)
downloadydb-4967f99474a4040ba150eb04995de06342252718.tar.gz
YQ Connector: prepare code base for S3 integration
1. Кодовая база Коннектора переписана с помощью Go дженериков так, чтобы добавление нового источника данных (в частности S3 + csv) максимально переиспользовало имеющийся код (чтобы сохранялась логика нарезания на блоки данных, учёт трафика и пр.) 2. API Connector расширено для работы с S3, но ещё пока не протестировано.
Diffstat (limited to 'vendor/github.com/aws/smithy-go/encoding/json')
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/array.go35
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/array_test.go21
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/constants.go15
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go139
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/decoder_util_test.go65
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/encoder.go30
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/encoder_test.go34
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/escape.go198
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/escape_test.go49
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/gotest/ya.make5
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/object.go40
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/object_test.go34
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/value.go149
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/value_test.go156
-rw-r--r--vendor/github.com/aws/smithy-go/encoding/json/ya.make29
15 files changed, 999 insertions, 0 deletions
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/array.go b/vendor/github.com/aws/smithy-go/encoding/json/array.go
new file mode 100644
index 0000000000..7a232f660f
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/array.go
@@ -0,0 +1,35 @@
+package json
+
+import (
+ "bytes"
+)
+
+// Array represents the encoding of a JSON Array
+type Array struct {
+ w *bytes.Buffer
+ writeComma bool
+ scratch *[]byte
+}
+
+func newArray(w *bytes.Buffer, scratch *[]byte) *Array {
+ w.WriteRune(leftBracket)
+ return &Array{w: w, scratch: scratch}
+}
+
+// Value adds a new element to the JSON Array.
+// Returns a Value type that is used to encode
+// the array element.
+func (a *Array) Value() Value {
+ if a.writeComma {
+ a.w.WriteRune(comma)
+ } else {
+ a.writeComma = true
+ }
+
+ return newValue(a.w, a.scratch)
+}
+
+// Close encodes the end of the JSON Array
+func (a *Array) Close() {
+ a.w.WriteRune(rightBracket)
+}
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/array_test.go b/vendor/github.com/aws/smithy-go/encoding/json/array_test.go
new file mode 100644
index 0000000000..072a424129
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/array_test.go
@@ -0,0 +1,21 @@
+package json
+
+import (
+ "bytes"
+ "testing"
+)
+
+func TestArray(t *testing.T) {
+ buffer := bytes.NewBuffer(nil)
+ scratch := make([]byte, 64)
+
+ array := newArray(buffer, &scratch)
+ array.Value().String("bar")
+ array.Value().String("baz")
+ array.Close()
+
+ e := []byte(`["bar","baz"]`)
+ if a := buffer.Bytes(); bytes.Compare(e, a) != 0 {
+ t.Errorf("expected %+q, but got %+q", e, a)
+ }
+}
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/constants.go b/vendor/github.com/aws/smithy-go/encoding/json/constants.go
new file mode 100644
index 0000000000..91044092ae
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/constants.go
@@ -0,0 +1,15 @@
+package json
+
+const (
+ leftBrace = '{'
+ rightBrace = '}'
+
+ leftBracket = '['
+ rightBracket = ']'
+
+ comma = ','
+ quote = '"'
+ colon = ':'
+
+ null = "null"
+)
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go b/vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go
new file mode 100644
index 0000000000..7050c85b3c
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go
@@ -0,0 +1,139 @@
+package json
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+)
+
+// DiscardUnknownField discards unknown fields from a decoder body.
+// This function is useful while deserializing a JSON body with additional
+// unknown information that should be discarded.
+func DiscardUnknownField(decoder *json.Decoder) error {
+ // This deliberately does not share logic with CollectUnknownField, even
+ // though it could, because if we were to delegate to that then we'd incur
+ // extra allocations and general memory usage.
+ v, err := decoder.Token()
+ if err == io.EOF {
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+
+ if _, ok := v.(json.Delim); ok {
+ for decoder.More() {
+ err = DiscardUnknownField(decoder)
+ }
+ endToken, err := decoder.Token()
+ if err != nil {
+ return err
+ }
+ if _, ok := endToken.(json.Delim); !ok {
+ return fmt.Errorf("invalid JSON : expected json delimiter, found %T %v",
+ endToken, endToken)
+ }
+ }
+
+ return nil
+}
+
+// CollectUnknownField grabs the contents of unknown fields from the decoder body
+// and returns them as a byte slice. This is useful for skipping unknown fields without
+// completely discarding them.
+func CollectUnknownField(decoder *json.Decoder) ([]byte, error) {
+ result, err := collectUnknownField(decoder)
+ if err != nil {
+ return nil, err
+ }
+
+ buff := bytes.NewBuffer(nil)
+ encoder := json.NewEncoder(buff)
+
+ if err := encoder.Encode(result); err != nil {
+ return nil, err
+ }
+
+ return buff.Bytes(), nil
+}
+
+func collectUnknownField(decoder *json.Decoder) (interface{}, error) {
+ // Grab the initial value. This could either be a concrete value like a string or a a
+ // delimiter.
+ token, err := decoder.Token()
+ if err == io.EOF {
+ return nil, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ // If it's an array or object, we'll need to recurse.
+ delim, ok := token.(json.Delim)
+ if ok {
+ var result interface{}
+ if delim == '{' {
+ result, err = collectUnknownObject(decoder)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ result, err = collectUnknownArray(decoder)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // Discard the closing token. decoder.Token handles checking for matching delimiters
+ if _, err := decoder.Token(); err != nil {
+ return nil, err
+ }
+ return result, nil
+ }
+
+ return token, nil
+}
+
+func collectUnknownArray(decoder *json.Decoder) ([]interface{}, error) {
+ // We need to create an empty array here instead of a nil array, since by getting
+ // into this function at all we necessarily have seen a non-nil list.
+ array := []interface{}{}
+
+ for decoder.More() {
+ value, err := collectUnknownField(decoder)
+ if err != nil {
+ return nil, err
+ }
+ array = append(array, value)
+ }
+
+ return array, nil
+}
+
+func collectUnknownObject(decoder *json.Decoder) (map[string]interface{}, error) {
+ object := make(map[string]interface{})
+
+ for decoder.More() {
+ key, err := collectUnknownField(decoder)
+ if err != nil {
+ return nil, err
+ }
+
+ // Keys have to be strings, which is particularly important as the encoder
+ // won't except a map with interface{} keys
+ stringKey, ok := key.(string)
+ if !ok {
+ return nil, fmt.Errorf("expected string key, found %T", key)
+ }
+
+ value, err := collectUnknownField(decoder)
+ if err != nil {
+ return nil, err
+ }
+
+ object[stringKey] = value
+ }
+
+ return object, nil
+}
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/decoder_util_test.go b/vendor/github.com/aws/smithy-go/encoding/json/decoder_util_test.go
new file mode 100644
index 0000000000..e4cb38e8b7
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/decoder_util_test.go
@@ -0,0 +1,65 @@
+package json
+
+import (
+ "bytes"
+ "encoding/json"
+ "testing"
+
+ smithytesting "github.com/aws/smithy-go/testing"
+)
+
+func TestDiscardUnknownField(t *testing.T) {
+ cases := map[string][]byte{
+ "empty object": []byte(`{}`),
+ "simple object": []byte(`{"foo": "bar"}`),
+ "nested object": []byte(`{"foo": {"bar": "baz"}}`),
+ "empty list": []byte(`[]`),
+ "simple list": []byte(`["foo", "bar", "baz"]`),
+ "nested list": []byte(`["foo", ["bar", ["baz"]]]`),
+ "number": []byte(`1`),
+ "boolean": []byte(`true`),
+ "null": []byte(`null`),
+ "string": []byte(`"foo"`),
+ }
+
+ for name, c := range cases {
+ t.Run(name, func(t *testing.T) {
+ buff := bytes.NewBuffer(c)
+ decoder := json.NewDecoder(buff)
+ err := DiscardUnknownField(decoder)
+ if err != nil {
+ t.Fatalf("failed to discard, %v", err)
+ }
+ if decoder.More() {
+ t.Fatalf("failed to discard entire contents")
+ }
+ })
+ }
+}
+
+func TestCollectUnknownField(t *testing.T) {
+ cases := map[string][]byte{
+ "empty object": []byte(`{}`),
+ "simple object": []byte(`{"foo": "bar"}`),
+ "nested object": []byte(`{"foo": {"bar": "baz"}}`),
+ "empty list": []byte(`[]`),
+ "simple list": []byte(`["foo", "bar", "baz"]`),
+ "nested list": []byte(`["foo", ["bar", ["baz"]]]`),
+ "number": []byte(`1`),
+ "boolean": []byte(`true`),
+ "null": []byte(`null`),
+ "string": []byte(`"foo"`),
+ }
+
+ for name, c := range cases {
+ t.Run(name, func(t *testing.T) {
+ buff := bytes.NewBuffer(c)
+ decoder := json.NewDecoder(buff)
+ actual, err := CollectUnknownField(decoder)
+ if err != nil {
+ t.Fatalf("failed to collect, %v", err)
+ }
+ smithytesting.AssertJSONEqual(t, c, actual)
+ })
+ }
+}
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/encoder.go b/vendor/github.com/aws/smithy-go/encoding/json/encoder.go
new file mode 100644
index 0000000000..8772953f1e
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/encoder.go
@@ -0,0 +1,30 @@
+package json
+
+import (
+ "bytes"
+)
+
+// Encoder is JSON encoder that supports construction of JSON values
+// using methods.
+type Encoder struct {
+ w *bytes.Buffer
+ Value
+}
+
+// NewEncoder returns a new JSON encoder
+func NewEncoder() *Encoder {
+ writer := bytes.NewBuffer(nil)
+ scratch := make([]byte, 64)
+
+ return &Encoder{w: writer, Value: newValue(writer, &scratch)}
+}
+
+// String returns the String output of the JSON encoder
+func (e Encoder) String() string {
+ return e.w.String()
+}
+
+// Bytes returns the []byte slice of the JSON encoder
+func (e Encoder) Bytes() []byte {
+ return e.w.Bytes()
+}
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/encoder_test.go b/vendor/github.com/aws/smithy-go/encoding/json/encoder_test.go
new file mode 100644
index 0000000000..d9fbd4ba82
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/encoder_test.go
@@ -0,0 +1,34 @@
+package json_test
+
+import (
+ "bytes"
+ "testing"
+
+ "github.com/aws/smithy-go/encoding/json"
+)
+
+func TestEncoder(t *testing.T) {
+ encoder := json.NewEncoder()
+
+ object := encoder.Object()
+
+ object.Key("stringKey").String("stringValue")
+ object.Key("integerKey").Long(1024)
+ object.Key("floatKey").Double(3.14)
+
+ subObj := object.Key("foo").Object()
+
+ subObj.Key("byteSlice").Base64EncodeBytes([]byte("foo bar"))
+ subObj.Close()
+
+ object.Close()
+
+ e := []byte(`{"stringKey":"stringValue","integerKey":1024,"floatKey":3.14,"foo":{"byteSlice":"Zm9vIGJhcg=="}}`)
+ if a := encoder.Bytes(); bytes.Compare(e, a) != 0 {
+ t.Errorf("expected %+q, but got %+q", e, a)
+ }
+
+ if a := encoder.String(); string(e) != a {
+ t.Errorf("expected %s, but got %s", e, a)
+ }
+}
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/escape.go b/vendor/github.com/aws/smithy-go/encoding/json/escape.go
new file mode 100644
index 0000000000..d984d0cdca
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/escape.go
@@ -0,0 +1,198 @@
+// Copyright 2016 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.
+
+// Copied and modified from Go 1.8 stdlib's encoding/json/#safeSet
+
+package json
+
+import (
+ "bytes"
+ "unicode/utf8"
+)
+
+// safeSet holds the value true if the ASCII character with the given array
+// position can be represented inside a JSON string without any further
+// escaping.
+//
+// All values are true except for the ASCII control characters (0-31), the
+// double quote ("), and the backslash character ("\").
+var safeSet = [utf8.RuneSelf]bool{
+ ' ': true,
+ '!': true,
+ '"': false,
+ '#': true,
+ '$': true,
+ '%': true,
+ '&': true,
+ '\'': true,
+ '(': true,
+ ')': true,
+ '*': true,
+ '+': true,
+ ',': true,
+ '-': true,
+ '.': true,
+ '/': true,
+ '0': true,
+ '1': true,
+ '2': true,
+ '3': true,
+ '4': true,
+ '5': true,
+ '6': true,
+ '7': true,
+ '8': true,
+ '9': true,
+ ':': true,
+ ';': true,
+ '<': true,
+ '=': true,
+ '>': true,
+ '?': true,
+ '@': true,
+ 'A': true,
+ 'B': true,
+ 'C': true,
+ 'D': true,
+ 'E': true,
+ 'F': true,
+ 'G': true,
+ 'H': true,
+ 'I': true,
+ 'J': true,
+ 'K': true,
+ 'L': true,
+ 'M': true,
+ 'N': true,
+ 'O': true,
+ 'P': true,
+ 'Q': true,
+ 'R': true,
+ 'S': true,
+ 'T': true,
+ 'U': true,
+ 'V': true,
+ 'W': true,
+ 'X': true,
+ 'Y': true,
+ 'Z': true,
+ '[': true,
+ '\\': false,
+ ']': true,
+ '^': true,
+ '_': true,
+ '`': true,
+ 'a': true,
+ 'b': true,
+ 'c': true,
+ 'd': true,
+ 'e': true,
+ 'f': true,
+ 'g': true,
+ 'h': true,
+ 'i': true,
+ 'j': true,
+ 'k': true,
+ 'l': true,
+ 'm': true,
+ 'n': true,
+ 'o': true,
+ 'p': true,
+ 'q': true,
+ 'r': true,
+ 's': true,
+ 't': true,
+ 'u': true,
+ 'v': true,
+ 'w': true,
+ 'x': true,
+ 'y': true,
+ 'z': true,
+ '{': true,
+ '|': true,
+ '}': true,
+ '~': true,
+ '\u007f': true,
+}
+
+// copied from Go 1.8 stdlib's encoding/json/#hex
+var hex = "0123456789abcdef"
+
+// escapeStringBytes escapes and writes the passed in string bytes to the dst
+// buffer
+//
+// Copied and modifed from Go 1.8 stdlib's encodeing/json/#encodeState.stringBytes
+func escapeStringBytes(e *bytes.Buffer, s []byte) {
+ e.WriteByte('"')
+ start := 0
+ for i := 0; i < len(s); {
+ if b := s[i]; b < utf8.RuneSelf {
+ if safeSet[b] {
+ i++
+ continue
+ }
+ if start < i {
+ e.Write(s[start:i])
+ }
+ switch b {
+ case '\\', '"':
+ e.WriteByte('\\')
+ e.WriteByte(b)
+ case '\n':
+ e.WriteByte('\\')
+ e.WriteByte('n')
+ case '\r':
+ e.WriteByte('\\')
+ e.WriteByte('r')
+ case '\t':
+ e.WriteByte('\\')
+ e.WriteByte('t')
+ default:
+ // This encodes bytes < 0x20 except for \t, \n and \r.
+ // If escapeHTML is set, it also escapes <, >, and &
+ // because they can lead to security holes when
+ // user-controlled strings are rendered into JSON
+ // and served to some browsers.
+ e.WriteString(`\u00`)
+ e.WriteByte(hex[b>>4])
+ e.WriteByte(hex[b&0xF])
+ }
+ i++
+ start = i
+ continue
+ }
+ c, size := utf8.DecodeRune(s[i:])
+ if c == utf8.RuneError && size == 1 {
+ if start < i {
+ e.Write(s[start:i])
+ }
+ e.WriteString(`\ufffd`)
+ i += size
+ start = i
+ continue
+ }
+ // U+2028 is LINE SEPARATOR.
+ // U+2029 is PARAGRAPH SEPARATOR.
+ // They are both technically valid characters in JSON strings,
+ // but don't work in JSONP, which has to be evaluated as JavaScript,
+ // and can lead to security holes there. It is valid JSON to
+ // escape them, so we do so unconditionally.
+ // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
+ if c == '\u2028' || c == '\u2029' {
+ if start < i {
+ e.Write(s[start:i])
+ }
+ e.WriteString(`\u202`)
+ e.WriteByte(hex[c&0xF])
+ i += size
+ start = i
+ continue
+ }
+ i += size
+ }
+ if start < len(s) {
+ e.Write(s[start:])
+ }
+ e.WriteByte('"')
+}
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/escape_test.go b/vendor/github.com/aws/smithy-go/encoding/json/escape_test.go
new file mode 100644
index 0000000000..c3a07a1260
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/escape_test.go
@@ -0,0 +1,49 @@
+package json
+
+import (
+ "bytes"
+ "testing"
+)
+
+func TestEscapeStringBytes(t *testing.T) {
+ cases := map[string]struct {
+ expected string
+ input []byte
+ }{
+ "safeSet only": {
+ expected: `"mountainPotato"`,
+ input: []byte("mountainPotato"),
+ },
+ "parenthesis": {
+ expected: `"foo\""`,
+ input: []byte(`foo"`),
+ },
+ "double escape": {
+ expected: `"hello\\\\world"`,
+ input: []byte(`hello\\world`),
+ },
+ "new line": {
+ expected: `"foo\nbar"`,
+ input: []byte("foo\nbar"),
+ },
+ "carriage return": {
+ expected: `"foo\rbar"`,
+ input: []byte("foo\rbar"),
+ },
+ "tab": {
+ expected: `"foo\tbar"`,
+ input: []byte("foo\tbar"),
+ },
+ }
+ for name, c := range cases {
+ t.Run(name, func(t *testing.T) {
+ var buffer bytes.Buffer
+ escapeStringBytes(&buffer, c.input)
+ expected := c.expected
+ actual := buffer.String()
+ if expected != actual {
+ t.Errorf("\nexpected %v \nactual %v", expected, actual)
+ }
+ })
+ }
+}
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/gotest/ya.make b/vendor/github.com/aws/smithy-go/encoding/json/gotest/ya.make
new file mode 100644
index 0000000000..8ae1b85797
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/gotest/ya.make
@@ -0,0 +1,5 @@
+GO_TEST_FOR(vendor/github.com/aws/smithy-go/encoding/json)
+
+LICENSE(Apache-2.0)
+
+END()
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/object.go b/vendor/github.com/aws/smithy-go/encoding/json/object.go
new file mode 100644
index 0000000000..722346d035
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/object.go
@@ -0,0 +1,40 @@
+package json
+
+import (
+ "bytes"
+)
+
+// Object represents the encoding of a JSON Object type
+type Object struct {
+ w *bytes.Buffer
+ writeComma bool
+ scratch *[]byte
+}
+
+func newObject(w *bytes.Buffer, scratch *[]byte) *Object {
+ w.WriteRune(leftBrace)
+ return &Object{w: w, scratch: scratch}
+}
+
+func (o *Object) writeKey(key string) {
+ escapeStringBytes(o.w, []byte(key))
+ o.w.WriteRune(colon)
+}
+
+// Key adds the given named key to the JSON object.
+// Returns a Value encoder that should be used to encode
+// a JSON value type.
+func (o *Object) Key(name string) Value {
+ if o.writeComma {
+ o.w.WriteRune(comma)
+ } else {
+ o.writeComma = true
+ }
+ o.writeKey(name)
+ return newValue(o.w, o.scratch)
+}
+
+// Close encodes the end of the JSON Object
+func (o *Object) Close() {
+ o.w.WriteRune(rightBrace)
+}
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/object_test.go b/vendor/github.com/aws/smithy-go/encoding/json/object_test.go
new file mode 100644
index 0000000000..1e0830e052
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/object_test.go
@@ -0,0 +1,34 @@
+package json
+
+import (
+ "bytes"
+ "testing"
+)
+
+func TestObject(t *testing.T) {
+ buffer := bytes.NewBuffer(nil)
+ scratch := make([]byte, 64)
+
+ object := newObject(buffer, &scratch)
+ object.Key("foo").String("bar")
+ object.Key("faz").String("baz")
+ object.Close()
+
+ e := []byte(`{"foo":"bar","faz":"baz"}`)
+ if a := buffer.Bytes(); bytes.Compare(e, a) != 0 {
+ t.Errorf("expected %+q, but got %+q", e, a)
+ }
+}
+
+func TestObjectKey_escaped(t *testing.T) {
+ jsonEncoder := NewEncoder()
+ object := jsonEncoder.Object()
+ object.Key("foo\"").String("bar")
+ object.Key("faz").String("baz")
+ object.Close()
+
+ e := []byte(`{"foo\"":"bar","faz":"baz"}`)
+ if a := object.w.Bytes(); bytes.Compare(e, a) != 0 {
+ t.Errorf("expected %+q, but got %+q", e, a)
+ }
+}
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/value.go b/vendor/github.com/aws/smithy-go/encoding/json/value.go
new file mode 100644
index 0000000000..b41ff1e15c
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/value.go
@@ -0,0 +1,149 @@
+package json
+
+import (
+ "bytes"
+ "encoding/base64"
+ "math/big"
+ "strconv"
+
+ "github.com/aws/smithy-go/encoding"
+)
+
+// Value represents a JSON Value type
+// JSON Value types: Object, Array, String, Number, Boolean, and Null
+type Value struct {
+ w *bytes.Buffer
+ scratch *[]byte
+}
+
+// newValue returns a new Value encoder
+func newValue(w *bytes.Buffer, scratch *[]byte) Value {
+ return Value{w: w, scratch: scratch}
+}
+
+// String encodes v as a JSON string
+func (jv Value) String(v string) {
+ escapeStringBytes(jv.w, []byte(v))
+}
+
+// Byte encodes v as a JSON number
+func (jv Value) Byte(v int8) {
+ jv.Long(int64(v))
+}
+
+// Short encodes v as a JSON number
+func (jv Value) Short(v int16) {
+ jv.Long(int64(v))
+}
+
+// Integer encodes v as a JSON number
+func (jv Value) Integer(v int32) {
+ jv.Long(int64(v))
+}
+
+// Long encodes v as a JSON number
+func (jv Value) Long(v int64) {
+ *jv.scratch = strconv.AppendInt((*jv.scratch)[:0], v, 10)
+ jv.w.Write(*jv.scratch)
+}
+
+// ULong encodes v as a JSON number
+func (jv Value) ULong(v uint64) {
+ *jv.scratch = strconv.AppendUint((*jv.scratch)[:0], v, 10)
+ jv.w.Write(*jv.scratch)
+}
+
+// Float encodes v as a JSON number
+func (jv Value) Float(v float32) {
+ jv.float(float64(v), 32)
+}
+
+// Double encodes v as a JSON number
+func (jv Value) Double(v float64) {
+ jv.float(v, 64)
+}
+
+func (jv Value) float(v float64, bits int) {
+ *jv.scratch = encoding.EncodeFloat((*jv.scratch)[:0], v, bits)
+ jv.w.Write(*jv.scratch)
+}
+
+// Boolean encodes v as a JSON boolean
+func (jv Value) Boolean(v bool) {
+ *jv.scratch = strconv.AppendBool((*jv.scratch)[:0], v)
+ jv.w.Write(*jv.scratch)
+}
+
+// Base64EncodeBytes writes v as a base64 value in JSON string
+func (jv Value) Base64EncodeBytes(v []byte) {
+ encodeByteSlice(jv.w, (*jv.scratch)[:0], v)
+}
+
+// Write writes v directly to the JSON document
+func (jv Value) Write(v []byte) {
+ jv.w.Write(v)
+}
+
+// Array returns a new Array encoder
+func (jv Value) Array() *Array {
+ return newArray(jv.w, jv.scratch)
+}
+
+// Object returns a new Object encoder
+func (jv Value) Object() *Object {
+ return newObject(jv.w, jv.scratch)
+}
+
+// Null encodes a null JSON value
+func (jv Value) Null() {
+ jv.w.WriteString(null)
+}
+
+// BigInteger encodes v as JSON value
+func (jv Value) BigInteger(v *big.Int) {
+ jv.w.Write([]byte(v.Text(10)))
+}
+
+// BigDecimal encodes v as JSON value
+func (jv Value) BigDecimal(v *big.Float) {
+ if i, accuracy := v.Int64(); accuracy == big.Exact {
+ jv.Long(i)
+ return
+ }
+ // TODO: Should this try to match ES6 ToString similar to stdlib JSON?
+ jv.w.Write([]byte(v.Text('e', -1)))
+}
+
+// Based on encoding/json encodeByteSlice from the Go Standard Library
+// https://golang.org/src/encoding/json/encode.go
+func encodeByteSlice(w *bytes.Buffer, scratch []byte, v []byte) {
+ if v == nil {
+ w.WriteString(null)
+ return
+ }
+
+ w.WriteRune(quote)
+
+ encodedLen := base64.StdEncoding.EncodedLen(len(v))
+ if encodedLen <= len(scratch) {
+ // If the encoded bytes fit in e.scratch, avoid an extra
+ // allocation and use the cheaper Encoding.Encode.
+ dst := scratch[:encodedLen]
+ base64.StdEncoding.Encode(dst, v)
+ w.Write(dst)
+ } else if encodedLen <= 1024 {
+ // The encoded bytes are short enough to allocate for, and
+ // Encoding.Encode is still cheaper.
+ dst := make([]byte, encodedLen)
+ base64.StdEncoding.Encode(dst, v)
+ w.Write(dst)
+ } else {
+ // The encoded bytes are too long to cheaply allocate, and
+ // Encoding.Encode is no longer noticeably cheaper.
+ enc := base64.NewEncoder(base64.StdEncoding, w)
+ enc.Write(v)
+ enc.Close()
+ }
+
+ w.WriteRune(quote)
+}
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/value_test.go b/vendor/github.com/aws/smithy-go/encoding/json/value_test.go
new file mode 100644
index 0000000000..29f0cc562c
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/value_test.go
@@ -0,0 +1,156 @@
+package json
+
+import (
+ "bytes"
+ "math"
+ "math/big"
+ "strconv"
+ "testing"
+)
+
+var (
+ oneInt = new(big.Int).SetInt64(1)
+ oneFloat = new(big.Float).SetFloat64(1.0)
+)
+
+func TestValue(t *testing.T) {
+ cases := map[string]struct {
+ setter func(Value)
+ expected string
+ }{
+ "string value": {
+ setter: func(value Value) {
+ value.String("foo")
+ },
+ expected: `"foo"`,
+ },
+ "string escaped": {
+ setter: func(value Value) {
+ value.String(`{"foo":"bar"}`)
+ },
+ expected: `"{\"foo\":\"bar\"}"`,
+ },
+ "integer": {
+ setter: func(value Value) {
+ value.Long(1024)
+ },
+ expected: `1024`,
+ },
+ "float": {
+ setter: func(value Value) {
+ value.Double(1e20)
+ },
+ expected: `100000000000000000000`,
+ },
+ "float exponent component": {
+ setter: func(value Value) {
+ value.Double(3e22)
+ },
+ expected: `3e+22`,
+ },
+ "boolean true": {
+ setter: func(value Value) {
+ value.Boolean(true)
+ },
+ expected: `true`,
+ },
+ "boolean false": {
+ setter: func(value Value) {
+ value.Boolean(false)
+ },
+ expected: `false`,
+ },
+ "encode bytes": {
+ setter: func(value Value) {
+ value.Base64EncodeBytes([]byte("foo bar"))
+ },
+ expected: `"Zm9vIGJhcg=="`,
+ },
+ "encode bytes nil": {
+ setter: func(value Value) {
+ value.Base64EncodeBytes(nil)
+ },
+ expected: `null`,
+ },
+ "object": {
+ setter: func(value Value) {
+ o := value.Object()
+ defer o.Close()
+ o.Key("key").String("value")
+ },
+ expected: `{"key":"value"}`,
+ },
+ "array": {
+ setter: func(value Value) {
+ o := value.Array()
+ defer o.Close()
+ o.Value().String("value1")
+ o.Value().String("value2")
+ },
+ expected: `["value1","value2"]`,
+ },
+ "null": {
+ setter: func(value Value) {
+ value.Null()
+ },
+ expected: `null`,
+ },
+ "write bytes": {
+ setter: func(value Value) {
+ o := value.Object()
+ o.Key("inline").Write([]byte(`{"nested":"value"}`))
+ defer o.Close()
+ },
+ expected: `{"inline":{"nested":"value"}}`,
+ },
+ "bigInteger": {
+ setter: func(value Value) {
+ v := new(big.Int).SetInt64(math.MaxInt64)
+ value.BigInteger(v.Sub(v, oneInt))
+ },
+ expected: strconv.FormatInt(math.MaxInt64-1, 10),
+ },
+ "bigInteger > int64": {
+ setter: func(value Value) {
+ v := new(big.Int).SetInt64(math.MaxInt64)
+ value.BigInteger(v.Add(v, oneInt))
+ },
+ expected: "9223372036854775808",
+ },
+ "bigInteger < int64": {
+ setter: func(value Value) {
+ v := new(big.Int).SetInt64(math.MinInt64)
+ value.BigInteger(v.Sub(v, oneInt))
+ },
+ expected: "-9223372036854775809",
+ },
+ "bigFloat": {
+ setter: func(value Value) {
+ v := new(big.Float).SetFloat64(math.MaxFloat64)
+ value.BigDecimal(v.Sub(v, oneFloat))
+ },
+ expected: strconv.FormatFloat(math.MaxFloat64-1, 'e', -1, 64),
+ },
+ "bigFloat fits in int64": {
+ setter: func(value Value) {
+ v := new(big.Float).SetInt64(math.MaxInt64)
+ value.BigDecimal(v)
+ },
+ expected: "9223372036854775807",
+ },
+ }
+ scratch := make([]byte, 64)
+
+ for name, tt := range cases {
+ t.Run(name, func(t *testing.T) {
+ var b bytes.Buffer
+ value := newValue(&b, &scratch)
+
+ tt.setter(value)
+
+ if e, a := []byte(tt.expected), b.Bytes(); bytes.Compare(e, a) != 0 {
+ t.Errorf("expected %+q, but got %+q", e, a)
+ }
+ })
+ }
+}
diff --git a/vendor/github.com/aws/smithy-go/encoding/json/ya.make b/vendor/github.com/aws/smithy-go/encoding/json/ya.make
new file mode 100644
index 0000000000..f43773b0d8
--- /dev/null
+++ b/vendor/github.com/aws/smithy-go/encoding/json/ya.make
@@ -0,0 +1,29 @@
+GO_LIBRARY()
+
+LICENSE(Apache-2.0)
+
+SRCS(
+ array.go
+ constants.go
+ decoder_util.go
+ encoder.go
+ escape.go
+ object.go
+ value.go
+)
+
+GO_TEST_SRCS(
+ array_test.go
+ decoder_util_test.go
+ escape_test.go
+ object_test.go
+ value_test.go
+)
+
+GO_XTEST_SRCS(encoder_test.go)
+
+END()
+
+RECURSE(
+ gotest
+)