diff options
author | vitalyisaev <vitalyisaev@ydb.tech> | 2023-12-12 21:55:07 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@ydb.tech> | 2023-12-12 22:25:10 +0300 |
commit | 4967f99474a4040ba150eb04995de06342252718 (patch) | |
tree | c9c118836513a8fab6e9fcfb25be5d404338bca7 /vendor/github.com/aws/smithy-go/encoding/json | |
parent | 2ce9cccb9b0bdd4cd7a3491dc5cbf8687cda51de (diff) | |
download | ydb-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')
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 +) |