|
| 1 | +// Copyright (c) Microsoft Corporation. All rights reserved. |
| 2 | +// Licensed under the MIT License. |
| 3 | + |
| 4 | +package azeventhubs |
| 5 | + |
| 6 | +import ( |
| 7 | + "time" |
| 8 | + |
| 9 | + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" |
| 10 | +) |
| 11 | + |
| 12 | +// AMQPAnnotatedMessage represents the AMQP message, as received from Event Hubs. |
| 13 | +// For details about these properties, refer to the AMQP specification: |
| 14 | +// |
| 15 | +// https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#section-message-format |
| 16 | +// |
| 17 | +// Some fields in this struct are typed 'any', which means they will accept AMQP primitives, or in some |
| 18 | +// cases slices and maps. |
| 19 | +// |
| 20 | +// AMQP simple types include: |
| 21 | +// - int (any size), uint (any size) |
| 22 | +// - float (any size) |
| 23 | +// - string |
| 24 | +// - bool |
| 25 | +// - time.Time |
| 26 | +type AMQPAnnotatedMessage struct { |
| 27 | + // ApplicationProperties corresponds to the "application-properties" section of an AMQP message. |
| 28 | + // |
| 29 | + // The values of the map are restricted to AMQP simple types, as listed in the comment for AMQPAnnotatedMessage. |
| 30 | + ApplicationProperties map[string]any |
| 31 | + |
| 32 | + // Body represents the body of an AMQP message. |
| 33 | + Body AMQPAnnotatedMessageBody |
| 34 | + |
| 35 | + // DeliveryAnnotations corresponds to the "delivery-annotations" section in an AMQP message. |
| 36 | + // |
| 37 | + // The values of the map are restricted to AMQP simple types, as listed in the comment for AMQPAnnotatedMessage. |
| 38 | + DeliveryAnnotations map[any]any |
| 39 | + |
| 40 | + // DeliveryTag corresponds to the delivery-tag property of the TRANSFER frame |
| 41 | + // for this message. |
| 42 | + DeliveryTag []byte |
| 43 | + |
| 44 | + // Footer is the transport footers for this AMQP message. |
| 45 | + // |
| 46 | + // The values of the map are restricted to AMQP simple types, as listed in the comment for AMQPAnnotatedMessage. |
| 47 | + Footer map[any]any |
| 48 | + |
| 49 | + // Header is the transport headers for this AMQP message. |
| 50 | + Header *AMQPAnnotatedMessageHeader |
| 51 | + |
| 52 | + // MessageAnnotations corresponds to the message-annotations section of an AMQP message. |
| 53 | + // |
| 54 | + // The values of the map are restricted to AMQP simple types, as listed in the comment for AMQPAnnotatedMessage. |
| 55 | + MessageAnnotations map[any]any |
| 56 | + |
| 57 | + // Properties corresponds to the properties section of an AMQP message. |
| 58 | + Properties *AMQPAnnotatedMessageProperties |
| 59 | +} |
| 60 | + |
| 61 | +// AMQPAnnotatedMessageProperties represents the properties of an AMQP message. |
| 62 | +// See here for more details: |
| 63 | +// http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-properties |
| 64 | +type AMQPAnnotatedMessageProperties struct { |
| 65 | + // AbsoluteExpiryTime corresponds to the 'absolute-expiry-time' property. |
| 66 | + AbsoluteExpiryTime *time.Time |
| 67 | + |
| 68 | + // ContentEncoding corresponds to the 'content-encoding' property. |
| 69 | + ContentEncoding *string |
| 70 | + |
| 71 | + // ContentType corresponds to the 'content-type' property |
| 72 | + ContentType *string |
| 73 | + |
| 74 | + // CorrelationID corresponds to the 'correlation-id' property. |
| 75 | + // The type of CorrelationID can be a uint64, UUID, []byte, or a string |
| 76 | + CorrelationID any |
| 77 | + |
| 78 | + // CreationTime corresponds to the 'creation-time' property. |
| 79 | + CreationTime *time.Time |
| 80 | + |
| 81 | + // GroupID corresponds to the 'group-id' property. |
| 82 | + GroupID *string |
| 83 | + |
| 84 | + // GroupSequence corresponds to the 'group-sequence' property. |
| 85 | + GroupSequence *uint32 |
| 86 | + |
| 87 | + // MessageID corresponds to the 'message-id' property. |
| 88 | + // The type of MessageID can be a uint64, UUID, []byte, or string |
| 89 | + MessageID any |
| 90 | + |
| 91 | + // ReplyTo corresponds to the 'reply-to' property. |
| 92 | + ReplyTo *string |
| 93 | + |
| 94 | + // ReplyToGroupID corresponds to the 'reply-to-group-id' property. |
| 95 | + ReplyToGroupID *string |
| 96 | + |
| 97 | + // Subject corresponds to the 'subject' property. |
| 98 | + Subject *string |
| 99 | + |
| 100 | + // To corresponds to the 'to' property. |
| 101 | + To *string |
| 102 | + |
| 103 | + // UserID corresponds to the 'user-id' property. |
| 104 | + UserID []byte |
| 105 | +} |
| 106 | + |
| 107 | +// AMQPAnnotatedMessageBody represents the body of an AMQP message. |
| 108 | +// Only one of these fields can be used a a time. They are mutually exclusive. |
| 109 | +type AMQPAnnotatedMessageBody struct { |
| 110 | + // Data is encoded/decoded as multiple data sections in the body. |
| 111 | + Data [][]byte |
| 112 | + |
| 113 | + // Sequence is encoded/decoded as one or more amqp-sequence sections in the body. |
| 114 | + // |
| 115 | + // The values of the slices are are restricted to AMQP simple types, as listed in the comment for AMQPAnnotatedMessage. |
| 116 | + Sequence [][]any |
| 117 | + |
| 118 | + // Value is encoded/decoded as the amqp-value section in the body. |
| 119 | + // |
| 120 | + // The type of Value can be any of the AMQP simple types, as listed in the comment for AMQPAnnotatedMessage, |
| 121 | + // as well as slices or maps of AMQP simple types. |
| 122 | + Value any |
| 123 | +} |
| 124 | + |
| 125 | +// AMQPAnnotatedMessageHeader carries standard delivery details about the transfer |
| 126 | +// of a message. |
| 127 | +// See https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-header |
| 128 | +// for more details. |
| 129 | +type AMQPAnnotatedMessageHeader struct { |
| 130 | + // DeliveryCount is the number of unsuccessful previous attempts to deliver this message. |
| 131 | + // It corresponds to the 'delivery-count' property. |
| 132 | + DeliveryCount uint32 |
| 133 | + |
| 134 | + // Durable corresponds to the 'durable' property. |
| 135 | + Durable bool |
| 136 | + |
| 137 | + // FirstAcquirer corresponds to the 'first-acquirer' property. |
| 138 | + FirstAcquirer bool |
| 139 | + |
| 140 | + // Priority corresponds to the 'priority' property. |
| 141 | + Priority uint8 |
| 142 | + |
| 143 | + // TTL corresponds to the 'ttl' property. |
| 144 | + TTL time.Duration |
| 145 | +} |
| 146 | + |
| 147 | +// toAMQPMessage converts between our (azeventhubs) AMQP message |
| 148 | +// to the underlying message used by go-amqp. |
| 149 | +func (am *AMQPAnnotatedMessage) toAMQPMessage() *amqp.Message { |
| 150 | + var header *amqp.MessageHeader |
| 151 | + |
| 152 | + if am.Header != nil { |
| 153 | + header = &amqp.MessageHeader{ |
| 154 | + DeliveryCount: am.Header.DeliveryCount, |
| 155 | + Durable: am.Header.Durable, |
| 156 | + FirstAcquirer: am.Header.FirstAcquirer, |
| 157 | + Priority: am.Header.Priority, |
| 158 | + TTL: am.Header.TTL, |
| 159 | + } |
| 160 | + } |
| 161 | + |
| 162 | + var properties *amqp.MessageProperties |
| 163 | + |
| 164 | + if am.Properties != nil { |
| 165 | + properties = &amqp.MessageProperties{ |
| 166 | + AbsoluteExpiryTime: am.Properties.AbsoluteExpiryTime, |
| 167 | + ContentEncoding: am.Properties.ContentEncoding, |
| 168 | + ContentType: am.Properties.ContentType, |
| 169 | + CorrelationID: am.Properties.CorrelationID, |
| 170 | + CreationTime: am.Properties.CreationTime, |
| 171 | + GroupID: am.Properties.GroupID, |
| 172 | + GroupSequence: am.Properties.GroupSequence, |
| 173 | + MessageID: am.Properties.MessageID, |
| 174 | + ReplyTo: am.Properties.ReplyTo, |
| 175 | + ReplyToGroupID: am.Properties.ReplyToGroupID, |
| 176 | + Subject: am.Properties.Subject, |
| 177 | + To: am.Properties.To, |
| 178 | + UserID: am.Properties.UserID, |
| 179 | + } |
| 180 | + } else { |
| 181 | + properties = &amqp.MessageProperties{} |
| 182 | + } |
| 183 | + |
| 184 | + var footer amqp.Annotations |
| 185 | + |
| 186 | + if am.Footer != nil { |
| 187 | + footer = (amqp.Annotations)(am.Footer) |
| 188 | + } |
| 189 | + |
| 190 | + return &amqp.Message{ |
| 191 | + Annotations: copyAnnotations(am.MessageAnnotations), |
| 192 | + ApplicationProperties: am.ApplicationProperties, |
| 193 | + Data: am.Body.Data, |
| 194 | + DeliveryAnnotations: amqp.Annotations(am.DeliveryAnnotations), |
| 195 | + DeliveryTag: am.DeliveryTag, |
| 196 | + Footer: footer, |
| 197 | + Header: header, |
| 198 | + Properties: properties, |
| 199 | + Sequence: am.Body.Sequence, |
| 200 | + Value: am.Body.Value, |
| 201 | + } |
| 202 | +} |
| 203 | + |
| 204 | +func copyAnnotations(src map[any]any) amqp.Annotations { |
| 205 | + if src == nil { |
| 206 | + return amqp.Annotations{} |
| 207 | + } |
| 208 | + |
| 209 | + dest := amqp.Annotations{} |
| 210 | + |
| 211 | + for k, v := range src { |
| 212 | + dest[k] = v |
| 213 | + } |
| 214 | + |
| 215 | + return dest |
| 216 | +} |
| 217 | + |
| 218 | +func newAMQPAnnotatedMessage(goAMQPMessage *amqp.Message) *AMQPAnnotatedMessage { |
| 219 | + var header *AMQPAnnotatedMessageHeader |
| 220 | + |
| 221 | + if goAMQPMessage.Header != nil { |
| 222 | + header = &AMQPAnnotatedMessageHeader{ |
| 223 | + DeliveryCount: goAMQPMessage.Header.DeliveryCount, |
| 224 | + Durable: goAMQPMessage.Header.Durable, |
| 225 | + FirstAcquirer: goAMQPMessage.Header.FirstAcquirer, |
| 226 | + Priority: goAMQPMessage.Header.Priority, |
| 227 | + TTL: goAMQPMessage.Header.TTL, |
| 228 | + } |
| 229 | + } |
| 230 | + |
| 231 | + var properties *AMQPAnnotatedMessageProperties |
| 232 | + |
| 233 | + if goAMQPMessage.Properties != nil { |
| 234 | + properties = &AMQPAnnotatedMessageProperties{ |
| 235 | + AbsoluteExpiryTime: goAMQPMessage.Properties.AbsoluteExpiryTime, |
| 236 | + ContentEncoding: goAMQPMessage.Properties.ContentEncoding, |
| 237 | + ContentType: goAMQPMessage.Properties.ContentType, |
| 238 | + CorrelationID: goAMQPMessage.Properties.CorrelationID, |
| 239 | + CreationTime: goAMQPMessage.Properties.CreationTime, |
| 240 | + GroupID: goAMQPMessage.Properties.GroupID, |
| 241 | + GroupSequence: goAMQPMessage.Properties.GroupSequence, |
| 242 | + MessageID: goAMQPMessage.Properties.MessageID, |
| 243 | + ReplyTo: goAMQPMessage.Properties.ReplyTo, |
| 244 | + ReplyToGroupID: goAMQPMessage.Properties.ReplyToGroupID, |
| 245 | + Subject: goAMQPMessage.Properties.Subject, |
| 246 | + To: goAMQPMessage.Properties.To, |
| 247 | + UserID: goAMQPMessage.Properties.UserID, |
| 248 | + } |
| 249 | + } |
| 250 | + |
| 251 | + var footer map[any]any |
| 252 | + |
| 253 | + if goAMQPMessage.Footer != nil { |
| 254 | + footer = (map[any]any)(goAMQPMessage.Footer) |
| 255 | + } |
| 256 | + |
| 257 | + return &AMQPAnnotatedMessage{ |
| 258 | + MessageAnnotations: map[any]any(goAMQPMessage.Annotations), |
| 259 | + ApplicationProperties: goAMQPMessage.ApplicationProperties, |
| 260 | + Body: AMQPAnnotatedMessageBody{ |
| 261 | + Data: goAMQPMessage.Data, |
| 262 | + Sequence: goAMQPMessage.Sequence, |
| 263 | + Value: goAMQPMessage.Value, |
| 264 | + }, |
| 265 | + DeliveryAnnotations: map[any]any(goAMQPMessage.DeliveryAnnotations), |
| 266 | + DeliveryTag: goAMQPMessage.DeliveryTag, |
| 267 | + Footer: footer, |
| 268 | + Header: header, |
| 269 | + Properties: properties, |
| 270 | + } |
| 271 | +} |
0 commit comments