serializer.go (6167B)
1 package eventstream 2 3 import ( 4 "math/big" 5 "time" 6 7 "github.com/aws/smithy-go" 8 "github.com/aws/smithy-go/document" 9 "github.com/aws/smithy-go/traits" 10 ) 11 12 // ShapeSerializer wraps a [smithy.ShapeSerializer], much like the internal 13 // httpbinding serializer, to handle event stream message binding traits. 14 type ShapeSerializer struct { 15 Message *Message 16 17 inner smithy.ShapeSerializer 18 contentType string // may be inflenced by bindings 19 depth int 20 hasBody bool 21 } 22 23 var _ smithy.ShapeSerializer = (*ShapeSerializer)(nil) 24 25 // NewShapeSerializer returns a serializer for a single Message. 26 func NewShapeSerializer(msg *Message, inner smithy.ShapeSerializer) *ShapeSerializer { 27 return &ShapeSerializer{ 28 Message: msg, 29 inner: inner, 30 } 31 } 32 33 // ContentType returns the resolved content type for the event message payload 34 // after serialization, which may be affected by bindings. 35 func (s *ShapeSerializer) ContentType() string { 36 return s.contentType 37 } 38 39 // Bytes returns the serialized body bytes. 40 func (s *ShapeSerializer) Bytes() []byte { 41 return s.inner.Bytes() 42 } 43 44 // WriteBool implements [smithy.ShapeSerializer]. 45 func (s *ShapeSerializer) WriteBool(schema *smithy.Schema, v bool) { 46 if isEventHeader(schema) { 47 s.Message.Headers.Set(schema.MemberName(), BoolValue(v)) 48 return 49 } 50 s.inner.WriteBool(schema, v) 51 } 52 53 // WriteInt8 implements [smithy.ShapeSerializer]. 54 func (s *ShapeSerializer) WriteInt8(schema *smithy.Schema, v int8) { 55 if isEventHeader(schema) { 56 s.Message.Headers.Set(schema.MemberName(), Int8Value(v)) 57 return 58 } 59 s.inner.WriteInt8(schema, v) 60 } 61 62 // WriteInt16 implements [smithy.ShapeSerializer]. 63 func (s *ShapeSerializer) WriteInt16(schema *smithy.Schema, v int16) { 64 if isEventHeader(schema) { 65 s.Message.Headers.Set(schema.MemberName(), Int16Value(v)) 66 return 67 } 68 s.inner.WriteInt16(schema, v) 69 } 70 71 // WriteInt32 implements [smithy.ShapeSerializer]. 72 func (s *ShapeSerializer) WriteInt32(schema *smithy.Schema, v int32) { 73 if isEventHeader(schema) { 74 s.Message.Headers.Set(schema.MemberName(), Int32Value(v)) 75 return 76 } 77 s.inner.WriteInt32(schema, v) 78 } 79 80 // WriteInt64 implements [smithy.ShapeSerializer]. 81 func (s *ShapeSerializer) WriteInt64(schema *smithy.Schema, v int64) { 82 if isEventHeader(schema) { 83 s.Message.Headers.Set(schema.MemberName(), Int64Value(v)) 84 return 85 } 86 s.inner.WriteInt64(schema, v) 87 } 88 89 // WriteFloat32 implements [smithy.ShapeSerializer]. 90 func (s *ShapeSerializer) WriteFloat32(schema *smithy.Schema, v float32) { 91 s.inner.WriteFloat32(schema, v) 92 } 93 94 // WriteFloat64 implements [smithy.ShapeSerializer]. 95 func (s *ShapeSerializer) WriteFloat64(schema *smithy.Schema, v float64) { 96 s.inner.WriteFloat64(schema, v) 97 } 98 99 // WriteString implements [smithy.ShapeSerializer]. 100 func (s *ShapeSerializer) WriteString(schema *smithy.Schema, v string) { 101 if isEventHeader(schema) { 102 s.Message.Headers.Set(schema.MemberName(), StringValue(v)) 103 return 104 } 105 if isEventPayload(schema) { 106 s.Message.Payload = []byte(v) 107 s.contentType = "text/plain" 108 return 109 } 110 s.inner.WriteString(schema, v) 111 } 112 113 // WriteBlob implements [smithy.ShapeSerializer]. 114 func (s *ShapeSerializer) WriteBlob(schema *smithy.Schema, v []byte) { 115 if isEventHeader(schema) { 116 s.Message.Headers.Set(schema.MemberName(), BytesValue(v)) 117 return 118 } 119 if isEventPayload(schema) { 120 s.Message.Payload = v 121 s.contentType = "application/octet-stream" 122 return 123 } 124 s.inner.WriteBlob(schema, v) 125 } 126 127 // WriteTime implements [smithy.ShapeSerializer]. 128 func (s *ShapeSerializer) WriteTime(schema *smithy.Schema, v time.Time) { 129 if isEventHeader(schema) { 130 s.Message.Headers.Set(schema.MemberName(), TimestampValue(v)) 131 return 132 } 133 s.inner.WriteTime(schema, v) 134 } 135 136 // WriteBigInt implements [smithy.ShapeSerializer]. 137 func (s *ShapeSerializer) WriteBigInt(schema *smithy.Schema, v *big.Int) { 138 s.inner.WriteBigInt(schema, v) 139 } 140 141 // WriteBigFloat implements [smithy.ShapeSerializer]. 142 func (s *ShapeSerializer) WriteBigFloat(schema *smithy.Schema, v *big.Float) { 143 s.inner.WriteBigFloat(schema, v) 144 } 145 146 // WriteStruct implements [smithy.ShapeSerializer]. 147 func (s *ShapeSerializer) WriteStruct(schema *smithy.Schema) { 148 s.depth++ 149 if s.depth > 1 { 150 s.inner.WriteStruct(schema) 151 return 152 } 153 // At depth 1 (the event struct itself), start a JSON body if there are 154 // implicit body members (members without @eventHeader or @eventPayload). 155 for _, m := range schema.Members() { 156 if !isEventBound(m) { 157 s.inner.WriteStruct(schema) 158 s.hasBody = true 159 return 160 } 161 } 162 } 163 164 // CloseStruct implements [smithy.ShapeSerializer]. 165 func (s *ShapeSerializer) CloseStruct() { 166 if s.depth > 1 || s.hasBody { 167 s.inner.CloseStruct() 168 } 169 if s.depth == 1 { 170 s.hasBody = false 171 } 172 s.depth-- 173 } 174 175 // WriteUnion implements [smithy.ShapeSerializer]. 176 func (s *ShapeSerializer) WriteUnion(schema, variant *smithy.Schema) { 177 s.inner.WriteUnion(schema, variant) 178 } 179 180 // CloseUnion implements [smithy.ShapeSerializer]. 181 func (s *ShapeSerializer) CloseUnion() { 182 s.inner.CloseUnion() 183 } 184 185 // WriteNil implements [smithy.ShapeSerializer]. 186 func (s *ShapeSerializer) WriteNil(schema *smithy.Schema) { 187 s.inner.WriteNil(schema) 188 } 189 190 // WriteList implements [smithy.ShapeSerializer]. 191 func (s *ShapeSerializer) WriteList(schema *smithy.Schema) { 192 s.inner.WriteList(schema) 193 } 194 195 // CloseList implements [smithy.ShapeSerializer]. 196 func (s *ShapeSerializer) CloseList() { 197 s.inner.CloseList() 198 } 199 200 // WriteMap implements [smithy.ShapeSerializer]. 201 func (s *ShapeSerializer) WriteMap(schema *smithy.Schema) { 202 s.inner.WriteMap(schema) 203 } 204 205 // WriteKey implements [smithy.ShapeSerializer]. 206 func (s *ShapeSerializer) WriteKey(schema *smithy.Schema, key string) { 207 s.inner.WriteKey(schema, key) 208 } 209 210 // CloseMap implements [smithy.ShapeSerializer]. 211 func (s *ShapeSerializer) CloseMap() { 212 s.inner.CloseMap() 213 } 214 215 // WriteDocument implements [smithy.ShapeSerializer]. 216 func (s *ShapeSerializer) WriteDocument(schema *smithy.Schema, v document.Value) { 217 s.inner.WriteDocument(schema, v) 218 } 219 220 func isEventHeader(schema *smithy.Schema) bool { 221 _, ok := smithy.SchemaTrait[*traits.EventHeader](schema) 222 return ok 223 } 224 225 func isEventPayload(schema *smithy.Schema) bool { 226 _, ok := smithy.SchemaTrait[*traits.EventPayload](schema) 227 return ok 228 }