1
1
//! Implements AMQP 1.0 binding for CloudEvents
2
2
3
+ use std:: collections:: HashMap ;
3
4
use std:: convert:: TryFrom ;
4
5
5
6
use fe2o3_amqp_lib:: types:: messaging:: {
6
7
ApplicationProperties , Body , Data as AmqpData , Message , Properties ,
7
8
} ;
8
9
use fe2o3_amqp_lib:: types:: primitives:: { Binary , SimpleValue , Symbol , Timestamp , Value } ;
9
10
10
- use crate :: event:: { AttributeValue , Attributes } ;
11
+ use crate :: event:: { AttributeValue , Attributes , ExtensionValue } ;
11
12
use crate :: message:: { Error , MessageAttributeValue } ;
12
- use crate :: { Event } ;
13
+ use crate :: { Event , AttributesReader , Data } ;
14
+
15
+ use self :: extensions:: ExtensionsHandler ;
16
+
17
+ pub mod extensions;
13
18
14
19
/// Type alias for an AMQP 1.0 message
15
20
///
@@ -20,19 +25,36 @@ pub type AmqpMessage = Message<Value>;
20
25
21
26
pub type AmqpBody = Body < Value > ;
22
27
28
+ pub type Extensions = HashMap < String , ExtensionValue > ;
29
+
23
30
pub struct AmqpCloudEvent {
24
- properties : Properties ,
31
+ content_type : Option < Symbol > ,
25
32
application_properties : ApplicationProperties ,
26
33
body : AmqpBody ,
27
34
}
28
35
36
+ impl AmqpCloudEvent {
37
+ pub fn with_extensions_handler < F > ( handler : F ) -> ExtensionsHandler < F >
38
+ where
39
+ F : FnOnce ( Extensions ) -> AmqpMessage
40
+ {
41
+ ExtensionsHandler :: new ( handler)
42
+ }
43
+
44
+ pub fn from_event ( event : Event ) -> Result < Self , Error > {
45
+ Self :: try_from ( event)
46
+ }
47
+ }
48
+
29
49
impl From < AmqpCloudEvent > for AmqpMessage {
30
50
fn from ( event : AmqpCloudEvent ) -> Self {
51
+ let mut properties = Properties :: default ( ) ;
52
+ properties. content_type = event. content_type ;
31
53
Message {
32
54
header : None ,
33
55
delivery_annotations : None ,
34
56
message_annotations : None ,
35
- properties : Some ( event . properties ) ,
57
+ properties : Some ( properties) ,
36
58
application_properties : Some ( event. application_properties ) ,
37
59
body : event. body ,
38
60
footer : None ,
@@ -48,12 +70,13 @@ impl TryFrom<AmqpMessage> for AmqpCloudEvent {
48
70
Body :: Data ( data) => Body :: Data ( data) ,
49
71
_ => return Err ( Error :: WrongEncoding { } ) ,
50
72
} ;
51
- let properties = value. properties . ok_or ( Error :: WrongEncoding { } ) ?;
73
+ let content_type = value. properties . ok_or ( Error :: WrongEncoding { } ) ?
74
+ . content_type . take ( ) ;
52
75
let application_properties = value
53
76
. application_properties
54
77
. ok_or ( Error :: WrongEncoding { } ) ?;
55
78
Ok ( Self {
56
- properties ,
79
+ content_type ,
57
80
application_properties,
58
81
body,
59
82
} )
@@ -140,43 +163,48 @@ impl From<MessageAttributeValue> for Value {
140
163
impl TryFrom < Event > for AmqpCloudEvent {
141
164
type Error = Error ;
142
165
143
- fn try_from ( mut event : Event ) -> Result < Self , Self :: Error > {
144
- let mut properties = Properties :: default ( ) ;
145
- properties. content_type = match & mut event. attributes {
146
- Attributes :: V03 ( attributes) => attributes. datacontenttype . take ( ) ,
147
- Attributes :: V10 ( attributes) => attributes. datacontenttype . take ( ) ,
148
- } . map ( Symbol :: from) ;
149
-
150
- let mut application_properties = ApplicationProperties :: default ( ) ;
151
- for ( key, value) in event. attributes . iter ( ) {
152
- if key == "datacontenttype" {
153
- continue ;
154
- } else {
155
- let key = format ! ( "cloudEvents:{}" , key) ;
156
- application_properties. insert ( key, SimpleValue :: from ( value) ) ;
157
- }
158
- }
159
-
160
- let body = match event. data {
161
- Some ( data) => match data {
162
- crate :: Data :: Binary ( data) => Body :: Data ( AmqpData ( Binary :: from ( data) ) ) ,
163
- crate :: Data :: String ( val) => Body :: Data ( AmqpData ( Binary :: from ( val) ) ) ,
164
- crate :: Data :: Json ( val) => {
165
- let bytes = serde_json:: to_vec ( & val) ?;
166
- Body :: Data ( AmqpData ( Binary :: from ( bytes) ) )
167
- } ,
168
- } ,
169
- None => AmqpBody :: Nothing ,
170
- } ;
166
+ fn try_from ( event : Event ) -> Result < Self , Self :: Error > {
167
+ let ( content_type, application_properties) = from_event_attributes ( event. attributes ) ;
168
+ let body = from_event_data ( event. data ) ?;
171
169
172
170
Ok ( Self {
173
- properties ,
171
+ content_type ,
174
172
application_properties,
175
173
body,
176
174
} )
177
175
}
178
176
}
179
177
178
+ fn from_event_attributes ( attributes : Attributes ) -> ( Option < Symbol > , ApplicationProperties ) {
179
+ let content_type = attributes. datacontenttype ( ) . map ( Symbol :: from) ;
180
+
181
+ let mut application_properties = ApplicationProperties :: default ( ) ;
182
+ for ( key, value) in attributes. iter ( ) {
183
+ if key == "datacontenttype" {
184
+ continue ;
185
+ } else {
186
+ let key = format ! ( "cloudEvents:{}" , key) ;
187
+ application_properties. insert ( key, SimpleValue :: from ( value) ) ;
188
+ }
189
+ }
190
+ ( content_type, application_properties)
191
+ }
192
+
193
+ fn from_event_data ( data : Option < Data > ) -> Result < AmqpBody , Error > {
194
+ let body = match data {
195
+ Some ( data) => match data {
196
+ crate :: Data :: Binary ( data) => Body :: Data ( AmqpData ( Binary :: from ( data) ) ) ,
197
+ crate :: Data :: String ( val) => Body :: Data ( AmqpData ( Binary :: from ( val) ) ) ,
198
+ crate :: Data :: Json ( val) => {
199
+ let bytes = serde_json:: to_vec ( & val) ?;
200
+ Body :: Data ( AmqpData ( Binary :: from ( bytes) ) )
201
+ } ,
202
+ } ,
203
+ None => AmqpBody :: Nothing ,
204
+ } ;
205
+ Ok ( body)
206
+ }
207
+
180
208
// impl BinarySerializer<AmqpCloudEvent> for AmqpCloudEvent {
181
209
// fn set_spec_version(mut self, spec_version: SpecVersion) -> crate::message::Result<Self> {
182
210
// let key = String::from("cloudEvents:specversion");
0 commit comments