Cleanup to follow C-GETTER (#88)

* Cleanup to follow C-GETTER

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Cleanup to follow C-GETTER
Implemented Debug in event::Data
Exposing event::Data in main cloudevents export
Fixed rebase errors with previous pr

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* cargo fmt

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>
This commit is contained in:
Francesco Guardiani 2020-10-21 12:04:32 +02:00 committed by GitHub
parent 1858a1caa5
commit c926188d78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 134 additions and 148 deletions

View File

@ -46,21 +46,21 @@ impl fmt::Display for AttributeValue<'_> {
/// Trait to get [CloudEvents Context attributes](https://github.com/cloudevents/spec/blob/master/spec.md#context-attributes).
pub trait AttributesReader {
/// Get the [id](https://github.com/cloudevents/spec/blob/master/spec.md#id).
fn get_id(&self) -> &str;
fn id(&self) -> &str;
/// Get the [source](https://github.com/cloudevents/spec/blob/master/spec.md#source-1).
fn get_source(&self) -> &Url;
fn source(&self) -> &Url;
/// Get the [specversion](https://github.com/cloudevents/spec/blob/master/spec.md#specversion).
fn get_specversion(&self) -> SpecVersion;
fn specversion(&self) -> SpecVersion;
/// Get the [type](https://github.com/cloudevents/spec/blob/master/spec.md#type).
fn get_type(&self) -> &str;
fn ty(&self) -> &str;
/// Get the [datacontenttype](https://github.com/cloudevents/spec/blob/master/spec.md#datacontenttype).
fn get_datacontenttype(&self) -> Option<&str>;
fn datacontenttype(&self) -> Option<&str>;
/// Get the [dataschema](https://github.com/cloudevents/spec/blob/master/spec.md#dataschema).
fn get_dataschema(&self) -> Option<&Url>;
fn dataschema(&self) -> Option<&Url>;
/// Get the [subject](https://github.com/cloudevents/spec/blob/master/spec.md#subject).
fn get_subject(&self) -> Option<&str>;
fn subject(&self) -> Option<&str>;
/// Get the [time](https://github.com/cloudevents/spec/blob/master/spec.md#time).
fn get_time(&self) -> Option<&DateTime<Utc>>;
fn time(&self) -> Option<&DateTime<Utc>>;
}
/// Trait to set [CloudEvents Context attributes](https://github.com/cloudevents/spec/blob/master/spec.md#context-attributes).
@ -117,59 +117,59 @@ pub enum Attributes {
}
impl AttributesReader for Attributes {
fn get_id(&self) -> &str {
fn id(&self) -> &str {
match self {
Attributes::V03(a) => a.get_id(),
Attributes::V10(a) => a.get_id(),
Attributes::V03(a) => a.id(),
Attributes::V10(a) => a.id(),
}
}
fn get_source(&self) -> &Url {
fn source(&self) -> &Url {
match self {
Attributes::V03(a) => a.get_source(),
Attributes::V10(a) => a.get_source(),
Attributes::V03(a) => a.source(),
Attributes::V10(a) => a.source(),
}
}
fn get_specversion(&self) -> SpecVersion {
fn specversion(&self) -> SpecVersion {
match self {
Attributes::V03(a) => a.get_specversion(),
Attributes::V10(a) => a.get_specversion(),
Attributes::V03(a) => a.specversion(),
Attributes::V10(a) => a.specversion(),
}
}
fn get_type(&self) -> &str {
fn ty(&self) -> &str {
match self {
Attributes::V03(a) => a.get_type(),
Attributes::V10(a) => a.get_type(),
Attributes::V03(a) => a.ty(),
Attributes::V10(a) => a.ty(),
}
}
fn get_datacontenttype(&self) -> Option<&str> {
fn datacontenttype(&self) -> Option<&str> {
match self {
Attributes::V03(a) => a.get_datacontenttype(),
Attributes::V10(a) => a.get_datacontenttype(),
Attributes::V03(a) => a.datacontenttype(),
Attributes::V10(a) => a.datacontenttype(),
}
}
fn get_dataschema(&self) -> Option<&Url> {
fn dataschema(&self) -> Option<&Url> {
match self {
Attributes::V03(a) => a.get_dataschema(),
Attributes::V10(a) => a.get_dataschema(),
Attributes::V03(a) => a.dataschema(),
Attributes::V10(a) => a.dataschema(),
}
}
fn get_subject(&self) -> Option<&str> {
fn subject(&self) -> Option<&str> {
match self {
Attributes::V03(a) => a.get_subject(),
Attributes::V10(a) => a.get_subject(),
Attributes::V03(a) => a.subject(),
Attributes::V10(a) => a.subject(),
}
}
fn get_time(&self) -> Option<&DateTime<Utc>> {
fn time(&self) -> Option<&DateTime<Utc>> {
match self {
Attributes::V03(a) => a.get_time(),
Attributes::V10(a) => a.get_time(),
Attributes::V03(a) => a.time(),
Attributes::V10(a) => a.time(),
}
}
}

View File

@ -1,4 +1,6 @@
use serde::export::Formatter;
use std::convert::{Into, TryFrom};
use std::fmt;
/// Event [data attribute](https://github.com/cloudevents/spec/blob/master/spec.md#event-data) representation
#[derive(Debug, PartialEq, Clone)]
@ -102,3 +104,13 @@ impl TryFrom<Data> for String {
}
}
}
impl fmt::Display for Data {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Data::Binary(vec) => write!(f, "Binary data: {:?}", vec),
Data::String(s) => write!(f, "String data: {}", s),
Data::Json(j) => write!(f, "Json data: {}", j),
}
}
}

View File

@ -6,7 +6,6 @@ use crate::event::attributes::DataAttributesWriter;
use chrono::{DateTime, Utc};
use delegate_attr::delegate;
use std::collections::HashMap;
use std::convert::TryFrom;
use url::Url;
/// Data structure that represents a [CloudEvent](https://github.com/cloudevents/spec/blob/master/spec.md).
@ -16,9 +15,11 @@ use url::Url;
///
/// You can build events using [`super::EventBuilder`]
/// ```
/// use cloudevents::Event;
/// use cloudevents::event::AttributesReader;
/// use cloudevents::*;
/// use std::convert::TryInto;
///
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// // Create an event using the Default trait
/// let mut e = Event::default();
/// e.write_data(
@ -27,11 +28,16 @@ use url::Url;
/// );
///
/// // Print the event id
/// println!("Event id: {}", e.get_id());
/// println!("Event id: {}", e.id());
///
/// // Get the event data
/// let data: serde_json::Value = e.try_get_data().unwrap().unwrap();
/// println!("Event data: {}", data)
/// let data: Option<Data> = e.data().cloned();
/// match data {
/// Some(d) => println!("{}", d),
/// None => println!("No event data")
/// }
/// # Ok(())
/// # }
/// ```
#[derive(PartialEq, Debug, Clone)]
pub struct Event {
@ -42,14 +48,14 @@ pub struct Event {
#[delegate(self.attributes)]
impl AttributesReader for Event {
fn get_id(&self) -> &str;
fn get_source(&self) -> &Url;
fn get_specversion(&self) -> SpecVersion;
fn get_type(&self) -> &str;
fn get_datacontenttype(&self) -> Option<&str>;
fn get_dataschema(&self) -> Option<&Url>;
fn get_subject(&self) -> Option<&str>;
fn get_time(&self) -> Option<&DateTime<Utc>>;
fn id(&self) -> &str;
fn source(&self) -> &Url;
fn specversion(&self) -> SpecVersion;
fn ty(&self) -> &str;
fn datacontenttype(&self) -> Option<&str>;
fn dataschema(&self) -> Option<&Url>;
fn subject(&self) -> Option<&str>;
fn time(&self) -> Option<&DateTime<Utc>>;
}
#[delegate(self.attributes)]
@ -126,6 +132,11 @@ impl Event {
self.data = Some(data.into());
}
/// Get `data` from this `Event`
pub fn data(&self) -> Option<&Data> {
self.data.as_ref()
}
/// Write `data` into this `Event` with the specified `datacontenttype` and `dataschema`.
///
/// ```
@ -152,34 +163,8 @@ impl Event {
self.data = Some(data.into());
}
/// Get `data` from this `Event`
pub fn get_data<T: Sized + From<Data>>(&self) -> Option<T> {
match self.data.as_ref() {
Some(d) => Some(T::from(d.clone())),
None => None,
}
}
/// Try to get `data` from this `Event`
pub fn try_get_data<T: Sized + TryFrom<Data>>(&self) -> Result<Option<T>, T::Error> {
match self.data.as_ref() {
Some(d) => Some(T::try_from(d.clone())),
None => None,
}
.transpose()
}
/// Transform this `Event` into the content of `data`
pub fn into_data<T: Sized + TryFrom<Data>>(self) -> Result<Option<T>, T::Error> {
match self.data {
Some(d) => Some(T::try_from(d)),
None => None,
}
.transpose()
}
/// Get the [extension](https://github.com/cloudevents/spec/blob/master/spec.md#extension-context-attributes) named `extension_name`
pub fn get_extension(&self, extension_name: &str) -> Option<&ExtensionValue> {
pub fn extension(&self, extension_name: &str) -> Option<&ExtensionValue> {
self.extensions.get(extension_name)
}
@ -206,28 +191,6 @@ impl Event {
mod tests {
use super::*;
#[test]
fn try_get_data_json() {
let expected_data = serde_json::json!({
"hello": "world"
});
let mut e = Event::default();
e.write_data_with_schema(
"application/json",
Url::parse("http://localhost:8080/schema").unwrap(),
expected_data.clone(),
);
let data: serde_json::Value = e.try_get_data().unwrap().unwrap();
assert_eq!(expected_data, data);
assert_eq!("application/json", e.get_datacontenttype().unwrap());
assert_eq!(
&Url::parse("http://localhost:8080/schema").unwrap(),
e.get_dataschema().unwrap()
)
}
#[test]
fn take_data() {
let mut e = Event::default();
@ -238,11 +201,15 @@ mod tests {
}),
);
let _d = e.take_data();
let (datacontenttype, dataschema, data) = e.take_data();
assert!(e.try_get_data::<serde_json::Value>().unwrap().is_none());
assert!(e.get_dataschema().is_none());
assert!(e.get_datacontenttype().is_none());
assert!(datacontenttype.is_some());
assert!(dataschema.is_none());
assert!(data.is_some());
assert!(e.data().is_none());
assert!(e.dataschema().is_none());
assert!(e.datacontenttype().is_none());
}
#[test]
@ -251,7 +218,7 @@ mod tests {
e.set_id("001");
assert_eq!(e.set_id("002"), String::from("001"));
assert_eq!(e.get_id(), "002")
assert_eq!(e.id(), "002")
}
#[test]

View File

@ -106,9 +106,7 @@ pub(crate) trait EventFormatDeserializer {
) -> Result<Event, E> {
let attributes = Self::deserialize_attributes(&mut map)?;
let data = Self::deserialize_data(
attributes
.get_datacontenttype()
.unwrap_or("application/json"),
attributes.datacontenttype().unwrap_or("application/json"),
&mut map,
)?;
let extensions = map

View File

@ -17,7 +17,7 @@ impl StructuredDeserializer for Event {
impl BinaryDeserializer for Event {
fn deserialize_binary<R: Sized, V: BinarySerializer<R>>(self, mut visitor: V) -> Result<R> {
visitor = visitor.set_spec_version(self.get_specversion())?;
visitor = visitor.set_spec_version(self.specversion())?;
visitor = self.attributes.deserialize_attributes(visitor)?;
for (k, v) in self.extensions.into_iter() {
visitor = visitor.set_extension(&k, v.into())?;

View File

@ -88,35 +88,35 @@ impl<'a> Iterator for AttributesIntoIterator<'a> {
}
impl AttributesReader for Attributes {
fn get_id(&self) -> &str {
fn id(&self) -> &str {
&self.id
}
fn get_source(&self) -> &Url {
fn source(&self) -> &Url {
&self.source
}
fn get_specversion(&self) -> SpecVersion {
fn specversion(&self) -> SpecVersion {
SpecVersion::V03
}
fn get_type(&self) -> &str {
fn ty(&self) -> &str {
&self.ty
}
fn get_datacontenttype(&self) -> Option<&str> {
fn datacontenttype(&self) -> Option<&str> {
self.datacontenttype.as_deref()
}
fn get_dataschema(&self) -> Option<&Url> {
fn dataschema(&self) -> Option<&Url> {
self.schemaurl.as_ref()
}
fn get_subject(&self) -> Option<&str> {
fn subject(&self) -> Option<&str> {
self.subject.as_deref()
}
fn get_time(&self) -> Option<&DateTime<Utc>> {
fn time(&self) -> Option<&DateTime<Utc>> {
self.time.as_ref()
}
}

View File

@ -88,35 +88,35 @@ impl<'a> Iterator for AttributesIntoIterator<'a> {
}
impl AttributesReader for Attributes {
fn get_id(&self) -> &str {
fn id(&self) -> &str {
&self.id
}
fn get_source(&self) -> &Url {
fn source(&self) -> &Url {
&self.source
}
fn get_specversion(&self) -> SpecVersion {
fn specversion(&self) -> SpecVersion {
SpecVersion::V10
}
fn get_type(&self) -> &str {
fn ty(&self) -> &str {
&self.ty
}
fn get_datacontenttype(&self) -> Option<&str> {
fn datacontenttype(&self) -> Option<&str> {
self.datacontenttype.as_deref()
}
fn get_dataschema(&self) -> Option<&Url> {
fn dataschema(&self) -> Option<&Url> {
self.dataschema.as_ref()
}
fn get_subject(&self) -> Option<&str> {
fn subject(&self) -> Option<&str> {
self.subject.as_deref()
}
fn get_time(&self) -> Option<&DateTime<Utc>> {
fn time(&self) -> Option<&DateTime<Utc>> {
self.time.as_ref()
}
}

View File

@ -13,8 +13,8 @@
//! .build()
//! .unwrap();
//!
//! println!("CloudEvent Id: {}", event.get_id());
//! println!("CloudEvent Time: {}", event.get_time().unwrap());
//! println!("CloudEvent Id: {}", event.id());
//! println!("CloudEvent Time: {}", event.time().unwrap());
//! ```
//!
//! If you're looking for Protocol Binding implementations, look at crates:
@ -33,6 +33,7 @@ pub mod event;
/// Provides facilities to implement Protocol Bindings
pub mod message;
pub use event::Data;
pub use event::Event;
pub use event::{AttributesReader, AttributesWriter};
pub use event::{EventBuilder, EventBuilderV03, EventBuilderV10};

View File

@ -6,6 +6,7 @@ use cloudevents::event::{
AttributesReader, EventBuilder, EventBuilderError, ExtensionValue, SpecVersion,
};
use cloudevents::EventBuilderV03;
use std::convert::TryInto;
use url::Url;
#[test]
@ -23,7 +24,7 @@ fn build_event() {
"hello": "world"
});
let event = EventBuilderV03::new()
let mut event = EventBuilderV03::new()
.id(id)
.source(source.clone())
.ty(ty)
@ -34,20 +35,20 @@ fn build_event() {
.build()
.unwrap();
assert_eq!(SpecVersion::V03, event.get_specversion());
assert_eq!(id, event.get_id());
assert_eq!(source, event.get_source().clone());
assert_eq!(ty, event.get_type());
assert_eq!(subject, event.get_subject().unwrap());
assert_eq!(time, event.get_time().unwrap().clone());
assert_eq!(SpecVersion::V03, event.specversion());
assert_eq!(id, event.id());
assert_eq!(source, event.source().clone());
assert_eq!(ty, event.ty());
assert_eq!(subject, event.subject().unwrap());
assert_eq!(time, event.time().unwrap().clone());
assert_eq!(
ExtensionValue::from(extension_value),
event.get_extension(extension_name).unwrap().clone()
event.extension(extension_name).unwrap().clone()
);
assert_eq!(content_type, event.get_datacontenttype().unwrap());
assert_eq!(schema, event.get_dataschema().unwrap().clone());
assert_eq!(content_type, event.datacontenttype().unwrap());
assert_eq!(schema, event.dataschema().unwrap().clone());
let event_data: serde_json::Value = event.try_get_data().unwrap().unwrap();
let event_data: serde_json::Value = event.take_data().2.unwrap().try_into().unwrap();
assert_eq!(data, event_data);
}

View File

@ -6,6 +6,7 @@ use cloudevents::event::{
AttributesReader, EventBuilder, EventBuilderError, ExtensionValue, SpecVersion,
};
use cloudevents::EventBuilderV10;
use std::convert::TryInto;
use url::Url;
#[test]
@ -23,7 +24,7 @@ fn build_event() {
"hello": "world"
});
let event = EventBuilderV10::new()
let mut event = EventBuilderV10::new()
.id(id)
.source(source.clone())
.ty(ty)
@ -34,20 +35,20 @@ fn build_event() {
.build()
.unwrap();
assert_eq!(SpecVersion::V10, event.get_specversion());
assert_eq!(id, event.get_id());
assert_eq!(source, event.get_source().clone());
assert_eq!(ty, event.get_type());
assert_eq!(subject, event.get_subject().unwrap());
assert_eq!(time, event.get_time().unwrap().clone());
assert_eq!(SpecVersion::V10, event.specversion());
assert_eq!(id, event.id());
assert_eq!(source, event.source().clone());
assert_eq!(ty, event.ty());
assert_eq!(subject, event.subject().unwrap());
assert_eq!(time, event.time().unwrap().clone());
assert_eq!(
ExtensionValue::from(extension_value),
event.get_extension(extension_name).unwrap().clone()
event.extension(extension_name).unwrap().clone()
);
assert_eq!(content_type, event.get_datacontenttype().unwrap());
assert_eq!(schema, event.get_dataschema().unwrap().clone());
assert_eq!(content_type, event.datacontenttype().unwrap());
assert_eq!(schema, event.dataschema().unwrap().clone());
let event_data: serde_json::Value = event.try_get_data().unwrap().unwrap();
let event_data: serde_json::Value = event.take_data().2.unwrap().try_into().unwrap();
assert_eq!(data, event_data);
}

View File

@ -2,6 +2,7 @@ mod test_data;
use cloudevents::message::{BinaryDeserializer, Result, StructuredDeserializer};
use cloudevents::{AttributesReader, EventBuilder, EventBuilderV03, EventBuilderV10};
use std::convert::TryInto;
use test_data::*;
#[test]
@ -18,10 +19,10 @@ fn message_v03_roundtrip_binary() -> Result<()> {
//TODO this code smells because we're missing a proper way in the public APIs
// to destructure an event and rebuild it
let wanna_be_expected = v03::full_json_data();
let data: serde_json::Value = wanna_be_expected.try_get_data()?.unwrap();
let data: serde_json::Value = wanna_be_expected.data().unwrap().clone().try_into()?;
let bytes = serde_json::to_vec(&data)?;
let expected = EventBuilderV03::from(wanna_be_expected.clone())
.data(wanna_be_expected.get_datacontenttype().unwrap(), bytes)
.data(wanna_be_expected.datacontenttype().unwrap(), bytes)
.build()
.unwrap();
@ -46,10 +47,15 @@ fn message_v10_roundtrip_binary() -> Result<()> {
//TODO this code smells because we're missing a proper way in the public APIs
// to destructure an event and rebuild it
let wanna_be_expected = v10::full_json_data();
let data: serde_json::Value = wanna_be_expected.try_get_data()?.unwrap();
let data: serde_json::Value = wanna_be_expected
.data()
.cloned()
.unwrap()
.try_into()
.unwrap();
let bytes = serde_json::to_vec(&data)?;
let expected = EventBuilderV10::from(wanna_be_expected.clone())
.data(wanna_be_expected.get_datacontenttype().unwrap(), bytes)
.data(wanna_be_expected.datacontenttype().unwrap(), bytes)
.build()
.unwrap();