[#106] Allowing handling URI-ref types (#115)

Signed-off-by: Jens Reimann <jreimann@redhat.com>
This commit is contained in:
Jens Reimann 2021-03-05 09:20:52 +01:00 committed by GitHub
parent da40d3d563
commit 62ca1cd7da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 47 additions and 51 deletions

View File

@ -1,6 +1,6 @@
use super::{ use super::{
AttributesIntoIteratorV03, AttributesIntoIteratorV10, AttributesV03, AttributesV10, AttributesIntoIteratorV03, AttributesIntoIteratorV10, AttributesV03, AttributesV10,
ExtensionValue, SpecVersion, ExtensionValue, SpecVersion, UriReference,
}; };
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use serde::Serializer; use serde::Serializer;
@ -14,7 +14,7 @@ pub enum AttributeValue<'a> {
SpecVersion(SpecVersion), SpecVersion(SpecVersion),
String(&'a str), String(&'a str),
URI(&'a Url), URI(&'a Url),
URIRef(&'a Url), URIRef(&'a UriReference),
Boolean(&'a bool), Boolean(&'a bool),
Integer(&'a i64), Integer(&'a i64),
Time(&'a DateTime<Utc>), Time(&'a DateTime<Utc>),
@ -49,7 +49,7 @@ pub trait AttributesReader {
/// Get the [id](https://github.com/cloudevents/spec/blob/master/spec.md#id). /// Get the [id](https://github.com/cloudevents/spec/blob/master/spec.md#id).
fn id(&self) -> &str; fn id(&self) -> &str;
/// Get the [source](https://github.com/cloudevents/spec/blob/master/spec.md#source-1). /// 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). /// Get the [specversion](https://github.com/cloudevents/spec/blob/master/spec.md#specversion).
fn specversion(&self) -> SpecVersion; fn specversion(&self) -> SpecVersion;
/// Get the [type](https://github.com/cloudevents/spec/blob/master/spec.md#type). /// 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>) -> String; fn set_id(&mut self, id: impl Into<String>) -> String;
/// Set the [source](https://github.com/cloudevents/spec/blob/master/spec.md#source-1). /// Set the [source](https://github.com/cloudevents/spec/blob/master/spec.md#source-1).
/// Returns the previous value. /// Returns the previous value.
fn set_source(&mut self, source: impl Into<Url>) -> Url; fn set_source(&mut self, source: impl Into<UriReference>) -> UriReference;
/// Set the [type](https://github.com/cloudevents/spec/blob/master/spec.md#type). /// Set the [type](https://github.com/cloudevents/spec/blob/master/spec.md#type).
/// Returns the previous value. /// Returns the previous value.
fn set_type(&mut self, ty: impl Into<String>) -> String; fn set_type(&mut self, ty: impl Into<String>) -> String;
@ -126,7 +126,7 @@ impl AttributesReader for Attributes {
} }
} }
fn source(&self) -> &Url { fn source(&self) -> &UriReference {
match self { match self {
Attributes::V03(a) => a.source(), Attributes::V03(a) => a.source(),
Attributes::V10(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>) -> Url { fn set_source(&mut self, source: impl Into<UriReference>) -> UriReference {
match self { match self {
Attributes::V03(a) => a.set_source(source), Attributes::V03(a) => a.set_source(source),
Attributes::V10(a) => a.set_source(source), Attributes::V10(a) => a.set_source(source),

View File

@ -20,7 +20,7 @@ pub(crate) use message::EventBinarySerializer;
pub(crate) use message::EventStructuredSerializer; pub(crate) use message::EventStructuredSerializer;
pub use spec_version::SpecVersion; pub use spec_version::SpecVersion;
pub use spec_version::UnknownSpecVersion; pub use spec_version::UnknownSpecVersion;
pub use types::{TryIntoTime, TryIntoUrl}; pub use types::{TryIntoTime, TryIntoUrl, UriReference};
mod v03; mod v03;
@ -85,7 +85,7 @@ pub struct Event {
#[delegate(self.attributes)] #[delegate(self.attributes)]
impl AttributesReader for Event { impl AttributesReader for Event {
fn id(&self) -> &str; fn id(&self) -> &str;
fn source(&self) -> &Url; fn source(&self) -> &UriReference;
fn specversion(&self) -> SpecVersion; fn specversion(&self) -> SpecVersion;
fn ty(&self) -> &str; fn ty(&self) -> &str;
fn datacontenttype(&self) -> Option<&str>; fn datacontenttype(&self) -> Option<&str>;
@ -97,7 +97,7 @@ impl AttributesReader for Event {
#[delegate(self.attributes)] #[delegate(self.attributes)]
impl AttributesWriter for Event { impl AttributesWriter for Event {
fn set_id(&mut self, id: impl Into<String>) -> String; fn set_id(&mut self, id: impl Into<String>) -> String;
fn set_source(&mut self, source: impl Into<Url>) -> Url; fn set_source(&mut self, source: impl Into<UriReference>) -> UriReference;
fn set_type(&mut self, ty: impl Into<String>) -> String; fn set_type(&mut self, ty: impl Into<String>) -> String;
fn set_subject(&mut self, subject: Option<impl Into<String>>) -> Option<String>; fn set_subject(&mut self, subject: Option<impl Into<String>>) -> Option<String>;
fn set_time(&mut self, time: Option<impl Into<DateTime<Utc>>>) -> Option<DateTime<Utc>>; fn set_time(&mut self, time: Option<impl Into<DateTime<Utc>>>) -> Option<DateTime<Utc>>;

View File

@ -46,3 +46,15 @@ impl TryIntoTime for String {
self.as_str().into_time() 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;

View File

@ -1,6 +1,5 @@
use crate::event::attributes::{default_hostname, AttributeValue, AttributesConverter}; use crate::event::attributes::{default_hostname, AttributeValue, AttributesConverter};
use crate::event::AttributesV10; use crate::event::{AttributesReader, AttributesV10, AttributesWriter, SpecVersion, UriReference};
use crate::event::{AttributesReader, AttributesWriter, SpecVersion};
use crate::message::{BinarySerializer, MessageAttributeValue}; use crate::message::{BinarySerializer, MessageAttributeValue};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use url::Url; use url::Url;
@ -22,7 +21,7 @@ pub(crate) const ATTRIBUTE_NAMES: [&str; 8] = [
pub struct Attributes { pub struct Attributes {
pub(crate) id: String, pub(crate) id: String,
pub(crate) ty: String, pub(crate) ty: String,
pub(crate) source: Url, pub(crate) source: UriReference,
pub(crate) datacontenttype: Option<String>, pub(crate) datacontenttype: Option<String>,
pub(crate) schemaurl: Option<Url>, pub(crate) schemaurl: Option<Url>,
pub(crate) subject: Option<String>, pub(crate) subject: Option<String>,
@ -64,7 +63,7 @@ impl<'a> Iterator for AttributesIntoIterator<'a> {
.attributes .attributes
.schemaurl .schemaurl
.as_ref() .as_ref()
.map(|v| ("schemaurl", AttributeValue::URIRef(v))), .map(|v| ("schemaurl", AttributeValue::URI(v))),
6 => self 6 => self
.attributes .attributes
.subject .subject
@ -90,7 +89,7 @@ impl AttributesReader for Attributes {
&self.id &self.id
} }
fn source(&self) -> &Url { fn source(&self) -> &UriReference {
&self.source &self.source
} }
@ -124,7 +123,7 @@ impl AttributesWriter for Attributes {
std::mem::replace(&mut self.id, id.into()) std::mem::replace(&mut self.id, id.into())
} }
fn set_source(&mut self, source: impl Into<Url>) -> Url { fn set_source(&mut self, source: impl Into<UriReference>) -> UriReference {
std::mem::replace(&mut self.source, source.into()) std::mem::replace(&mut self.source, source.into())
} }
@ -157,7 +156,7 @@ impl Default for Attributes {
Attributes { Attributes {
id: Uuid::new_v4().to_string(), id: Uuid::new_v4().to_string(),
ty: "type".to_string(), ty: "type".to_string(),
source: default_hostname(), source: default_hostname().to_string(),
datacontenttype: None, datacontenttype: None,
schemaurl: None, schemaurl: None,
subject: None, subject: None,
@ -228,7 +227,7 @@ mod tests {
let a = Attributes { let a = Attributes {
id: String::from("1"), id: String::from("1"),
ty: String::from("someType"), ty: String::from("someType"),
source: Url::parse("https://example.net").unwrap(), source: "https://example.net".into(),
datacontenttype: None, datacontenttype: None,
schemaurl: None, schemaurl: None,
subject: None, subject: None,

View File

@ -1,6 +1,7 @@
use super::Attributes as AttributesV03; use super::Attributes as AttributesV03;
use crate::event::{ use crate::event::{
Attributes, Data, Event, EventBuilderError, ExtensionValue, TryIntoTime, TryIntoUrl, Attributes, Data, Event, EventBuilderError, ExtensionValue, TryIntoTime, TryIntoUrl,
UriReference,
}; };
use crate::message::MessageAttributeValue; use crate::message::MessageAttributeValue;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
@ -13,7 +14,7 @@ use url::Url;
pub struct EventBuilder { pub struct EventBuilder {
id: Option<String>, id: Option<String>,
ty: Option<String>, ty: Option<String>,
source: Option<Url>, source: Option<UriReference>,
datacontenttype: Option<String>, datacontenttype: Option<String>,
schemaurl: Option<Url>, schemaurl: Option<Url>,
subject: Option<String>, subject: Option<String>,
@ -29,16 +30,8 @@ impl EventBuilder {
self self
} }
pub fn source(mut self, source: impl TryIntoUrl) -> Self { pub fn source(mut self, source: impl Into<String>) -> Self {
match source.into_url() { self.source = Some(source.into());
Ok(u) => self.source = Some(u),
Err(e) => {
self.error = Some(EventBuilderError::ParseUrlError {
attribute_name: "source",
source: e,
})
}
};
self self
} }
@ -190,7 +183,7 @@ impl crate::event::message::AttributesSerializer for EventBuilder {
match name { match name {
"id" => self.id = Some(value.to_string()), "id" => self.id = Some(value.to_string()),
"type" => self.ty = 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()), "datacontenttype" => self.datacontenttype = Some(value.to_string()),
"schemaurl" => self.schemaurl = Some(value.try_into()?), "schemaurl" => self.schemaurl = Some(value.try_into()?),
"subject" => self.subject = Some(value.to_string()), "subject" => self.subject = Some(value.to_string()),

View File

@ -18,7 +18,7 @@ impl crate::event::format::EventFormatDeserializer for EventFormatDeserializer {
Ok(crate::event::Attributes::V03(Attributes { Ok(crate::event::Attributes::V03(Attributes {
id: extract_field!(map, "id", String, E)?, id: extract_field!(map, "id", String, E)?,
ty: extract_field!(map, "type", 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)?, datacontenttype: extract_optional_field!(map, "datacontenttype", String, E)?,
schemaurl: extract_optional_field!(map, "schemaurl", String, E, |s: String| { schemaurl: extract_optional_field!(map, "schemaurl", String, E, |s: String| {
Url::parse(&s) Url::parse(&s)

View File

@ -1,5 +1,5 @@
use crate::event::attributes::{default_hostname, AttributeValue, AttributesConverter}; 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 crate::message::{BinarySerializer, MessageAttributeValue};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use core::fmt::Debug; use core::fmt::Debug;
@ -22,7 +22,7 @@ pub(crate) const ATTRIBUTE_NAMES: [&str; 8] = [
pub struct Attributes { pub struct Attributes {
pub(crate) id: String, pub(crate) id: String,
pub(crate) ty: String, pub(crate) ty: String,
pub(crate) source: Url, pub(crate) source: UriReference,
pub(crate) datacontenttype: Option<String>, pub(crate) datacontenttype: Option<String>,
pub(crate) dataschema: Option<Url>, pub(crate) dataschema: Option<Url>,
pub(crate) subject: Option<String>, pub(crate) subject: Option<String>,
@ -90,7 +90,7 @@ impl AttributesReader for Attributes {
&self.id &self.id
} }
fn source(&self) -> &Url { fn source(&self) -> &UriReference {
&self.source &self.source
} }
@ -124,7 +124,7 @@ impl AttributesWriter for Attributes {
std::mem::replace(&mut self.id, id.into()) std::mem::replace(&mut self.id, id.into())
} }
fn set_source(&mut self, source: impl Into<Url>) -> Url { fn set_source(&mut self, source: impl Into<UriReference>) -> UriReference {
std::mem::replace(&mut self.source, source.into()) std::mem::replace(&mut self.source, source.into())
} }
@ -157,7 +157,7 @@ impl Default for Attributes {
Attributes { Attributes {
id: Uuid::new_v4().to_string(), id: Uuid::new_v4().to_string(),
ty: "type".to_string(), ty: "type".to_string(),
source: default_hostname(), source: default_hostname().to_string(),
datacontenttype: None, datacontenttype: None,
dataschema: None, dataschema: None,
subject: None, subject: None,

View File

@ -1,6 +1,7 @@
use super::Attributes as AttributesV10; use super::Attributes as AttributesV10;
use crate::event::{ use crate::event::{
Attributes, Data, Event, EventBuilderError, ExtensionValue, TryIntoTime, TryIntoUrl, Attributes, Data, Event, EventBuilderError, ExtensionValue, TryIntoTime, TryIntoUrl,
UriReference,
}; };
use crate::message::MessageAttributeValue; use crate::message::MessageAttributeValue;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
@ -13,7 +14,7 @@ use url::Url;
pub struct EventBuilder { pub struct EventBuilder {
id: Option<String>, id: Option<String>,
ty: Option<String>, ty: Option<String>,
source: Option<Url>, source: Option<UriReference>,
datacontenttype: Option<String>, datacontenttype: Option<String>,
dataschema: Option<Url>, dataschema: Option<Url>,
subject: Option<String>, subject: Option<String>,
@ -29,16 +30,8 @@ impl EventBuilder {
self self
} }
pub fn source(mut self, source: impl TryIntoUrl) -> Self { pub fn source(mut self, source: impl Into<String>) -> Self {
match source.into_url() { self.source = Some(source.into());
Ok(u) => self.source = Some(u),
Err(e) => {
self.error = Some(EventBuilderError::ParseUrlError {
attribute_name: "source",
source: e,
})
}
};
self self
} }
@ -190,7 +183,7 @@ impl crate::event::message::AttributesSerializer for EventBuilder {
match name { match name {
"id" => self.id = Some(value.to_string()), "id" => self.id = Some(value.to_string()),
"type" => self.ty = 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()), "datacontenttype" => self.datacontenttype = Some(value.to_string()),
"dataschema" => self.dataschema = Some(value.try_into()?), "dataschema" => self.dataschema = Some(value.try_into()?),
"subject" => self.subject = Some(value.to_string()), "subject" => self.subject = Some(value.to_string()),

View File

@ -18,7 +18,7 @@ impl crate::event::format::EventFormatDeserializer for EventFormatDeserializer {
Ok(crate::event::Attributes::V10(Attributes { Ok(crate::event::Attributes::V10(Attributes {
id: extract_field!(map, "id", String, E)?, id: extract_field!(map, "id", String, E)?,
ty: extract_field!(map, "type", 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)?, datacontenttype: extract_optional_field!(map, "datacontenttype", String, E)?,
dataschema: extract_optional_field!(map, "dataschema", String, E, |s: String| { dataschema: extract_optional_field!(map, "dataschema", String, E, |s: String| {
Url::parse(&s) Url::parse(&s)

View File

@ -1,4 +1,4 @@
use crate::event::ExtensionValue; use crate::event::{ExtensionValue, UriReference};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use std::convert::TryInto; use std::convert::TryInto;
use std::fmt; use std::fmt;
@ -12,7 +12,7 @@ pub enum MessageAttributeValue {
String(String), String(String),
Binary(Vec<u8>), Binary(Vec<u8>),
Uri(Url), Uri(Url),
UriRef(Url), UriRef(UriReference),
DateTime(DateTime<Utc>), DateTime(DateTime<Utc>),
} }
@ -35,7 +35,6 @@ impl TryInto<Url> for MessageAttributeValue {
fn try_into(self) -> Result<Url, Self::Error> { fn try_into(self) -> Result<Url, Self::Error> {
match self { match self {
MessageAttributeValue::Uri(u) => Ok(u), MessageAttributeValue::Uri(u) => Ok(u),
MessageAttributeValue::UriRef(u) => Ok(u),
v => Ok(Url::parse(v.to_string().as_ref())?), v => Ok(Url::parse(v.to_string().as_ref())?),
} }
} }