Vendor dependencies
This commit is contained in:
+294
@@ -0,0 +1,294 @@
|
||||
package eventstream
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/aws/smithy-go"
|
||||
"github.com/aws/smithy-go/document"
|
||||
"github.com/aws/smithy-go/traits"
|
||||
)
|
||||
|
||||
// ShapeDeserializer wraps a [smithy.ShapeDeserializer] to handle event stream
|
||||
// message binding traits.
|
||||
type ShapeDeserializer struct {
|
||||
Message *Message
|
||||
|
||||
inner smithy.ShapeDeserializer
|
||||
|
||||
depth int
|
||||
schema *smithy.Schema
|
||||
|
||||
bindings []*smithy.Schema
|
||||
bindIdx int
|
||||
inBindings bool
|
||||
|
||||
inBody bool
|
||||
hasPayload bool
|
||||
hasBody bool
|
||||
}
|
||||
|
||||
var _ smithy.ShapeDeserializer = (*ShapeDeserializer)(nil)
|
||||
|
||||
// NewShapeDeserializer returns a deserializer for a Message.
|
||||
func NewShapeDeserializer(msg *Message, inner smithy.ShapeDeserializer) *ShapeDeserializer {
|
||||
return &ShapeDeserializer{
|
||||
Message: msg,
|
||||
inner: inner,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadStruct(s *smithy.Schema) error {
|
||||
d.depth++
|
||||
if d.depth > 1 {
|
||||
return d.inner.ReadStruct(s)
|
||||
}
|
||||
d.schema = s
|
||||
for _, m := range s.Members() {
|
||||
if _, ok := smithy.SchemaTrait[*traits.EventPayload](m); ok {
|
||||
d.hasPayload = true
|
||||
}
|
||||
if isEventBound(m) {
|
||||
d.bindings = append(d.bindings, m)
|
||||
} else {
|
||||
d.hasBody = true
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadStructMember() (*smithy.Schema, error) {
|
||||
if d.depth > 1 {
|
||||
ms, err := d.inner.ReadStructMember()
|
||||
if ms == nil {
|
||||
d.depth--
|
||||
}
|
||||
return ms, err
|
||||
}
|
||||
|
||||
// like httpbinding, throw back the bound stuff first before we drop into
|
||||
// the body
|
||||
for d.bindIdx < len(d.bindings) {
|
||||
m := d.bindings[d.bindIdx]
|
||||
d.bindIdx++
|
||||
if isEventHeader(m) && d.Message.Headers.Get(m.MemberName()) == nil {
|
||||
continue
|
||||
}
|
||||
d.inBindings = true
|
||||
return m, nil
|
||||
}
|
||||
d.inBindings = false
|
||||
|
||||
if d.hasPayload {
|
||||
d.depth--
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if !d.hasBody {
|
||||
d.depth--
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if !d.inBody {
|
||||
d.inBody = true
|
||||
if err := d.inner.ReadStruct(d.schema); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
ms, err := d.inner.ReadStructMember()
|
||||
if ms == nil {
|
||||
d.depth--
|
||||
}
|
||||
|
||||
return ms, err
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadString(s *smithy.Schema, v *string) error {
|
||||
if d.inBindings {
|
||||
if isEventHeader(s) {
|
||||
hv := d.Message.Headers.Get(s.MemberName())
|
||||
if hv == nil {
|
||||
return nil
|
||||
}
|
||||
sv, ok := hv.(StringValue)
|
||||
if !ok {
|
||||
return fmt.Errorf("event header %q: expected string, got %T", s.MemberName(), hv)
|
||||
}
|
||||
*v = string(sv)
|
||||
return nil
|
||||
}
|
||||
if isEventPayload(s) {
|
||||
*v = string(d.Message.Payload)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return d.inner.ReadString(s, v)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadBool(s *smithy.Schema, v *bool) error {
|
||||
if d.inBindings && isEventHeader(s) {
|
||||
hv := d.Message.Headers.Get(s.MemberName())
|
||||
if hv == nil {
|
||||
return nil
|
||||
}
|
||||
bv, ok := hv.(BoolValue)
|
||||
if !ok {
|
||||
return fmt.Errorf("event header %q: expected bool, got %T", s.MemberName(), hv)
|
||||
}
|
||||
*v = bool(bv)
|
||||
return nil
|
||||
}
|
||||
return d.inner.ReadBool(s, v)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) readHeaderInt64(name string) (int64, bool, error) {
|
||||
hv := d.Message.Headers.Get(name)
|
||||
if hv == nil {
|
||||
return 0, false, nil
|
||||
}
|
||||
switch v := hv.(type) {
|
||||
case Int8Value:
|
||||
return int64(v), true, nil
|
||||
case Int16Value:
|
||||
return int64(v), true, nil
|
||||
case Int32Value:
|
||||
return int64(v), true, nil
|
||||
case Int64Value:
|
||||
return int64(v), true, nil
|
||||
default:
|
||||
return 0, false, fmt.Errorf("event header %q: expected integer, got %T", name, hv)
|
||||
}
|
||||
}
|
||||
|
||||
type intn interface {
|
||||
int8 | int16 | int32 | int64
|
||||
}
|
||||
|
||||
func readEventHeaderInt[T intn](d *ShapeDeserializer, s *smithy.Schema, v *T) error {
|
||||
n, ok, err := d.readHeaderInt64(s.MemberName())
|
||||
if err != nil || !ok {
|
||||
return err
|
||||
}
|
||||
*v = T(n)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadInt8(s *smithy.Schema, v *int8) error {
|
||||
if d.inBindings && isEventHeader(s) {
|
||||
return readEventHeaderInt(d, s, v)
|
||||
}
|
||||
return d.inner.ReadInt8(s, v)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadInt16(s *smithy.Schema, v *int16) error {
|
||||
if d.inBindings && isEventHeader(s) {
|
||||
return readEventHeaderInt(d, s, v)
|
||||
}
|
||||
return d.inner.ReadInt16(s, v)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadInt32(s *smithy.Schema, v *int32) error {
|
||||
if d.inBindings && isEventHeader(s) {
|
||||
return readEventHeaderInt(d, s, v)
|
||||
}
|
||||
return d.inner.ReadInt32(s, v)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadInt64(s *smithy.Schema, v *int64) error {
|
||||
if d.inBindings && isEventHeader(s) {
|
||||
return readEventHeaderInt(d, s, v)
|
||||
}
|
||||
return d.inner.ReadInt64(s, v)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadFloat32(s *smithy.Schema, v *float32) error {
|
||||
return d.inner.ReadFloat32(s, v)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadFloat64(s *smithy.Schema, v *float64) error {
|
||||
return d.inner.ReadFloat64(s, v)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadBlob(s *smithy.Schema, v *[]byte) error {
|
||||
if d.inBindings {
|
||||
if isEventHeader(s) {
|
||||
hv := d.Message.Headers.Get(s.MemberName())
|
||||
if hv == nil {
|
||||
return nil
|
||||
}
|
||||
bv, ok := hv.(BytesValue)
|
||||
if !ok {
|
||||
return fmt.Errorf("event header %q: expected bytes, got %T", s.MemberName(), hv)
|
||||
}
|
||||
*v = []byte(bv)
|
||||
return nil
|
||||
}
|
||||
if isEventPayload(s) {
|
||||
*v = d.Message.Payload
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return d.inner.ReadBlob(s, v)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadTime(s *smithy.Schema, v *time.Time) error {
|
||||
if d.inBindings && isEventHeader(s) {
|
||||
hv := d.Message.Headers.Get(s.MemberName())
|
||||
if hv == nil {
|
||||
return nil
|
||||
}
|
||||
tv, ok := hv.(TimestampValue)
|
||||
if !ok {
|
||||
return fmt.Errorf("event header %q: expected timestamp, got %T", s.MemberName(), hv)
|
||||
}
|
||||
*v = time.Time(tv)
|
||||
return nil
|
||||
}
|
||||
return d.inner.ReadTime(s, v)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadList(s *smithy.Schema) error {
|
||||
return d.inner.ReadList(s)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadListItem(s *smithy.Schema) (bool, error) {
|
||||
return d.inner.ReadListItem(s)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadMap(s *smithy.Schema) error {
|
||||
return d.inner.ReadMap(s)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadMapKey(s *smithy.Schema) (string, bool, error) {
|
||||
return d.inner.ReadMapKey(s)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadUnion(s *smithy.Schema) (*smithy.Schema, error) {
|
||||
return d.inner.ReadUnion(s)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadNil(s *smithy.Schema) (bool, error) {
|
||||
return d.inner.ReadNil(s)
|
||||
}
|
||||
|
||||
func (d *ShapeDeserializer) ReadDocument(s *smithy.Schema, v *document.Value) error {
|
||||
return d.inner.ReadDocument(s, v)
|
||||
}
|
||||
|
||||
func isEventBound(schema *smithy.Schema) bool {
|
||||
_, h := smithy.SchemaTrait[*traits.EventHeader](schema)
|
||||
_, p := smithy.SchemaTrait[*traits.EventPayload](schema)
|
||||
return h || p
|
||||
}
|
||||
|
||||
// ReadBigInt is unimplemented and will return an error.
|
||||
func (d *ShapeDeserializer) ReadBigInt(_ *smithy.Schema, _ *big.Int) error {
|
||||
return fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
// ReadBigFloat is unimplemented and will return an error.
|
||||
func (d *ShapeDeserializer) ReadBigFloat(_ *smithy.Schema, _ *big.Float) error {
|
||||
return fmt.Errorf("unimplemented")
|
||||
}
|
||||
Reference in New Issue
Block a user