feat(train): add new command to interact with aws and train models
This commit is contained in:
4
vendor/github.com/aws/smithy-go/encoding/doc.go
generated
vendored
Normal file
4
vendor/github.com/aws/smithy-go/encoding/doc.go
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
// Package encoding provides utilities for encoding values for specific
|
||||
// document encodings.
|
||||
|
||||
package encoding
|
40
vendor/github.com/aws/smithy-go/encoding/encoding.go
generated
vendored
Normal file
40
vendor/github.com/aws/smithy-go/encoding/encoding.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// EncodeFloat encodes a float value as per the stdlib encoder for json and xml protocol
|
||||
// This encodes a float value into dst while attempting to conform to ES6 ToString for Numbers
|
||||
//
|
||||
// Based on encoding/json floatEncoder from the Go Standard Library
|
||||
// https://golang.org/src/encoding/json/encode.go
|
||||
func EncodeFloat(dst []byte, v float64, bits int) []byte {
|
||||
if math.IsInf(v, 0) || math.IsNaN(v) {
|
||||
panic(fmt.Sprintf("invalid float value: %s", strconv.FormatFloat(v, 'g', -1, bits)))
|
||||
}
|
||||
|
||||
abs := math.Abs(v)
|
||||
fmt := byte('f')
|
||||
|
||||
if abs != 0 {
|
||||
if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
|
||||
fmt = 'e'
|
||||
}
|
||||
}
|
||||
|
||||
dst = strconv.AppendFloat(dst, v, fmt, -1, bits)
|
||||
|
||||
if fmt == 'e' {
|
||||
// clean up e-09 to e-9
|
||||
n := len(dst)
|
||||
if n >= 4 && dst[n-4] == 'e' && dst[n-3] == '-' && dst[n-2] == '0' {
|
||||
dst[n-2] = dst[n-1]
|
||||
dst = dst[:n-1]
|
||||
}
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
116
vendor/github.com/aws/smithy-go/encoding/httpbinding/encode.go
generated
vendored
Normal file
116
vendor/github.com/aws/smithy-go/encoding/httpbinding/encode.go
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
package httpbinding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
contentLengthHeader = "Content-Length"
|
||||
floatNaN = "NaN"
|
||||
floatInfinity = "Infinity"
|
||||
floatNegInfinity = "-Infinity"
|
||||
)
|
||||
|
||||
// An Encoder provides encoding of REST URI path, query, and header components
|
||||
// of an HTTP request. Can also encode a stream as the payload.
|
||||
//
|
||||
// Does not support SetFields.
|
||||
type Encoder struct {
|
||||
path, rawPath, pathBuffer []byte
|
||||
|
||||
query url.Values
|
||||
header http.Header
|
||||
}
|
||||
|
||||
// NewEncoder creates a new encoder from the passed in request. All query and
|
||||
// header values will be added on top of the request's existing values. Overwriting
|
||||
// duplicate values.
|
||||
func NewEncoder(path, query string, headers http.Header) (*Encoder, error) {
|
||||
parseQuery, err := url.ParseQuery(query)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse query string: %w", err)
|
||||
}
|
||||
|
||||
e := &Encoder{
|
||||
path: []byte(path),
|
||||
rawPath: []byte(path),
|
||||
query: parseQuery,
|
||||
header: headers.Clone(),
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// Encode returns a REST protocol encoder for encoding HTTP bindings.
|
||||
//
|
||||
// Due net/http requiring `Content-Length` to be specified on the http.Request#ContentLength directly. Encode
|
||||
// will look for whether the header is present, and if so will remove it and set the respective value on http.Request.
|
||||
//
|
||||
// Returns any error if one occurred during encoding.
|
||||
func (e *Encoder) Encode(req *http.Request) (*http.Request, error) {
|
||||
req.URL.Path, req.URL.RawPath = string(e.path), string(e.rawPath)
|
||||
req.URL.RawQuery = e.query.Encode()
|
||||
|
||||
// net/http ignores Content-Length header and requires it to be set on http.Request
|
||||
if v := e.header.Get(contentLengthHeader); len(v) > 0 {
|
||||
iv, err := strconv.ParseInt(v, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.ContentLength = iv
|
||||
e.header.Del(contentLengthHeader)
|
||||
}
|
||||
|
||||
req.Header = e.header
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// AddHeader returns a HeaderValue for appending to the given header name
|
||||
func (e *Encoder) AddHeader(key string) HeaderValue {
|
||||
return newHeaderValue(e.header, key, true)
|
||||
}
|
||||
|
||||
// SetHeader returns a HeaderValue for setting the given header name
|
||||
func (e *Encoder) SetHeader(key string) HeaderValue {
|
||||
return newHeaderValue(e.header, key, false)
|
||||
}
|
||||
|
||||
// Headers returns a Header used encoding headers with the given prefix
|
||||
func (e *Encoder) Headers(prefix string) Headers {
|
||||
return Headers{
|
||||
header: e.header,
|
||||
prefix: strings.TrimSpace(prefix),
|
||||
}
|
||||
}
|
||||
|
||||
// HasHeader returns if a header with the key specified exists with one or
|
||||
// more value.
|
||||
func (e Encoder) HasHeader(key string) bool {
|
||||
return len(e.header[key]) != 0
|
||||
}
|
||||
|
||||
// SetURI returns a URIValue used for setting the given path key
|
||||
func (e *Encoder) SetURI(key string) URIValue {
|
||||
return newURIValue(&e.path, &e.rawPath, &e.pathBuffer, key)
|
||||
}
|
||||
|
||||
// SetQuery returns a QueryValue used for setting the given query key
|
||||
func (e *Encoder) SetQuery(key string) QueryValue {
|
||||
return NewQueryValue(e.query, key, false)
|
||||
}
|
||||
|
||||
// AddQuery returns a QueryValue used for appending the given query key
|
||||
func (e *Encoder) AddQuery(key string) QueryValue {
|
||||
return NewQueryValue(e.query, key, true)
|
||||
}
|
||||
|
||||
// HasQuery returns if a query with the key specified exists with one or
|
||||
// more value.
|
||||
func (e *Encoder) HasQuery(key string) bool {
|
||||
return len(e.query.Get(key)) != 0
|
||||
}
|
122
vendor/github.com/aws/smithy-go/encoding/httpbinding/header.go
generated
vendored
Normal file
122
vendor/github.com/aws/smithy-go/encoding/httpbinding/header.go
generated
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
package httpbinding
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"math"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Headers is used to encode header keys using a provided prefix
|
||||
type Headers struct {
|
||||
header http.Header
|
||||
prefix string
|
||||
}
|
||||
|
||||
// AddHeader returns a HeaderValue used to append values to prefix+key
|
||||
func (h Headers) AddHeader(key string) HeaderValue {
|
||||
return h.newHeaderValue(key, true)
|
||||
}
|
||||
|
||||
// SetHeader returns a HeaderValue used to set the value of prefix+key
|
||||
func (h Headers) SetHeader(key string) HeaderValue {
|
||||
return h.newHeaderValue(key, false)
|
||||
}
|
||||
|
||||
func (h Headers) newHeaderValue(key string, append bool) HeaderValue {
|
||||
return newHeaderValue(h.header, h.prefix+strings.TrimSpace(key), append)
|
||||
}
|
||||
|
||||
// HeaderValue is used to encode values to an HTTP header
|
||||
type HeaderValue struct {
|
||||
header http.Header
|
||||
key string
|
||||
append bool
|
||||
}
|
||||
|
||||
func newHeaderValue(header http.Header, key string, append bool) HeaderValue {
|
||||
return HeaderValue{header: header, key: strings.TrimSpace(key), append: append}
|
||||
}
|
||||
|
||||
func (h HeaderValue) modifyHeader(value string) {
|
||||
if h.append {
|
||||
h.header[h.key] = append(h.header[h.key], value)
|
||||
} else {
|
||||
h.header[h.key] = append(h.header[h.key][:0], value)
|
||||
}
|
||||
}
|
||||
|
||||
// String encodes the value v as the header string value
|
||||
func (h HeaderValue) String(v string) {
|
||||
h.modifyHeader(v)
|
||||
}
|
||||
|
||||
// Byte encodes the value v as a query string value
|
||||
func (h HeaderValue) Byte(v int8) {
|
||||
h.Long(int64(v))
|
||||
}
|
||||
|
||||
// Short encodes the value v as a query string value
|
||||
func (h HeaderValue) Short(v int16) {
|
||||
h.Long(int64(v))
|
||||
}
|
||||
|
||||
// Integer encodes the value v as the header string value
|
||||
func (h HeaderValue) Integer(v int32) {
|
||||
h.Long(int64(v))
|
||||
}
|
||||
|
||||
// Long encodes the value v as the header string value
|
||||
func (h HeaderValue) Long(v int64) {
|
||||
h.modifyHeader(strconv.FormatInt(v, 10))
|
||||
}
|
||||
|
||||
// Boolean encodes the value v as a query string value
|
||||
func (h HeaderValue) Boolean(v bool) {
|
||||
h.modifyHeader(strconv.FormatBool(v))
|
||||
}
|
||||
|
||||
// Float encodes the value v as a query string value
|
||||
func (h HeaderValue) Float(v float32) {
|
||||
h.float(float64(v), 32)
|
||||
}
|
||||
|
||||
// Double encodes the value v as a query string value
|
||||
func (h HeaderValue) Double(v float64) {
|
||||
h.float(v, 64)
|
||||
}
|
||||
|
||||
func (h HeaderValue) float(v float64, bitSize int) {
|
||||
switch {
|
||||
case math.IsNaN(v):
|
||||
h.String(floatNaN)
|
||||
case math.IsInf(v, 1):
|
||||
h.String(floatInfinity)
|
||||
case math.IsInf(v, -1):
|
||||
h.String(floatNegInfinity)
|
||||
default:
|
||||
h.modifyHeader(strconv.FormatFloat(v, 'f', -1, bitSize))
|
||||
}
|
||||
}
|
||||
|
||||
// BigInteger encodes the value v as a query string value
|
||||
func (h HeaderValue) BigInteger(v *big.Int) {
|
||||
h.modifyHeader(v.String())
|
||||
}
|
||||
|
||||
// BigDecimal encodes the value v as a query string value
|
||||
func (h HeaderValue) BigDecimal(v *big.Float) {
|
||||
if i, accuracy := v.Int64(); accuracy == big.Exact {
|
||||
h.Long(i)
|
||||
return
|
||||
}
|
||||
h.modifyHeader(v.Text('e', -1))
|
||||
}
|
||||
|
||||
// Blob encodes the value v as a base64 header string value
|
||||
func (h HeaderValue) Blob(v []byte) {
|
||||
encodeToString := base64.StdEncoding.EncodeToString(v)
|
||||
h.modifyHeader(encodeToString)
|
||||
}
|
108
vendor/github.com/aws/smithy-go/encoding/httpbinding/path_replace.go
generated
vendored
Normal file
108
vendor/github.com/aws/smithy-go/encoding/httpbinding/path_replace.go
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
package httpbinding
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
uriTokenStart = '{'
|
||||
uriTokenStop = '}'
|
||||
uriTokenSkip = '+'
|
||||
)
|
||||
|
||||
func bufCap(b []byte, n int) []byte {
|
||||
if cap(b) < n {
|
||||
return make([]byte, 0, n)
|
||||
}
|
||||
|
||||
return b[0:0]
|
||||
}
|
||||
|
||||
// replacePathElement replaces a single element in the path []byte.
|
||||
// Escape is used to control whether the value will be escaped using Amazon path escape style.
|
||||
func replacePathElement(path, fieldBuf []byte, key, val string, escape bool) ([]byte, []byte, error) {
|
||||
fieldBuf = bufCap(fieldBuf, len(key)+3) // { <key> [+] }
|
||||
fieldBuf = append(fieldBuf, uriTokenStart)
|
||||
fieldBuf = append(fieldBuf, key...)
|
||||
|
||||
start := bytes.Index(path, fieldBuf)
|
||||
end := start + len(fieldBuf)
|
||||
if start < 0 || len(path[end:]) == 0 {
|
||||
// TODO what to do about error?
|
||||
return path, fieldBuf, fmt.Errorf("invalid path index, start=%d,end=%d. %s", start, end, path)
|
||||
}
|
||||
|
||||
encodeSep := true
|
||||
if path[end] == uriTokenSkip {
|
||||
// '+' token means do not escape slashes
|
||||
encodeSep = false
|
||||
end++
|
||||
}
|
||||
|
||||
if escape {
|
||||
val = EscapePath(val, encodeSep)
|
||||
}
|
||||
|
||||
if path[end] != uriTokenStop {
|
||||
return path, fieldBuf, fmt.Errorf("invalid path element, does not contain token stop, %s", path)
|
||||
}
|
||||
end++
|
||||
|
||||
fieldBuf = bufCap(fieldBuf, len(val))
|
||||
fieldBuf = append(fieldBuf, val...)
|
||||
|
||||
keyLen := end - start
|
||||
valLen := len(fieldBuf)
|
||||
|
||||
if keyLen == valLen {
|
||||
copy(path[start:], fieldBuf)
|
||||
return path, fieldBuf, nil
|
||||
}
|
||||
|
||||
newLen := len(path) + (valLen - keyLen)
|
||||
if len(path) < newLen {
|
||||
path = path[:cap(path)]
|
||||
}
|
||||
if cap(path) < newLen {
|
||||
newURI := make([]byte, newLen)
|
||||
copy(newURI, path)
|
||||
path = newURI
|
||||
}
|
||||
|
||||
// shift
|
||||
copy(path[start+valLen:], path[end:])
|
||||
path = path[:newLen]
|
||||
copy(path[start:], fieldBuf)
|
||||
|
||||
return path, fieldBuf, nil
|
||||
}
|
||||
|
||||
// EscapePath escapes part of a URL path in Amazon style.
|
||||
func EscapePath(path string, encodeSep bool) string {
|
||||
var buf bytes.Buffer
|
||||
for i := 0; i < len(path); i++ {
|
||||
c := path[i]
|
||||
if noEscape[c] || (c == '/' && !encodeSep) {
|
||||
buf.WriteByte(c)
|
||||
} else {
|
||||
fmt.Fprintf(&buf, "%%%02X", c)
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
var noEscape [256]bool
|
||||
|
||||
func init() {
|
||||
for i := 0; i < len(noEscape); i++ {
|
||||
// AWS expects every character except these to be escaped
|
||||
noEscape[i] = (i >= 'A' && i <= 'Z') ||
|
||||
(i >= 'a' && i <= 'z') ||
|
||||
(i >= '0' && i <= '9') ||
|
||||
i == '-' ||
|
||||
i == '.' ||
|
||||
i == '_' ||
|
||||
i == '~'
|
||||
}
|
||||
}
|
107
vendor/github.com/aws/smithy-go/encoding/httpbinding/query.go
generated
vendored
Normal file
107
vendor/github.com/aws/smithy-go/encoding/httpbinding/query.go
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
package httpbinding
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"math"
|
||||
"math/big"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// QueryValue is used to encode query key values
|
||||
type QueryValue struct {
|
||||
query url.Values
|
||||
key string
|
||||
append bool
|
||||
}
|
||||
|
||||
// NewQueryValue creates a new QueryValue which enables encoding
|
||||
// a query value into the given url.Values.
|
||||
func NewQueryValue(query url.Values, key string, append bool) QueryValue {
|
||||
return QueryValue{
|
||||
query: query,
|
||||
key: key,
|
||||
append: append,
|
||||
}
|
||||
}
|
||||
|
||||
func (qv QueryValue) updateKey(value string) {
|
||||
if qv.append {
|
||||
qv.query.Add(qv.key, value)
|
||||
} else {
|
||||
qv.query.Set(qv.key, value)
|
||||
}
|
||||
}
|
||||
|
||||
// Blob encodes v as a base64 query string value
|
||||
func (qv QueryValue) Blob(v []byte) {
|
||||
encodeToString := base64.StdEncoding.EncodeToString(v)
|
||||
qv.updateKey(encodeToString)
|
||||
}
|
||||
|
||||
// Boolean encodes v as a query string value
|
||||
func (qv QueryValue) Boolean(v bool) {
|
||||
qv.updateKey(strconv.FormatBool(v))
|
||||
}
|
||||
|
||||
// String encodes v as a query string value
|
||||
func (qv QueryValue) String(v string) {
|
||||
qv.updateKey(v)
|
||||
}
|
||||
|
||||
// Byte encodes v as a query string value
|
||||
func (qv QueryValue) Byte(v int8) {
|
||||
qv.Long(int64(v))
|
||||
}
|
||||
|
||||
// Short encodes v as a query string value
|
||||
func (qv QueryValue) Short(v int16) {
|
||||
qv.Long(int64(v))
|
||||
}
|
||||
|
||||
// Integer encodes v as a query string value
|
||||
func (qv QueryValue) Integer(v int32) {
|
||||
qv.Long(int64(v))
|
||||
}
|
||||
|
||||
// Long encodes v as a query string value
|
||||
func (qv QueryValue) Long(v int64) {
|
||||
qv.updateKey(strconv.FormatInt(v, 10))
|
||||
}
|
||||
|
||||
// Float encodes v as a query string value
|
||||
func (qv QueryValue) Float(v float32) {
|
||||
qv.float(float64(v), 32)
|
||||
}
|
||||
|
||||
// Double encodes v as a query string value
|
||||
func (qv QueryValue) Double(v float64) {
|
||||
qv.float(v, 64)
|
||||
}
|
||||
|
||||
func (qv QueryValue) float(v float64, bitSize int) {
|
||||
switch {
|
||||
case math.IsNaN(v):
|
||||
qv.String(floatNaN)
|
||||
case math.IsInf(v, 1):
|
||||
qv.String(floatInfinity)
|
||||
case math.IsInf(v, -1):
|
||||
qv.String(floatNegInfinity)
|
||||
default:
|
||||
qv.updateKey(strconv.FormatFloat(v, 'f', -1, bitSize))
|
||||
}
|
||||
}
|
||||
|
||||
// BigInteger encodes v as a query string value
|
||||
func (qv QueryValue) BigInteger(v *big.Int) {
|
||||
qv.updateKey(v.String())
|
||||
}
|
||||
|
||||
// BigDecimal encodes v as a query string value
|
||||
func (qv QueryValue) BigDecimal(v *big.Float) {
|
||||
if i, accuracy := v.Int64(); accuracy == big.Exact {
|
||||
qv.Long(i)
|
||||
return
|
||||
}
|
||||
qv.updateKey(v.Text('e', -1))
|
||||
}
|
108
vendor/github.com/aws/smithy-go/encoding/httpbinding/uri.go
generated
vendored
Normal file
108
vendor/github.com/aws/smithy-go/encoding/httpbinding/uri.go
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
package httpbinding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// URIValue is used to encode named URI parameters
|
||||
type URIValue struct {
|
||||
path, rawPath, buffer *[]byte
|
||||
|
||||
key string
|
||||
}
|
||||
|
||||
func newURIValue(path *[]byte, rawPath *[]byte, buffer *[]byte, key string) URIValue {
|
||||
return URIValue{path: path, rawPath: rawPath, buffer: buffer, key: key}
|
||||
}
|
||||
|
||||
func (u URIValue) modifyURI(value string) (err error) {
|
||||
*u.path, *u.buffer, err = replacePathElement(*u.path, *u.buffer, u.key, value, false)
|
||||
*u.rawPath, *u.buffer, err = replacePathElement(*u.rawPath, *u.buffer, u.key, value, true)
|
||||
return err
|
||||
}
|
||||
|
||||
// Boolean encodes v as a URI string value
|
||||
func (u URIValue) Boolean(v bool) error {
|
||||
return u.modifyURI(strconv.FormatBool(v))
|
||||
}
|
||||
|
||||
// String encodes v as a URI string value
|
||||
func (u URIValue) String(v string) error {
|
||||
return u.modifyURI(v)
|
||||
}
|
||||
|
||||
// Byte encodes v as a URI string value
|
||||
func (u URIValue) Byte(v int8) error {
|
||||
return u.Long(int64(v))
|
||||
}
|
||||
|
||||
// Short encodes v as a URI string value
|
||||
func (u URIValue) Short(v int16) error {
|
||||
return u.Long(int64(v))
|
||||
}
|
||||
|
||||
// Integer encodes v as a URI string value
|
||||
func (u URIValue) Integer(v int32) error {
|
||||
return u.Long(int64(v))
|
||||
}
|
||||
|
||||
// Long encodes v as a URI string value
|
||||
func (u URIValue) Long(v int64) error {
|
||||
return u.modifyURI(strconv.FormatInt(v, 10))
|
||||
}
|
||||
|
||||
// Float encodes v as a query string value
|
||||
func (u URIValue) Float(v float32) error {
|
||||
return u.float(float64(v), 32)
|
||||
}
|
||||
|
||||
// Double encodes v as a query string value
|
||||
func (u URIValue) Double(v float64) error {
|
||||
return u.float(v, 64)
|
||||
}
|
||||
|
||||
func (u URIValue) float(v float64, bitSize int) error {
|
||||
switch {
|
||||
case math.IsNaN(v):
|
||||
return u.String(floatNaN)
|
||||
case math.IsInf(v, 1):
|
||||
return u.String(floatInfinity)
|
||||
case math.IsInf(v, -1):
|
||||
return u.String(floatNegInfinity)
|
||||
default:
|
||||
return u.modifyURI(strconv.FormatFloat(v, 'f', -1, bitSize))
|
||||
}
|
||||
}
|
||||
|
||||
// BigInteger encodes v as a query string value
|
||||
func (u URIValue) BigInteger(v *big.Int) error {
|
||||
return u.modifyURI(v.String())
|
||||
}
|
||||
|
||||
// BigDecimal encodes v as a query string value
|
||||
func (u URIValue) BigDecimal(v *big.Float) error {
|
||||
if i, accuracy := v.Int64(); accuracy == big.Exact {
|
||||
return u.Long(i)
|
||||
}
|
||||
return u.modifyURI(v.Text('e', -1))
|
||||
}
|
||||
|
||||
// SplitURI parses a Smithy HTTP binding trait URI
|
||||
func SplitURI(uri string) (path, query string) {
|
||||
queryStart := strings.IndexRune(uri, '?')
|
||||
if queryStart == -1 {
|
||||
path = uri
|
||||
return path, query
|
||||
}
|
||||
|
||||
path = uri[:queryStart]
|
||||
if queryStart+1 >= len(uri) {
|
||||
return path, query
|
||||
}
|
||||
query = uri[queryStart+1:]
|
||||
|
||||
return path, query
|
||||
}
|
35
vendor/github.com/aws/smithy-go/encoding/json/array.go
generated
vendored
Normal file
35
vendor/github.com/aws/smithy-go/encoding/json/array.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// Array represent 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)
|
||||
}
|
15
vendor/github.com/aws/smithy-go/encoding/json/constants.go
generated
vendored
Normal file
15
vendor/github.com/aws/smithy-go/encoding/json/constants.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
package json
|
||||
|
||||
const (
|
||||
leftBrace = '{'
|
||||
rightBrace = '}'
|
||||
|
||||
leftBracket = '['
|
||||
rightBracket = ']'
|
||||
|
||||
comma = ','
|
||||
quote = '"'
|
||||
colon = ':'
|
||||
|
||||
null = "null"
|
||||
)
|
139
vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go
generated
vendored
Normal file
139
vendor/github.com/aws/smithy-go/encoding/json/decoder_util.go
generated
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// DiscardUnknownField discards unknown fields from decoder body.
|
||||
// This function is useful while deserializing 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
|
||||
}
|
30
vendor/github.com/aws/smithy-go/encoding/json/encoder.go
generated
vendored
Normal file
30
vendor/github.com/aws/smithy-go/encoding/json/encoder.go
generated
vendored
Normal file
@ -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()
|
||||
}
|
198
vendor/github.com/aws/smithy-go/encoding/json/escape.go
generated
vendored
Normal file
198
vendor/github.com/aws/smithy-go/encoding/json/escape.go
generated
vendored
Normal file
@ -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('"')
|
||||
}
|
42
vendor/github.com/aws/smithy-go/encoding/json/object.go
generated
vendored
Normal file
42
vendor/github.com/aws/smithy-go/encoding/json/object.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
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) {
|
||||
o.w.WriteRune(quote)
|
||||
o.w.Write([]byte(key))
|
||||
o.w.WriteRune(quote)
|
||||
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)
|
||||
}
|
149
vendor/github.com/aws/smithy-go/encoding/json/value.go
generated
vendored
Normal file
149
vendor/github.com/aws/smithy-go/encoding/json/value.go
generated
vendored
Normal file
@ -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)
|
||||
}
|
49
vendor/github.com/aws/smithy-go/encoding/xml/array.go
generated
vendored
Normal file
49
vendor/github.com/aws/smithy-go/encoding/xml/array.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
package xml
|
||||
|
||||
// arrayMemberWrapper is the default member wrapper tag name for XML Array type
|
||||
var arrayMemberWrapper = StartElement{
|
||||
Name: Name{Local: "member"},
|
||||
}
|
||||
|
||||
// Array represents the encoding of a XML array type
|
||||
type Array struct {
|
||||
w writer
|
||||
scratch *[]byte
|
||||
|
||||
// member start element is the array member wrapper start element
|
||||
memberStartElement StartElement
|
||||
|
||||
// isFlattened indicates if the array is a flattened array.
|
||||
isFlattened bool
|
||||
}
|
||||
|
||||
// newArray returns an array encoder.
|
||||
// It also takes in the member start element, array start element.
|
||||
// It takes in a isFlattened bool, indicating that an array is flattened array.
|
||||
//
|
||||
// A wrapped array ["value1", "value2"] is represented as
|
||||
// `<List><member>value1</member><member>value2</member></List>`.
|
||||
|
||||
// A flattened array `someList: ["value1", "value2"]` is represented as
|
||||
// `<someList>value1</someList><someList>value2</someList>`.
|
||||
func newArray(w writer, scratch *[]byte, memberStartElement StartElement, arrayStartElement StartElement, isFlattened bool) *Array {
|
||||
var memberWrapper = memberStartElement
|
||||
if isFlattened {
|
||||
memberWrapper = arrayStartElement
|
||||
}
|
||||
|
||||
return &Array{
|
||||
w: w,
|
||||
scratch: scratch,
|
||||
memberStartElement: memberWrapper,
|
||||
isFlattened: isFlattened,
|
||||
}
|
||||
}
|
||||
|
||||
// Member adds a new member to the XML array.
|
||||
// It returns a Value encoder.
|
||||
func (a *Array) Member() Value {
|
||||
v := newValue(a.w, a.scratch, a.memberStartElement)
|
||||
v.isFlattened = a.isFlattened
|
||||
return v
|
||||
}
|
10
vendor/github.com/aws/smithy-go/encoding/xml/constants.go
generated
vendored
Normal file
10
vendor/github.com/aws/smithy-go/encoding/xml/constants.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
package xml
|
||||
|
||||
const (
|
||||
leftAngleBracket = '<'
|
||||
rightAngleBracket = '>'
|
||||
forwardSlash = '/'
|
||||
colon = ':'
|
||||
equals = '='
|
||||
quote = '"'
|
||||
)
|
49
vendor/github.com/aws/smithy-go/encoding/xml/doc.go
generated
vendored
Normal file
49
vendor/github.com/aws/smithy-go/encoding/xml/doc.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
Package xml holds the XMl encoder utility. This utility is written in accordance to our design to delegate to
|
||||
shape serializer function in which a xml.Value will be passed around.
|
||||
|
||||
Resources followed: https://awslabs.github.io/smithy/1.0/spec/core/xml-traits.html#
|
||||
|
||||
Member Element
|
||||
|
||||
Member element should be used to encode xml shapes into xml elements except for flattened xml shapes. Member element
|
||||
write their own element start tag. These elements should always be closed.
|
||||
|
||||
Flattened Element
|
||||
|
||||
Flattened element should be used to encode shapes marked with flattened trait into xml elements. Flattened element
|
||||
do not write a start tag, and thus should not be closed.
|
||||
|
||||
Simple types encoding
|
||||
|
||||
All simple type methods on value such as String(), Long() etc; auto close the associated member element.
|
||||
|
||||
Array
|
||||
|
||||
Array returns the collection encoder. It has two modes, wrapped and flattened encoding.
|
||||
|
||||
Wrapped arrays have two methods Array() and ArrayWithCustomName() which facilitate array member wrapping.
|
||||
By default, a wrapped array members are wrapped with `member` named start element.
|
||||
|
||||
<wrappedArray><member>apple</member><member>tree</member></wrappedArray>
|
||||
|
||||
Flattened arrays rely on Value being marked as flattened.
|
||||
If a shape is marked as flattened, Array() will use the shape element name as wrapper for array elements.
|
||||
|
||||
<flattenedAarray>apple</flattenedArray><flattenedArray>tree</flattenedArray>
|
||||
|
||||
Map
|
||||
|
||||
Map is the map encoder. It has two modes, wrapped and flattened encoding.
|
||||
|
||||
Wrapped map has Array() method, which facilitate map member wrapping.
|
||||
By default, a wrapped map members are wrapped with `entry` named start element.
|
||||
|
||||
<wrappedMap><entry><Key>apple</Key><Value>tree</Value></entry><entry><Key>snow</Key><Value>ice</Value></entry></wrappedMap>
|
||||
|
||||
Flattened map rely on Value being marked as flattened.
|
||||
If a shape is marked as flattened, Map() will use the shape element name as wrapper for map entry elements.
|
||||
|
||||
<flattenedMap><Key>apple</Key><Value>tree</Value></flattenedMap><flattenedMap><Key>snow</Key><Value>ice</Value></flattenedMap>
|
||||
*/
|
||||
package xml
|
91
vendor/github.com/aws/smithy-go/encoding/xml/element.go
generated
vendored
Normal file
91
vendor/github.com/aws/smithy-go/encoding/xml/element.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright 2009 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.14 stdlib's encoding/xml
|
||||
|
||||
package xml
|
||||
|
||||
// A Name represents an XML name (Local) annotated
|
||||
// with a name space identifier (Space).
|
||||
// In tokens returned by Decoder.Token, the Space identifier
|
||||
// is given as a canonical URL, not the short prefix used
|
||||
// in the document being parsed.
|
||||
type Name struct {
|
||||
Space, Local string
|
||||
}
|
||||
|
||||
// An Attr represents an attribute in an XML element (Name=Value).
|
||||
type Attr struct {
|
||||
Name Name
|
||||
Value string
|
||||
}
|
||||
|
||||
/*
|
||||
NewAttribute returns a pointer to an attribute.
|
||||
It takes in a local name aka attribute name, and value
|
||||
representing the attribute value.
|
||||
*/
|
||||
func NewAttribute(local, value string) Attr {
|
||||
return Attr{
|
||||
Name: Name{
|
||||
Local: local,
|
||||
},
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
NewNamespaceAttribute returns a pointer to an attribute.
|
||||
It takes in a local name aka attribute name, and value
|
||||
representing the attribute value.
|
||||
|
||||
NewNamespaceAttribute appends `xmlns:` in front of namespace
|
||||
prefix.
|
||||
|
||||
For creating a name space attribute representing
|
||||
`xmlns:prefix="http://example.com`, the breakdown would be:
|
||||
local = "prefix"
|
||||
value = "http://example.com"
|
||||
*/
|
||||
func NewNamespaceAttribute(local, value string) Attr {
|
||||
attr := NewAttribute(local, value)
|
||||
|
||||
// default name space identifier
|
||||
attr.Name.Space = "xmlns"
|
||||
return attr
|
||||
}
|
||||
|
||||
// A StartElement represents an XML start element.
|
||||
type StartElement struct {
|
||||
Name Name
|
||||
Attr []Attr
|
||||
}
|
||||
|
||||
// Copy creates a new copy of StartElement.
|
||||
func (e StartElement) Copy() StartElement {
|
||||
attrs := make([]Attr, len(e.Attr))
|
||||
copy(attrs, e.Attr)
|
||||
e.Attr = attrs
|
||||
return e
|
||||
}
|
||||
|
||||
// End returns the corresponding XML end element.
|
||||
func (e StartElement) End() EndElement {
|
||||
return EndElement{e.Name}
|
||||
}
|
||||
|
||||
// returns true if start element local name is empty
|
||||
func (e StartElement) isZero() bool {
|
||||
return len(e.Name.Local) == 0
|
||||
}
|
||||
|
||||
// An EndElement represents an XML end element.
|
||||
type EndElement struct {
|
||||
Name Name
|
||||
}
|
||||
|
||||
// returns true if end element local name is empty
|
||||
func (e EndElement) isZero() bool {
|
||||
return len(e.Name.Local) == 0
|
||||
}
|
51
vendor/github.com/aws/smithy-go/encoding/xml/encoder.go
generated
vendored
Normal file
51
vendor/github.com/aws/smithy-go/encoding/xml/encoder.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
package xml
|
||||
|
||||
// writer interface used by the xml encoder to write an encoded xml
|
||||
// document in a writer.
|
||||
type writer interface {
|
||||
|
||||
// Write takes in a byte slice and returns number of bytes written and error
|
||||
Write(p []byte) (n int, err error)
|
||||
|
||||
// WriteRune takes in a rune and returns number of bytes written and error
|
||||
WriteRune(r rune) (n int, err error)
|
||||
|
||||
// WriteString takes in a string and returns number of bytes written and error
|
||||
WriteString(s string) (n int, err error)
|
||||
|
||||
// String method returns a string
|
||||
String() string
|
||||
|
||||
// Bytes return a byte slice.
|
||||
Bytes() []byte
|
||||
}
|
||||
|
||||
// Encoder is an XML encoder that supports construction of XML values
|
||||
// using methods. The encoder takes in a writer and maintains a scratch buffer.
|
||||
type Encoder struct {
|
||||
w writer
|
||||
scratch *[]byte
|
||||
}
|
||||
|
||||
// NewEncoder returns an XML encoder
|
||||
func NewEncoder(w writer) *Encoder {
|
||||
scratch := make([]byte, 64)
|
||||
|
||||
return &Encoder{w: w, scratch: &scratch}
|
||||
}
|
||||
|
||||
// String returns the string output of the XML encoder
|
||||
func (e Encoder) String() string {
|
||||
return e.w.String()
|
||||
}
|
||||
|
||||
// Bytes returns the []byte slice of the XML encoder
|
||||
func (e Encoder) Bytes() []byte {
|
||||
return e.w.Bytes()
|
||||
}
|
||||
|
||||
// RootElement builds a root element encoding
|
||||
// It writes it's start element tag. The value should be closed.
|
||||
func (e Encoder) RootElement(element StartElement) Value {
|
||||
return newValue(e.w, e.scratch, element)
|
||||
}
|
51
vendor/github.com/aws/smithy-go/encoding/xml/error_utils.go
generated
vendored
Normal file
51
vendor/github.com/aws/smithy-go/encoding/xml/error_utils.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
package xml
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// ErrorComponents represents the error response fields
|
||||
// that will be deserialized from an xml error response body
|
||||
type ErrorComponents struct {
|
||||
Code string
|
||||
Message string
|
||||
}
|
||||
|
||||
// GetErrorResponseComponents returns the error fields from an xml error response body
|
||||
func GetErrorResponseComponents(r io.Reader, noErrorWrapping bool) (ErrorComponents, error) {
|
||||
if noErrorWrapping {
|
||||
var errResponse noWrappedErrorResponse
|
||||
if err := xml.NewDecoder(r).Decode(&errResponse); err != nil && err != io.EOF {
|
||||
return ErrorComponents{}, fmt.Errorf("error while deserializing xml error response: %w", err)
|
||||
}
|
||||
return ErrorComponents{
|
||||
Code: errResponse.Code,
|
||||
Message: errResponse.Message,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var errResponse wrappedErrorResponse
|
||||
if err := xml.NewDecoder(r).Decode(&errResponse); err != nil && err != io.EOF {
|
||||
return ErrorComponents{}, fmt.Errorf("error while deserializing xml error response: %w", err)
|
||||
}
|
||||
return ErrorComponents{
|
||||
Code: errResponse.Code,
|
||||
Message: errResponse.Message,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// noWrappedErrorResponse represents the error response body with
|
||||
// no internal <Error></Error wrapping
|
||||
type noWrappedErrorResponse struct {
|
||||
Code string `xml:"Code"`
|
||||
Message string `xml:"Message"`
|
||||
}
|
||||
|
||||
// wrappedErrorResponse represents the error response body
|
||||
// wrapped within <Error>...</Error>
|
||||
type wrappedErrorResponse struct {
|
||||
Code string `xml:"Error>Code"`
|
||||
Message string `xml:"Error>Message"`
|
||||
}
|
137
vendor/github.com/aws/smithy-go/encoding/xml/escape.go
generated
vendored
Normal file
137
vendor/github.com/aws/smithy-go/encoding/xml/escape.go
generated
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright 2009 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.14 stdlib's encoding/xml
|
||||
|
||||
package xml
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Copied from Go 1.14 stdlib's encoding/xml
|
||||
var (
|
||||
escQuot = []byte(""") // shorter than """
|
||||
escApos = []byte("'") // shorter than "'"
|
||||
escAmp = []byte("&")
|
||||
escLT = []byte("<")
|
||||
escGT = []byte(">")
|
||||
escTab = []byte("	")
|
||||
escNL = []byte("
")
|
||||
escCR = []byte("
")
|
||||
escFFFD = []byte("\uFFFD") // Unicode replacement character
|
||||
|
||||
// Additional Escapes
|
||||
escNextLine = []byte("…")
|
||||
escLS = []byte("
")
|
||||
)
|
||||
|
||||
// Decide whether the given rune is in the XML Character Range, per
|
||||
// the Char production of https://www.xml.com/axml/testaxml.htm,
|
||||
// Section 2.2 Characters.
|
||||
func isInCharacterRange(r rune) (inrange bool) {
|
||||
return r == 0x09 ||
|
||||
r == 0x0A ||
|
||||
r == 0x0D ||
|
||||
r >= 0x20 && r <= 0xD7FF ||
|
||||
r >= 0xE000 && r <= 0xFFFD ||
|
||||
r >= 0x10000 && r <= 0x10FFFF
|
||||
}
|
||||
|
||||
// TODO: When do we need to escape the string?
|
||||
// Based on encoding/xml escapeString from the Go Standard Library.
|
||||
// https://golang.org/src/encoding/xml/xml.go
|
||||
func escapeString(e writer, s string) {
|
||||
var esc []byte
|
||||
last := 0
|
||||
for i := 0; i < len(s); {
|
||||
r, width := utf8.DecodeRuneInString(s[i:])
|
||||
i += width
|
||||
switch r {
|
||||
case '"':
|
||||
esc = escQuot
|
||||
case '\'':
|
||||
esc = escApos
|
||||
case '&':
|
||||
esc = escAmp
|
||||
case '<':
|
||||
esc = escLT
|
||||
case '>':
|
||||
esc = escGT
|
||||
case '\t':
|
||||
esc = escTab
|
||||
case '\n':
|
||||
esc = escNL
|
||||
case '\r':
|
||||
esc = escCR
|
||||
case '\u0085':
|
||||
// Not escaped by stdlib
|
||||
esc = escNextLine
|
||||
case '\u2028':
|
||||
// Not escaped by stdlib
|
||||
esc = escLS
|
||||
default:
|
||||
if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
|
||||
esc = escFFFD
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
e.WriteString(s[last : i-width])
|
||||
e.Write(esc)
|
||||
last = i
|
||||
}
|
||||
e.WriteString(s[last:])
|
||||
}
|
||||
|
||||
// escapeText writes to w the properly escaped XML equivalent
|
||||
// of the plain text data s. If escapeNewline is true, newline
|
||||
// characters will be escaped.
|
||||
//
|
||||
// Based on encoding/xml escapeText from the Go Standard Library.
|
||||
// https://golang.org/src/encoding/xml/xml.go
|
||||
func escapeText(e writer, s []byte) {
|
||||
var esc []byte
|
||||
last := 0
|
||||
for i := 0; i < len(s); {
|
||||
r, width := utf8.DecodeRune(s[i:])
|
||||
i += width
|
||||
switch r {
|
||||
case '"':
|
||||
esc = escQuot
|
||||
case '\'':
|
||||
esc = escApos
|
||||
case '&':
|
||||
esc = escAmp
|
||||
case '<':
|
||||
esc = escLT
|
||||
case '>':
|
||||
esc = escGT
|
||||
case '\t':
|
||||
esc = escTab
|
||||
case '\n':
|
||||
// This always escapes newline, which is different than stdlib's optional
|
||||
// escape of new line.
|
||||
esc = escNL
|
||||
case '\r':
|
||||
esc = escCR
|
||||
case '\u0085':
|
||||
// Not escaped by stdlib
|
||||
esc = escNextLine
|
||||
case '\u2028':
|
||||
// Not escaped by stdlib
|
||||
esc = escLS
|
||||
default:
|
||||
if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
|
||||
esc = escFFFD
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
e.Write(s[last : i-width])
|
||||
e.Write(esc)
|
||||
last = i
|
||||
}
|
||||
e.Write(s[last:])
|
||||
}
|
53
vendor/github.com/aws/smithy-go/encoding/xml/map.go
generated
vendored
Normal file
53
vendor/github.com/aws/smithy-go/encoding/xml/map.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
package xml
|
||||
|
||||
// mapEntryWrapper is the default member wrapper start element for XML Map entry
|
||||
var mapEntryWrapper = StartElement{
|
||||
Name: Name{Local: "entry"},
|
||||
}
|
||||
|
||||
// Map represents the encoding of a XML map type
|
||||
type Map struct {
|
||||
w writer
|
||||
scratch *[]byte
|
||||
|
||||
// member start element is the map entry wrapper start element
|
||||
memberStartElement StartElement
|
||||
|
||||
// isFlattened returns true if the map is a flattened map
|
||||
isFlattened bool
|
||||
}
|
||||
|
||||
// newMap returns a map encoder which sets the default map
|
||||
// entry wrapper to `entry`.
|
||||
//
|
||||
// A map `someMap : {{key:"abc", value:"123"}}` is represented as
|
||||
// `<someMap><entry><key>abc<key><value>123</value></entry></someMap>`.
|
||||
func newMap(w writer, scratch *[]byte) *Map {
|
||||
return &Map{
|
||||
w: w,
|
||||
scratch: scratch,
|
||||
memberStartElement: mapEntryWrapper,
|
||||
}
|
||||
}
|
||||
|
||||
// newFlattenedMap returns a map encoder which sets the map
|
||||
// entry wrapper to the passed in memberWrapper`.
|
||||
//
|
||||
// A flattened map `someMap : {{key:"abc", value:"123"}}` is represented as
|
||||
// `<someMap><key>abc<key><value>123</value></someMap>`.
|
||||
func newFlattenedMap(w writer, scratch *[]byte, memberWrapper StartElement) *Map {
|
||||
return &Map{
|
||||
w: w,
|
||||
scratch: scratch,
|
||||
memberStartElement: memberWrapper,
|
||||
isFlattened: true,
|
||||
}
|
||||
}
|
||||
|
||||
// Entry returns a Value encoder with map's element.
|
||||
// It writes the member wrapper start tag for each entry.
|
||||
func (m *Map) Entry() Value {
|
||||
v := newValue(m.w, m.scratch, m.memberStartElement)
|
||||
v.isFlattened = m.isFlattened
|
||||
return v
|
||||
}
|
302
vendor/github.com/aws/smithy-go/encoding/xml/value.go
generated
vendored
Normal file
302
vendor/github.com/aws/smithy-go/encoding/xml/value.go
generated
vendored
Normal file
@ -0,0 +1,302 @@
|
||||
package xml
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
"github.com/aws/smithy-go/encoding"
|
||||
)
|
||||
|
||||
// Value represents an XML Value type
|
||||
// XML Value types: Object, Array, Map, String, Number, Boolean.
|
||||
type Value struct {
|
||||
w writer
|
||||
scratch *[]byte
|
||||
|
||||
// xml start element is the associated start element for the Value
|
||||
startElement StartElement
|
||||
|
||||
// indicates if the Value represents a flattened shape
|
||||
isFlattened bool
|
||||
}
|
||||
|
||||
// newFlattenedValue returns a Value encoder. newFlattenedValue does NOT write the start element tag
|
||||
func newFlattenedValue(w writer, scratch *[]byte, startElement StartElement) Value {
|
||||
return Value{
|
||||
w: w,
|
||||
scratch: scratch,
|
||||
startElement: startElement,
|
||||
}
|
||||
}
|
||||
|
||||
// newValue writes the start element xml tag and returns a Value
|
||||
func newValue(w writer, scratch *[]byte, startElement StartElement) Value {
|
||||
writeStartElement(w, startElement)
|
||||
return Value{w: w, scratch: scratch, startElement: startElement}
|
||||
}
|
||||
|
||||
// writeStartElement takes in a start element and writes it.
|
||||
// It handles namespace, attributes in start element.
|
||||
func writeStartElement(w writer, el StartElement) error {
|
||||
if el.isZero() {
|
||||
return fmt.Errorf("xml start element cannot be nil")
|
||||
}
|
||||
|
||||
w.WriteRune(leftAngleBracket)
|
||||
|
||||
if len(el.Name.Space) != 0 {
|
||||
escapeString(w, el.Name.Space)
|
||||
w.WriteRune(colon)
|
||||
}
|
||||
escapeString(w, el.Name.Local)
|
||||
for _, attr := range el.Attr {
|
||||
w.WriteRune(' ')
|
||||
writeAttribute(w, &attr)
|
||||
}
|
||||
|
||||
w.WriteRune(rightAngleBracket)
|
||||
return nil
|
||||
}
|
||||
|
||||
// writeAttribute writes an attribute from a provided Attribute
|
||||
// For a namespace attribute, the attr.Name.Space must be defined as "xmlns".
|
||||
// https://www.w3.org/TR/REC-xml-names/#NT-DefaultAttName
|
||||
func writeAttribute(w writer, attr *Attr) {
|
||||
// if local, space both are not empty
|
||||
if len(attr.Name.Space) != 0 && len(attr.Name.Local) != 0 {
|
||||
escapeString(w, attr.Name.Space)
|
||||
w.WriteRune(colon)
|
||||
}
|
||||
|
||||
// if prefix is empty, the default `xmlns` space should be used as prefix.
|
||||
if len(attr.Name.Local) == 0 {
|
||||
attr.Name.Local = attr.Name.Space
|
||||
}
|
||||
|
||||
escapeString(w, attr.Name.Local)
|
||||
w.WriteRune(equals)
|
||||
w.WriteRune(quote)
|
||||
escapeString(w, attr.Value)
|
||||
w.WriteRune(quote)
|
||||
}
|
||||
|
||||
// writeEndElement takes in a end element and writes it.
|
||||
func writeEndElement(w writer, el EndElement) error {
|
||||
if el.isZero() {
|
||||
return fmt.Errorf("xml end element cannot be nil")
|
||||
}
|
||||
|
||||
w.WriteRune(leftAngleBracket)
|
||||
w.WriteRune(forwardSlash)
|
||||
|
||||
if len(el.Name.Space) != 0 {
|
||||
escapeString(w, el.Name.Space)
|
||||
w.WriteRune(colon)
|
||||
}
|
||||
escapeString(w, el.Name.Local)
|
||||
w.WriteRune(rightAngleBracket)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// String encodes v as a XML string.
|
||||
// It will auto close the parent xml element tag.
|
||||
func (xv Value) String(v string) {
|
||||
escapeString(xv.w, v)
|
||||
xv.Close()
|
||||
}
|
||||
|
||||
// Byte encodes v as a XML number.
|
||||
// It will auto close the parent xml element tag.
|
||||
func (xv Value) Byte(v int8) {
|
||||
xv.Long(int64(v))
|
||||
}
|
||||
|
||||
// Short encodes v as a XML number.
|
||||
// It will auto close the parent xml element tag.
|
||||
func (xv Value) Short(v int16) {
|
||||
xv.Long(int64(v))
|
||||
}
|
||||
|
||||
// Integer encodes v as a XML number.
|
||||
// It will auto close the parent xml element tag.
|
||||
func (xv Value) Integer(v int32) {
|
||||
xv.Long(int64(v))
|
||||
}
|
||||
|
||||
// Long encodes v as a XML number.
|
||||
// It will auto close the parent xml element tag.
|
||||
func (xv Value) Long(v int64) {
|
||||
*xv.scratch = strconv.AppendInt((*xv.scratch)[:0], v, 10)
|
||||
xv.w.Write(*xv.scratch)
|
||||
|
||||
xv.Close()
|
||||
}
|
||||
|
||||
// Float encodes v as a XML number.
|
||||
// It will auto close the parent xml element tag.
|
||||
func (xv Value) Float(v float32) {
|
||||
xv.float(float64(v), 32)
|
||||
xv.Close()
|
||||
}
|
||||
|
||||
// Double encodes v as a XML number.
|
||||
// It will auto close the parent xml element tag.
|
||||
func (xv Value) Double(v float64) {
|
||||
xv.float(v, 64)
|
||||
xv.Close()
|
||||
}
|
||||
|
||||
func (xv Value) float(v float64, bits int) {
|
||||
*xv.scratch = encoding.EncodeFloat((*xv.scratch)[:0], v, bits)
|
||||
xv.w.Write(*xv.scratch)
|
||||
}
|
||||
|
||||
// Boolean encodes v as a XML boolean.
|
||||
// It will auto close the parent xml element tag.
|
||||
func (xv Value) Boolean(v bool) {
|
||||
*xv.scratch = strconv.AppendBool((*xv.scratch)[:0], v)
|
||||
xv.w.Write(*xv.scratch)
|
||||
|
||||
xv.Close()
|
||||
}
|
||||
|
||||
// Base64EncodeBytes writes v as a base64 value in XML string.
|
||||
// It will auto close the parent xml element tag.
|
||||
func (xv Value) Base64EncodeBytes(v []byte) {
|
||||
encodeByteSlice(xv.w, (*xv.scratch)[:0], v)
|
||||
xv.Close()
|
||||
}
|
||||
|
||||
// BigInteger encodes v big.Int as XML value.
|
||||
// It will auto close the parent xml element tag.
|
||||
func (xv Value) BigInteger(v *big.Int) {
|
||||
xv.w.Write([]byte(v.Text(10)))
|
||||
xv.Close()
|
||||
}
|
||||
|
||||
// BigDecimal encodes v big.Float as XML value.
|
||||
// It will auto close the parent xml element tag.
|
||||
func (xv Value) BigDecimal(v *big.Float) {
|
||||
if i, accuracy := v.Int64(); accuracy == big.Exact {
|
||||
xv.Long(i)
|
||||
return
|
||||
}
|
||||
|
||||
xv.w.Write([]byte(v.Text('e', -1)))
|
||||
xv.Close()
|
||||
}
|
||||
|
||||
// Write writes v directly to the xml document
|
||||
// if escapeXMLText is set to true, write will escape text.
|
||||
// It will auto close the parent xml element tag.
|
||||
func (xv Value) Write(v []byte, escapeXMLText bool) {
|
||||
// escape and write xml text
|
||||
if escapeXMLText {
|
||||
escapeText(xv.w, v)
|
||||
} else {
|
||||
// write xml directly
|
||||
xv.w.Write(v)
|
||||
}
|
||||
|
||||
xv.Close()
|
||||
}
|
||||
|
||||
// MemberElement does member element encoding. It returns a Value.
|
||||
// Member Element method should be used for all shapes except flattened shapes.
|
||||
//
|
||||
// A call to MemberElement will write nested element tags directly using the
|
||||
// provided start element. The value returned by MemberElement should be closed.
|
||||
func (xv Value) MemberElement(element StartElement) Value {
|
||||
return newValue(xv.w, xv.scratch, element)
|
||||
}
|
||||
|
||||
// FlattenedElement returns flattened element encoding. It returns a Value.
|
||||
// This method should be used for flattened shapes.
|
||||
//
|
||||
// Unlike MemberElement, flattened element will NOT write element tags
|
||||
// directly for the associated start element.
|
||||
//
|
||||
// The value returned by the FlattenedElement does not need to be closed.
|
||||
func (xv Value) FlattenedElement(element StartElement) Value {
|
||||
v := newFlattenedValue(xv.w, xv.scratch, element)
|
||||
v.isFlattened = true
|
||||
return v
|
||||
}
|
||||
|
||||
// Array returns an array encoder. By default, the members of array are
|
||||
// wrapped with `<member>` element tag.
|
||||
// If value is marked as flattened, the start element is used to wrap the members instead of
|
||||
// the `<member>` element.
|
||||
func (xv Value) Array() *Array {
|
||||
return newArray(xv.w, xv.scratch, arrayMemberWrapper, xv.startElement, xv.isFlattened)
|
||||
}
|
||||
|
||||
/*
|
||||
ArrayWithCustomName returns an array encoder.
|
||||
|
||||
It takes named start element as an argument, the named start element will used to wrap xml array entries.
|
||||
for eg, `<someList><customName>entry1</customName></someList>`
|
||||
Here `customName` named start element will be wrapped on each array member.
|
||||
*/
|
||||
func (xv Value) ArrayWithCustomName(element StartElement) *Array {
|
||||
return newArray(xv.w, xv.scratch, element, xv.startElement, xv.isFlattened)
|
||||
}
|
||||
|
||||
/*
|
||||
Map returns a map encoder. By default, the map entries are
|
||||
wrapped with `<entry>` element tag.
|
||||
|
||||
If value is marked as flattened, the start element is used to wrap the entry instead of
|
||||
the `<member>` element.
|
||||
*/
|
||||
func (xv Value) Map() *Map {
|
||||
// flattened map
|
||||
if xv.isFlattened {
|
||||
return newFlattenedMap(xv.w, xv.scratch, xv.startElement)
|
||||
}
|
||||
|
||||
// un-flattened map
|
||||
return newMap(xv.w, xv.scratch)
|
||||
}
|
||||
|
||||
// encodeByteSlice is modified copy of json encoder's encodeByteSlice.
|
||||
// It is used to base64 encode a byte slice.
|
||||
func encodeByteSlice(w writer, scratch []byte, v []byte) {
|
||||
if v == nil {
|
||||
return
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
// IsFlattened returns true if value is for flattened shape.
|
||||
func (xv Value) IsFlattened() bool {
|
||||
return xv.isFlattened
|
||||
}
|
||||
|
||||
// Close closes the value.
|
||||
func (xv Value) Close() {
|
||||
writeEndElement(xv.w, xv.startElement.End())
|
||||
}
|
154
vendor/github.com/aws/smithy-go/encoding/xml/xml_decoder.go
generated
vendored
Normal file
154
vendor/github.com/aws/smithy-go/encoding/xml/xml_decoder.go
generated
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
package xml
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// NodeDecoder is a XML decoder wrapper that is responsible to decoding
|
||||
// a single XML Node element and it's nested member elements. This wrapper decoder
|
||||
// takes in the start element of the top level node being decoded.
|
||||
type NodeDecoder struct {
|
||||
Decoder *xml.Decoder
|
||||
StartEl xml.StartElement
|
||||
}
|
||||
|
||||
// WrapNodeDecoder returns an initialized XMLNodeDecoder
|
||||
func WrapNodeDecoder(decoder *xml.Decoder, startEl xml.StartElement) NodeDecoder {
|
||||
return NodeDecoder{
|
||||
Decoder: decoder,
|
||||
StartEl: startEl,
|
||||
}
|
||||
}
|
||||
|
||||
// Token on a Node Decoder returns a xml StartElement. It returns a boolean that indicates the
|
||||
// a token is the node decoder's end node token; and an error which indicates any error
|
||||
// that occurred while retrieving the start element
|
||||
func (d NodeDecoder) Token() (t xml.StartElement, done bool, err error) {
|
||||
for {
|
||||
token, e := d.Decoder.Token()
|
||||
if e != nil {
|
||||
return t, done, e
|
||||
}
|
||||
|
||||
// check if we reach end of the node being decoded
|
||||
if el, ok := token.(xml.EndElement); ok {
|
||||
return t, el == d.StartEl.End(), err
|
||||
}
|
||||
|
||||
if t, ok := token.(xml.StartElement); ok {
|
||||
return restoreAttrNamespaces(t), false, err
|
||||
}
|
||||
|
||||
// skip token if it is a comment or preamble or empty space value due to indentation
|
||||
// or if it's a value and is not expected
|
||||
}
|
||||
}
|
||||
|
||||
// restoreAttrNamespaces update XML attributes to restore the short namespaces found within
|
||||
// the raw XML document.
|
||||
func restoreAttrNamespaces(node xml.StartElement) xml.StartElement {
|
||||
if len(node.Attr) == 0 {
|
||||
return node
|
||||
}
|
||||
|
||||
// Generate a mapping of XML namespace values to their short names.
|
||||
ns := map[string]string{}
|
||||
for _, a := range node.Attr {
|
||||
if a.Name.Space == "xmlns" {
|
||||
ns[a.Value] = a.Name.Local
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for i, a := range node.Attr {
|
||||
if a.Name.Space == "xmlns" {
|
||||
continue
|
||||
}
|
||||
// By default, xml.Decoder will fully resolve these namespaces. So if you had <foo xmlns:bar=baz bar:bin=hi/>
|
||||
// then by default the second attribute would have the `Name.Space` resolved to `baz`. But we need it to
|
||||
// continue to resolve as `bar` so we can easily identify it later on.
|
||||
if v, ok := ns[node.Attr[i].Name.Space]; ok {
|
||||
node.Attr[i].Name.Space = v
|
||||
}
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// GetElement looks for the given tag name at the current level, and returns the element if found, and
|
||||
// skipping over non-matching elements. Returns an error if the node is not found, or if an error occurs while walking
|
||||
// the document.
|
||||
func (d NodeDecoder) GetElement(name string) (t xml.StartElement, err error) {
|
||||
for {
|
||||
token, done, err := d.Token()
|
||||
if err != nil {
|
||||
return t, err
|
||||
}
|
||||
if done {
|
||||
return t, fmt.Errorf("%s node not found", name)
|
||||
}
|
||||
switch {
|
||||
case strings.EqualFold(name, token.Name.Local):
|
||||
return token, nil
|
||||
default:
|
||||
err = d.Decoder.Skip()
|
||||
if err != nil {
|
||||
return t, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Value provides an abstraction to retrieve char data value within an xml element.
|
||||
// The method will return an error if it encounters a nested xml element instead of char data.
|
||||
// This method should only be used to retrieve simple type or blob shape values as []byte.
|
||||
func (d NodeDecoder) Value() (c []byte, err error) {
|
||||
t, e := d.Decoder.Token()
|
||||
if e != nil {
|
||||
return c, e
|
||||
}
|
||||
|
||||
endElement := d.StartEl.End()
|
||||
|
||||
switch ev := t.(type) {
|
||||
case xml.CharData:
|
||||
c = ev.Copy()
|
||||
case xml.EndElement: // end tag or self-closing
|
||||
if ev == endElement {
|
||||
return []byte{}, err
|
||||
}
|
||||
return c, fmt.Errorf("expected value for %v element, got %T type %v instead", d.StartEl.Name.Local, t, t)
|
||||
default:
|
||||
return c, fmt.Errorf("expected value for %v element, got %T type %v instead", d.StartEl.Name.Local, t, t)
|
||||
}
|
||||
|
||||
t, e = d.Decoder.Token()
|
||||
if e != nil {
|
||||
return c, e
|
||||
}
|
||||
|
||||
if ev, ok := t.(xml.EndElement); ok {
|
||||
if ev == endElement {
|
||||
return c, err
|
||||
}
|
||||
}
|
||||
|
||||
return c, fmt.Errorf("expected end element %v, got %T type %v instead", endElement, t, t)
|
||||
}
|
||||
|
||||
// FetchRootElement takes in a decoder and returns the first start element within the xml body.
|
||||
// This function is useful in fetching the start element of an XML response and ignore the
|
||||
// comments and preamble
|
||||
func FetchRootElement(decoder *xml.Decoder) (startElement xml.StartElement, err error) {
|
||||
for {
|
||||
t, e := decoder.Token()
|
||||
if e != nil {
|
||||
return startElement, e
|
||||
}
|
||||
|
||||
if startElement, ok := t.(xml.StartElement); ok {
|
||||
return startElement, err
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user