mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
rbd: add aws-sts-metdata
encryption type
With Amazon STS and kubernetes cluster is configured with OIDC identity provider, credentials to access Amazon KMS can be fetched using oidc-token(serviceaccount token). Each tenant/namespace needs to create a secret with aws region, role and CMK ARN. Ceph-CSI will assume the given role with oidc token and access aws KMS, with given CMK to encrypt/decrypt DEK which will stored in the image metdata. Refer: https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html Resolves: #2879 Signed-off-by: Rakshith R <rar@redhat.com>
This commit is contained in:
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