diff --git a/src/event/attributes.rs b/src/event/attributes.rs index 120bb9c6..30c1d304 100644 --- a/src/event/attributes.rs +++ b/src/event/attributes.rs @@ -1,6 +1,6 @@ use super::{ AttributesIntoIteratorV03, AttributesIntoIteratorV10, AttributesV03, AttributesV10, - ExtensionValue, SpecVersion, + ExtensionValue, SpecVersion, UriReference, }; use chrono::{DateTime, Utc}; use serde::Serializer; @@ -14,7 +14,7 @@ pub enum AttributeValue<'a> { SpecVersion(SpecVersion), String(&'a str), URI(&'a Url), - URIRef(&'a Url), + URIRef(&'a UriReference), Boolean(&'a bool), Integer(&'a i64), Time(&'a DateTime), @@ -49,7 +49,7 @@ pub trait AttributesReader { /// Get the [id](https://github.com/cloudevents/spec/blob/master/spec.md#id). fn id(&self) -> &str; /// Get the [source](https://github.com/cloudevents/spec/blob/master/spec.md#source-1). - fn source(&self) -> &Url; + fn source(&self) -> &UriReference; /// Get the [specversion](https://github.com/cloudevents/spec/blob/master/spec.md#specversion). fn specversion(&self) -> SpecVersion; /// Get the [type](https://github.com/cloudevents/spec/blob/master/spec.md#type). @@ -71,7 +71,7 @@ pub trait AttributesWriter { fn set_id(&mut self, id: impl Into) -> String; /// Set the [source](https://github.com/cloudevents/spec/blob/master/spec.md#source-1). /// Returns the previous value. - fn set_source(&mut self, source: impl Into) -> Url; + fn set_source(&mut self, source: impl Into) -> UriReference; /// Set the [type](https://github.com/cloudevents/spec/blob/master/spec.md#type). /// Returns the previous value. fn set_type(&mut self, ty: impl Into) -> String; @@ -126,7 +126,7 @@ impl AttributesReader for Attributes { } } - fn source(&self) -> &Url { + fn source(&self) -> &UriReference { match self { Attributes::V03(a) => a.source(), Attributes::V10(a) => a.source(), @@ -184,7 +184,7 @@ impl AttributesWriter for Attributes { } } - fn set_source(&mut self, source: impl Into) -> Url { + fn set_source(&mut self, source: impl Into) -> UriReference { match self { Attributes::V03(a) => a.set_source(source), Attributes::V10(a) => a.set_source(source), diff --git a/src/event/mod.rs b/src/event/mod.rs index 2d88b7ce..4de44450 100644 --- a/src/event/mod.rs +++ b/src/event/mod.rs @@ -20,7 +20,7 @@ pub(crate) use message::EventBinarySerializer; pub(crate) use message::EventStructuredSerializer; pub use spec_version::SpecVersion; pub use spec_version::UnknownSpecVersion; -pub use types::{TryIntoTime, TryIntoUrl}; +pub use types::{TryIntoTime, TryIntoUrl, UriReference}; mod v03; @@ -85,7 +85,7 @@ pub struct Event { #[delegate(self.attributes)] impl AttributesReader for Event { fn id(&self) -> &str; - fn source(&self) -> &Url; + fn source(&self) -> &UriReference; fn specversion(&self) -> SpecVersion; fn ty(&self) -> &str; fn datacontenttype(&self) -> Option<&str>; @@ -97,7 +97,7 @@ impl AttributesReader for Event { #[delegate(self.attributes)] impl AttributesWriter for Event { fn set_id(&mut self, id: impl Into) -> String; - fn set_source(&mut self, source: impl Into) -> Url; + fn set_source(&mut self, source: impl Into) -> UriReference; fn set_type(&mut self, ty: impl Into) -> String; fn set_subject(&mut self, subject: Option>) -> Option; fn set_time(&mut self, time: Option>>) -> Option>; diff --git a/src/event/types.rs b/src/event/types.rs index 2ae2f649..2a8720f8 100644 --- a/src/event/types.rs +++ b/src/event/types.rs @@ -46,3 +46,15 @@ impl TryIntoTime for String { self.as_str().into_time() } } + +/// The URI-reference type. +/// +/// The URI reference can be a URI, or just a relative path. +/// +/// As the [`url::Url`] type can only represent an absolute URL, we are falling back to a string +/// here. +/// +/// Also see: +/// * https://github.com/cloudevents/spec/blob/v1.0.1/spec.md#type-system +/// * https://tools.ietf.org/html/rfc3986#section-4.1 +pub type UriReference = String; diff --git a/src/event/v03/attributes.rs b/src/event/v03/attributes.rs index cbdb7a23..e26cee71 100644 --- a/src/event/v03/attributes.rs +++ b/src/event/v03/attributes.rs @@ -1,6 +1,5 @@ use crate::event::attributes::{default_hostname, AttributeValue, AttributesConverter}; -use crate::event::AttributesV10; -use crate::event::{AttributesReader, AttributesWriter, SpecVersion}; +use crate::event::{AttributesReader, AttributesV10, AttributesWriter, SpecVersion, UriReference}; use crate::message::{BinarySerializer, MessageAttributeValue}; use chrono::{DateTime, Utc}; use url::Url; @@ -22,7 +21,7 @@ pub(crate) const ATTRIBUTE_NAMES: [&str; 8] = [ pub struct Attributes { pub(crate) id: String, pub(crate) ty: String, - pub(crate) source: Url, + pub(crate) source: UriReference, pub(crate) datacontenttype: Option, pub(crate) schemaurl: Option, pub(crate) subject: Option, @@ -64,7 +63,7 @@ impl<'a> Iterator for AttributesIntoIterator<'a> { .attributes .schemaurl .as_ref() - .map(|v| ("schemaurl", AttributeValue::URIRef(v))), + .map(|v| ("schemaurl", AttributeValue::URI(v))), 6 => self .attributes .subject @@ -90,7 +89,7 @@ impl AttributesReader for Attributes { &self.id } - fn source(&self) -> &Url { + fn source(&self) -> &UriReference { &self.source } @@ -124,7 +123,7 @@ impl AttributesWriter for Attributes { std::mem::replace(&mut self.id, id.into()) } - fn set_source(&mut self, source: impl Into) -> Url { + fn set_source(&mut self, source: impl Into) -> UriReference { std::mem::replace(&mut self.source, source.into()) } @@ -157,7 +156,7 @@ impl Default for Attributes { Attributes { id: Uuid::new_v4().to_string(), ty: "type".to_string(), - source: default_hostname(), + source: default_hostname().to_string(), datacontenttype: None, schemaurl: None, subject: None, @@ -228,7 +227,7 @@ mod tests { let a = Attributes { id: String::from("1"), ty: String::from("someType"), - source: Url::parse("https://example.net").unwrap(), + source: "https://example.net".into(), datacontenttype: None, schemaurl: None, subject: None, diff --git a/src/event/v03/builder.rs b/src/event/v03/builder.rs index d40b4368..3689d95e 100644 --- a/src/event/v03/builder.rs +++ b/src/event/v03/builder.rs @@ -1,6 +1,7 @@ use super::Attributes as AttributesV03; use crate::event::{ Attributes, Data, Event, EventBuilderError, ExtensionValue, TryIntoTime, TryIntoUrl, + UriReference, }; use crate::message::MessageAttributeValue; use chrono::{DateTime, Utc}; @@ -13,7 +14,7 @@ use url::Url; pub struct EventBuilder { id: Option, ty: Option, - source: Option, + source: Option, datacontenttype: Option, schemaurl: Option, subject: Option, @@ -29,16 +30,8 @@ impl EventBuilder { self } - pub fn source(mut self, source: impl TryIntoUrl) -> Self { - match source.into_url() { - Ok(u) => self.source = Some(u), - Err(e) => { - self.error = Some(EventBuilderError::ParseUrlError { - attribute_name: "source", - source: e, - }) - } - }; + pub fn source(mut self, source: impl Into) -> Self { + self.source = Some(source.into()); self } @@ -190,7 +183,7 @@ impl crate::event::message::AttributesSerializer for EventBuilder { match name { "id" => self.id = Some(value.to_string()), "type" => self.ty = Some(value.to_string()), - "source" => self.source = Some(value.try_into()?), + "source" => self.source = Some(value.to_string()), "datacontenttype" => self.datacontenttype = Some(value.to_string()), "schemaurl" => self.schemaurl = Some(value.try_into()?), "subject" => self.subject = Some(value.to_string()), diff --git a/src/event/v03/format.rs b/src/event/v03/format.rs index e735e10c..4cb4de65 100644 --- a/src/event/v03/format.rs +++ b/src/event/v03/format.rs @@ -18,7 +18,7 @@ impl crate::event::format::EventFormatDeserializer for EventFormatDeserializer { Ok(crate::event::Attributes::V03(Attributes { id: extract_field!(map, "id", String, E)?, ty: extract_field!(map, "type", String, E)?, - source: extract_field!(map, "source", String, E, |s: String| Url::parse(&s))?, + source: extract_field!(map, "source", String, E)?, datacontenttype: extract_optional_field!(map, "datacontenttype", String, E)?, schemaurl: extract_optional_field!(map, "schemaurl", String, E, |s: String| { Url::parse(&s) diff --git a/src/event/v10/attributes.rs b/src/event/v10/attributes.rs index 4e604424..b52ae152 100644 --- a/src/event/v10/attributes.rs +++ b/src/event/v10/attributes.rs @@ -1,5 +1,5 @@ use crate::event::attributes::{default_hostname, AttributeValue, AttributesConverter}; -use crate::event::{AttributesReader, AttributesV03, AttributesWriter, SpecVersion}; +use crate::event::{AttributesReader, AttributesV03, AttributesWriter, SpecVersion, UriReference}; use crate::message::{BinarySerializer, MessageAttributeValue}; use chrono::{DateTime, Utc}; use core::fmt::Debug; @@ -22,7 +22,7 @@ pub(crate) const ATTRIBUTE_NAMES: [&str; 8] = [ pub struct Attributes { pub(crate) id: String, pub(crate) ty: String, - pub(crate) source: Url, + pub(crate) source: UriReference, pub(crate) datacontenttype: Option, pub(crate) dataschema: Option, pub(crate) subject: Option, @@ -90,7 +90,7 @@ impl AttributesReader for Attributes { &self.id } - fn source(&self) -> &Url { + fn source(&self) -> &UriReference { &self.source } @@ -124,7 +124,7 @@ impl AttributesWriter for Attributes { std::mem::replace(&mut self.id, id.into()) } - fn set_source(&mut self, source: impl Into) -> Url { + fn set_source(&mut self, source: impl Into) -> UriReference { std::mem::replace(&mut self.source, source.into()) } @@ -157,7 +157,7 @@ impl Default for Attributes { Attributes { id: Uuid::new_v4().to_string(), ty: "type".to_string(), - source: default_hostname(), + source: default_hostname().to_string(), datacontenttype: None, dataschema: None, subject: None, diff --git a/src/event/v10/builder.rs b/src/event/v10/builder.rs index 1fceeeeb..e765fe17 100644 --- a/src/event/v10/builder.rs +++ b/src/event/v10/builder.rs @@ -1,6 +1,7 @@ use super::Attributes as AttributesV10; use crate::event::{ Attributes, Data, Event, EventBuilderError, ExtensionValue, TryIntoTime, TryIntoUrl, + UriReference, }; use crate::message::MessageAttributeValue; use chrono::{DateTime, Utc}; @@ -13,7 +14,7 @@ use url::Url; pub struct EventBuilder { id: Option, ty: Option, - source: Option, + source: Option, datacontenttype: Option, dataschema: Option, subject: Option, @@ -29,16 +30,8 @@ impl EventBuilder { self } - pub fn source(mut self, source: impl TryIntoUrl) -> Self { - match source.into_url() { - Ok(u) => self.source = Some(u), - Err(e) => { - self.error = Some(EventBuilderError::ParseUrlError { - attribute_name: "source", - source: e, - }) - } - }; + pub fn source(mut self, source: impl Into) -> Self { + self.source = Some(source.into()); self } @@ -190,7 +183,7 @@ impl crate::event::message::AttributesSerializer for EventBuilder { match name { "id" => self.id = Some(value.to_string()), "type" => self.ty = Some(value.to_string()), - "source" => self.source = Some(value.try_into()?), + "source" => self.source = Some(value.to_string()), "datacontenttype" => self.datacontenttype = Some(value.to_string()), "dataschema" => self.dataschema = Some(value.try_into()?), "subject" => self.subject = Some(value.to_string()), diff --git a/src/event/v10/format.rs b/src/event/v10/format.rs index df624639..50f1e361 100644 --- a/src/event/v10/format.rs +++ b/src/event/v10/format.rs @@ -18,7 +18,7 @@ impl crate::event::format::EventFormatDeserializer for EventFormatDeserializer { Ok(crate::event::Attributes::V10(Attributes { id: extract_field!(map, "id", String, E)?, ty: extract_field!(map, "type", String, E)?, - source: extract_field!(map, "source", String, E, |s: String| Url::parse(&s))?, + source: extract_field!(map, "source", String, E)?, datacontenttype: extract_optional_field!(map, "datacontenttype", String, E)?, dataschema: extract_optional_field!(map, "dataschema", String, E, |s: String| { Url::parse(&s) diff --git a/src/message/types.rs b/src/message/types.rs index 7abf2632..721490fc 100644 --- a/src/message/types.rs +++ b/src/message/types.rs @@ -1,4 +1,4 @@ -use crate::event::ExtensionValue; +use crate::event::{ExtensionValue, UriReference}; use chrono::{DateTime, Utc}; use std::convert::TryInto; use std::fmt; @@ -12,7 +12,7 @@ pub enum MessageAttributeValue { String(String), Binary(Vec), Uri(Url), - UriRef(Url), + UriRef(UriReference), DateTime(DateTime), } @@ -35,7 +35,6 @@ impl TryInto for MessageAttributeValue { fn try_into(self) -> Result { match self { MessageAttributeValue::Uri(u) => Ok(u), - MessageAttributeValue::UriRef(u) => Ok(u), v => Ok(Url::parse(v.to_string().as_ref())?), } }