Skip to content

Commit e876057

Browse files
Proper BinarySerializer & StructuredSerializer implementations for Event (cloudevents#61)
* WIP Signed-off-by: Francesco Guardiani <[email protected]> * Progress Signed-off-by: Francesco Guardiani <[email protected]> * Seems like everything works Signed-off-by: Francesco Guardiani <[email protected]> * fmt'ed more stuff Signed-off-by: Francesco Guardiani <[email protected]>
1 parent fc3790a commit e876057

File tree

16 files changed

+281
-183
lines changed

16 files changed

+281
-183
lines changed

cloudevents-sdk-actix-web/src/server_request.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ mod tests {
181181
//TODO this is required now because the message deserializer implictly set default values
182182
// As soon as this defaulting doesn't happen anymore, we can remove it (Issues #40/#41)
183183
.time(time)
184-
.data("application/json", j.clone())
184+
.data("application/json", j.to_string().into_bytes())
185185
.extension("someint", "10")
186186
.build()
187187
.unwrap();

cloudevents-sdk-reqwest/src/client_response.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ mod tests {
195195
// As soon as this defaulting doesn't happen anymore, we can remove it (Issues #40/#41)
196196
.time(time)
197197
.source(Url::from_str("http://localhost").unwrap())
198-
.data("application/json", j.clone())
198+
.data("application/json", j.to_string().into_bytes())
199199
.extension("someint", "10")
200200
.build()
201201
.unwrap();

src/event/data.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl Data {
4646
}
4747

4848
pub(crate) fn is_json_content_type(ct: &str) -> bool {
49-
ct == "application/json" || ct == "text/json" || ct.ends_with("+json")
49+
ct.starts_with("application/json") || ct.starts_with("text/json") || ct.ends_with("+json")
5050
}
5151

5252
impl Into<Data> for serde_json::Value {

src/event/message.rs

Lines changed: 104 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::message::{
66
BinaryDeserializer, BinarySerializer, MessageAttributeValue, Result, StructuredDeserializer,
77
StructuredSerializer,
88
};
9+
use crate::{EventBuilder, EventBuilderV03, EventBuilderV10};
910

1011
impl StructuredDeserializer for Event {
1112
fn deserialize_structured<R, V: StructuredSerializer<R>>(self, visitor: V) -> Result<R> {
@@ -37,10 +38,6 @@ pub(crate) trait AttributesDeserializer {
3738
fn deserialize_attributes<R: Sized, V: BinarySerializer<R>>(self, visitor: V) -> Result<V>;
3839
}
3940

40-
pub(crate) trait AttributesSerializer {
41-
fn serialize_attribute(&mut self, name: &str, value: MessageAttributeValue) -> Result<()>;
42-
}
43-
4441
impl AttributesDeserializer for Attributes {
4542
fn deserialize_attributes<R: Sized, V: BinarySerializer<R>>(self, visitor: V) -> Result<V> {
4643
match self {
@@ -50,50 +47,125 @@ impl AttributesDeserializer for Attributes {
5047
}
5148
}
5249

53-
impl AttributesSerializer for Attributes {
54-
fn serialize_attribute(&mut self, name: &str, value: MessageAttributeValue) -> Result<()> {
55-
match self {
56-
Attributes::V03(v03) => v03.serialize_attribute(name, value),
57-
Attributes::V10(v10) => v10.serialize_attribute(name, value),
58-
}
50+
pub(crate) trait AttributesSerializer {
51+
fn serialize_attribute(&mut self, name: &str, value: MessageAttributeValue) -> Result<()>;
52+
}
53+
54+
#[derive(Debug)]
55+
pub(crate) struct EventStructuredSerializer {}
56+
57+
impl StructuredSerializer<Event> for EventStructuredSerializer {
58+
fn set_structured_event(self, bytes: Vec<u8>) -> Result<Event> {
59+
Ok(serde_json::from_slice(&bytes)?)
5960
}
6061
}
6162

62-
impl StructuredSerializer<Event> for Event {
63-
fn set_structured_event(mut self, bytes: Vec<u8>) -> Result<Event> {
64-
let new_event: Event = serde_json::from_slice(&bytes)?;
65-
self.attributes = new_event.attributes;
66-
self.data = new_event.data;
67-
self.extensions = new_event.extensions;
68-
Ok(self)
63+
#[derive(Debug)]
64+
pub(crate) enum EventBinarySerializer {
65+
V10(EventBuilderV10),
66+
V03(EventBuilderV03),
67+
}
68+
69+
impl EventBinarySerializer {
70+
pub(crate) fn new() -> Self {
71+
EventBinarySerializer::V10(EventBuilderV10::new())
6972
}
7073
}
7174

72-
impl BinarySerializer<Event> for Event {
73-
fn set_spec_version(mut self, spec_version: SpecVersion) -> Result<Self> {
74-
match spec_version {
75-
SpecVersion::V03 => self.attributes = self.attributes.clone().into_v03(),
76-
SpecVersion::V10 => self.attributes = self.attributes.clone().into_v10(),
77-
}
78-
Ok(self)
75+
impl BinarySerializer<Event> for EventBinarySerializer {
76+
fn set_spec_version(self, spec_version: SpecVersion) -> Result<Self> {
77+
Ok(match spec_version {
78+
SpecVersion::V03 => EventBinarySerializer::V03(EventBuilderV03::new()),
79+
SpecVersion::V10 => EventBinarySerializer::V10(EventBuilderV10::new()),
80+
})
7981
}
8082

8183
fn set_attribute(mut self, name: &str, value: MessageAttributeValue) -> Result<Self> {
82-
self.attributes.serialize_attribute(name, value)?;
84+
match &mut self {
85+
EventBinarySerializer::V03(eb) => eb.serialize_attribute(name, value)?,
86+
EventBinarySerializer::V10(eb) => eb.serialize_attribute(name, value)?,
87+
}
8388
Ok(self)
8489
}
8590

86-
fn set_extension(mut self, name: &str, value: MessageAttributeValue) -> Result<Self> {
87-
self.extensions.insert(name.to_string(), value.into());
88-
Ok(self)
91+
fn set_extension(self, name: &str, value: MessageAttributeValue) -> Result<Self> {
92+
Ok(match self {
93+
EventBinarySerializer::V03(eb) => EventBinarySerializer::V03(eb.extension(name, value)),
94+
EventBinarySerializer::V10(eb) => EventBinarySerializer::V10(eb.extension(name, value)),
95+
})
8996
}
9097

91-
fn end_with_data(mut self, bytes: Vec<u8>) -> Result<Event> {
92-
self.data = Some(Data::from_binary(self.get_datacontenttype(), bytes)?);
93-
Ok(self)
98+
fn end_with_data(self, bytes: Vec<u8>) -> Result<Event> {
99+
Ok(match self {
100+
EventBinarySerializer::V03(eb) => {
101+
eb.data_without_content_type(Data::Binary(bytes)).build()
102+
}
103+
EventBinarySerializer::V10(eb) => {
104+
eb.data_without_content_type(Data::Binary(bytes)).build()
105+
}
106+
}?)
94107
}
95108

96109
fn end(self) -> Result<Event> {
97-
Ok(self)
110+
Ok(match self {
111+
EventBinarySerializer::V03(eb) => eb.build(),
112+
EventBinarySerializer::V10(eb) => eb.build(),
113+
}?)
114+
}
115+
}
116+
117+
#[cfg(test)]
118+
mod tests {
119+
use super::*;
120+
use crate::message::Error;
121+
122+
#[test]
123+
fn binary_deserializer_unrecognized_attribute_v03() {
124+
assert_eq!(
125+
Error::UnrecognizedAttributeName {
126+
name: "dataschema".to_string()
127+
}
128+
.to_string(),
129+
EventBinarySerializer::new()
130+
.set_spec_version(SpecVersion::V03)
131+
.unwrap()
132+
.set_attribute("dataschema", MessageAttributeValue::Boolean(true))
133+
.expect_err("Should return an error")
134+
.to_string()
135+
)
136+
}
137+
138+
#[test]
139+
fn binary_deserializer_missing_id() {
140+
assert_eq!(
141+
Error::EventBuilderError {
142+
source: crate::event::EventBuilderError::MissingRequiredAttribute {
143+
attribute_name: "id"
144+
},
145+
}
146+
.to_string(),
147+
EventBinarySerializer::new()
148+
.set_spec_version(SpecVersion::V10)
149+
.unwrap()
150+
.end()
151+
.unwrap_err()
152+
.to_string()
153+
)
154+
}
155+
156+
#[test]
157+
fn binary_deserializer_unrecognized_attribute_v10() {
158+
assert_eq!(
159+
Error::UnrecognizedAttributeName {
160+
name: "schemaurl".to_string()
161+
}
162+
.to_string(),
163+
EventBinarySerializer::new()
164+
.set_spec_version(SpecVersion::V10)
165+
.unwrap()
166+
.set_attribute("schemaurl", MessageAttributeValue::Boolean(true))
167+
.expect_err("Should return an error")
168+
.to_string()
169+
)
98170
}
99171
}

src/event/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ pub use builder::EventBuilder;
1717
pub use data::Data;
1818
pub use event::Event;
1919
pub use extensions::ExtensionValue;
20+
pub(crate) use message::EventBinarySerializer;
21+
pub(crate) use message::EventStructuredSerializer;
2022
pub use spec_version::InvalidSpecVersion;
2123
pub use spec_version::SpecVersion;
2224
pub use types::{TryIntoTime, TryIntoUrl};

src/event/v03/attributes.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::event::attributes::{
33
};
44
use crate::event::AttributesV10;
55
use crate::event::{AttributesReader, AttributesWriter, SpecVersion};
6+
use crate::message::{BinarySerializer, MessageAttributeValue};
67
use chrono::{DateTime, Utc};
78
use url::Url;
89
use uuid::Uuid;
@@ -184,6 +185,40 @@ impl AttributesConverter for Attributes {
184185
}
185186
}
186187

188+
impl crate::event::message::AttributesDeserializer for super::Attributes {
189+
fn deserialize_attributes<R: Sized, V: BinarySerializer<R>>(
190+
self,
191+
mut visitor: V,
192+
) -> crate::message::Result<V> {
193+
visitor = visitor.set_attribute("id", MessageAttributeValue::String(self.id))?;
194+
visitor = visitor.set_attribute("type", MessageAttributeValue::String(self.ty))?;
195+
visitor = visitor.set_attribute("source", MessageAttributeValue::UriRef(self.source))?;
196+
if self.datacontenttype.is_some() {
197+
visitor = visitor.set_attribute(
198+
"datacontenttype",
199+
MessageAttributeValue::String(self.datacontenttype.unwrap()),
200+
)?;
201+
}
202+
if self.schemaurl.is_some() {
203+
visitor = visitor.set_attribute(
204+
"schemaurl",
205+
MessageAttributeValue::Uri(self.schemaurl.unwrap()),
206+
)?;
207+
}
208+
if self.subject.is_some() {
209+
visitor = visitor.set_attribute(
210+
"subject",
211+
MessageAttributeValue::String(self.subject.unwrap()),
212+
)?;
213+
}
214+
if self.time.is_some() {
215+
visitor = visitor
216+
.set_attribute("time", MessageAttributeValue::DateTime(self.time.unwrap()))?;
217+
}
218+
Ok(visitor)
219+
}
220+
}
221+
187222
#[cfg(test)]
188223
mod tests {
189224
use super::*;

src/event/v03/builder.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ use super::Attributes as AttributesV03;
22
use crate::event::{
33
Attributes, Data, Event, EventBuilderError, ExtensionValue, TryIntoTime, TryIntoUrl,
44
};
5+
use crate::message::MessageAttributeValue;
56
use chrono::{DateTime, Utc};
67
use std::collections::HashMap;
8+
use std::convert::TryInto;
79
use url::Url;
810

911
/// Builder to create a CloudEvent V0.3
10-
#[derive(Clone)]
12+
#[derive(Clone, Debug)]
1113
pub struct EventBuilder {
1214
id: Option<String>,
1315
ty: Option<String>,
@@ -73,6 +75,11 @@ impl EventBuilder {
7375
self
7476
}
7577

78+
pub(crate) fn data_without_content_type(mut self, data: impl Into<Data>) -> Self {
79+
self.data = Some(data.into());
80+
self
81+
}
82+
7683
pub fn data(mut self, datacontenttype: impl Into<String>, data: impl Into<Data>) -> Self {
7784
self.datacontenttype = Some(datacontenttype.into());
7885
self.data = Some(data.into());
@@ -173,3 +180,27 @@ impl crate::event::builder::EventBuilder for EventBuilder {
173180
}
174181
}
175182
}
183+
184+
impl crate::event::message::AttributesSerializer for EventBuilder {
185+
fn serialize_attribute(
186+
&mut self,
187+
name: &str,
188+
value: MessageAttributeValue,
189+
) -> crate::message::Result<()> {
190+
match name {
191+
"id" => self.id = Some(value.to_string()),
192+
"type" => self.ty = Some(value.to_string()),
193+
"source" => self.source = Some(value.try_into()?),
194+
"datacontenttype" => self.datacontenttype = Some(value.to_string()),
195+
"schemaurl" => self.schemaurl = Some(value.try_into()?),
196+
"subject" => self.subject = Some(value.to_string()),
197+
"time" => self.time = Some(value.try_into()?),
198+
_ => {
199+
return Err(crate::message::Error::UnrecognizedAttributeName {
200+
name: name.to_string(),
201+
})
202+
}
203+
};
204+
Ok(())
205+
}
206+
}

src/event/v03/message.rs

Lines changed: 0 additions & 53 deletions
This file was deleted.

src/event/v03/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
mod attributes;
22
mod builder;
33
mod format;
4-
mod message;
54

65
pub use attributes::Attributes;
76
pub(crate) use attributes::AttributesIntoIterator;

0 commit comments

Comments
 (0)