This commit is contained in:
Francesco Guardiani 2021-07-08 14:03:45 +05:30 committed by GitHub
commit f4d569ec71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 257 additions and 142 deletions

View File

@ -53,14 +53,14 @@ jobs:
# If glibc, compile and test all # If glibc, compile and test all
- uses: actions-rs/cargo@v1 - uses: actions-rs/cargo@v1
name: "Build" name: "Build glibc"
if: matrix.target == 'x86_64-unknown-linux-gnu' if: matrix.target == 'x86_64-unknown-linux-gnu'
with: with:
command: build command: build
toolchain: ${{ matrix.toolchain }} toolchain: ${{ matrix.toolchain }}
args: --target ${{ matrix.target }} --all-features args: --target ${{ matrix.target }} --all-features
- uses: actions-rs/cargo@v1 - uses: actions-rs/cargo@v1
name: "Test" name: "Test glibc"
if: matrix.target == 'x86_64-unknown-linux-gnu' if: matrix.target == 'x86_64-unknown-linux-gnu'
with: with:
command: test command: test
@ -129,3 +129,31 @@ jobs:
command: build command: build
toolchain: ${{ matrix.toolchain }} toolchain: ${{ matrix.toolchain }}
args: --target ${{ matrix.target }} --manifest-path ./example-projects/warp-example/Cargo.toml args: --target ${{ matrix.target }} --manifest-path ./example-projects/warp-example/Cargo.toml
check_no_std:
name: Check no_std
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
# Caching stuff
- uses: actions/cache@v2
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
key: ${{ runner.os }}-cargo-no-std-deps-${{ hashFiles('**/Cargo.toml') }}
- uses: actions/cache@v2
with:
path: |
target/
key: ${{ runner.os }}-cargo-no-std-build-${{ hashFiles('**/Cargo.toml') }}
- name: Download cargo-nono
run: curl -LSfs https://japaric.github.io/trust/install.sh | sh -s -- --git hobofan/cargo-nono
- name: Run check
run: ./cargo-nono check

View File

@ -11,12 +11,17 @@ repository = "https://github.com/cloudevents/sdk-rust"
exclude = [ exclude = [
".github/*" ".github/*"
] ]
categories = ["web-programming", "encoding", "data-structures"] categories = ["web-programming", "encoding", "data-structures", "no_std"]
[lib] [lib]
name = "cloudevents" name = "cloudevents"
[features] [features]
# Without default features, the package acts as no_std
default = ["std"]
std = ["snafu/std", "url"]
actix = ["actix-web", "async-trait", "lazy_static", "bytes", "futures"] actix = ["actix-web", "async-trait", "lazy_static", "bytes", "futures"]
reqwest = ["reqwest-lib", "async-trait", "lazy_static", "bytes"] reqwest = ["reqwest-lib", "async-trait", "lazy_static", "bytes"]
rdkafka = ["rdkafka-lib", "lazy_static", "bytes", "futures"] rdkafka = ["rdkafka-lib", "lazy_static", "bytes", "futures"]
@ -28,9 +33,9 @@ serde_json = "^1.0"
chrono = { version = "^0.4", features = ["serde"] } chrono = { version = "^0.4", features = ["serde"] }
delegate-attr = "^0.2" delegate-attr = "^0.2"
base64 = "^0.12" base64 = "^0.12"
url = { version = "^2.1", features = ["serde"] } snafu = { version = "^0.6", default-features = false }
snafu = "^0.6"
bitflags = "^1.2" bitflags = "^1.2"
url = { version = "^2.1", features = ["serde"], optional = true }
# runtime optional deps # runtime optional deps
actix-web = { version = "^3", default-features = false, optional = true } actix-web = { version = "^3", default-features = false, optional = true }
@ -49,7 +54,7 @@ hostname = "^0.3"
uuid = { version = "^0.8", features = ["v4"] } uuid = { version = "^0.8", features = ["v4"] }
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
web-sys = { version = "^0.3", features = ["Window", "Location"] } web-sys = { version = "^0.3", default-features = false, features = ["Window", "Location"] }
uuid = { version = "^0.8", features = ["v4", "wasm-bindgen"] } uuid = { version = "^0.8", features = ["v4", "wasm-bindgen"] }
[dev-dependencies] [dev-dependencies]

View File

@ -0,0 +1,15 @@
[package]
name = "no-std-example"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cloudevents-sdk = { path = "../..", default-features = false }
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"

View File

@ -0,0 +1,25 @@
#![no_std]
#![no_main]
use core::panic::PanicInfo;
use cloudevents;
use cloudevents::EventBuilder;
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
#[no_mangle]
pub extern "C" fn _start() -> ! {
loop {
#[allow(dead_code)]
let event = cloudevents::EventBuilderV10::new()
.id("my_id")
.source("my_source")
.subject("some_subject")
.build()
.unwrap();
}
}

View File

@ -1,11 +1,10 @@
use super::{ use super::{
AttributesIntoIteratorV03, AttributesIntoIteratorV10, AttributesV03, AttributesV10, types::*, AttributesIntoIteratorV03, AttributesIntoIteratorV10, AttributesV03, AttributesV10,
ExtensionValue, SpecVersion, UriReference, ExtensionValue, SpecVersion,
}; };
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use serde::Serializer; use serde::Serializer;
use std::fmt; use std::fmt;
use url::Url;
/// Enum representing a borrowed value of a CloudEvent attribute. /// Enum representing a borrowed value of a CloudEvent attribute.
/// This represents the types defined in the [CloudEvent spec type system](https://github.com/cloudevents/spec/blob/v1.0/spec.md#type-system) /// This represents the types defined in the [CloudEvent spec type system](https://github.com/cloudevents/spec/blob/v1.0/spec.md#type-system)
@ -13,7 +12,7 @@ use url::Url;
pub enum AttributeValue<'a> { pub enum AttributeValue<'a> {
SpecVersion(SpecVersion), SpecVersion(SpecVersion),
String(&'a str), String(&'a str),
URI(&'a Url), URI(&'a Uri),
URIRef(&'a UriReference), URIRef(&'a UriReference),
Boolean(&'a bool), Boolean(&'a bool),
Integer(&'a i64), Integer(&'a i64),
@ -57,7 +56,7 @@ pub trait AttributesReader {
/// Get the [datacontenttype](https://github.com/cloudevents/spec/blob/master/spec.md#datacontenttype). /// Get the [datacontenttype](https://github.com/cloudevents/spec/blob/master/spec.md#datacontenttype).
fn datacontenttype(&self) -> Option<&str>; fn datacontenttype(&self) -> Option<&str>;
/// Get the [dataschema](https://github.com/cloudevents/spec/blob/master/spec.md#dataschema). /// Get the [dataschema](https://github.com/cloudevents/spec/blob/master/spec.md#dataschema).
fn dataschema(&self) -> Option<&Url>; fn dataschema(&self) -> Option<&Uri>;
/// Get the [subject](https://github.com/cloudevents/spec/blob/master/spec.md#subject). /// Get the [subject](https://github.com/cloudevents/spec/blob/master/spec.md#subject).
fn subject(&self) -> Option<&str>; fn subject(&self) -> Option<&str>;
/// Get the [time](https://github.com/cloudevents/spec/blob/master/spec.md#time). /// Get the [time](https://github.com/cloudevents/spec/blob/master/spec.md#time).
@ -87,7 +86,7 @@ pub trait AttributesWriter {
-> Option<String>; -> Option<String>;
/// Set the [dataschema](https://github.com/cloudevents/spec/blob/master/spec.md#dataschema). /// Set the [dataschema](https://github.com/cloudevents/spec/blob/master/spec.md#dataschema).
/// Returns the previous value. /// Returns the previous value.
fn set_dataschema(&mut self, dataschema: Option<impl Into<Url>>) -> Option<Url>; fn set_dataschema(&mut self, dataschema: Option<impl Into<Uri>>) -> Option<Uri>;
} }
pub(crate) trait AttributesConverter { pub(crate) trait AttributesConverter {
@ -154,7 +153,7 @@ impl AttributesReader for Attributes {
} }
} }
fn dataschema(&self) -> Option<&Url> { fn dataschema(&self) -> Option<&Uri> {
match self { match self {
Attributes::V03(a) => a.dataschema(), Attributes::V03(a) => a.dataschema(),
Attributes::V10(a) => a.dataschema(), Attributes::V10(a) => a.dataschema(),
@ -222,7 +221,7 @@ impl AttributesWriter for Attributes {
} }
} }
fn set_dataschema(&mut self, dataschema: Option<impl Into<Url>>) -> Option<Url> { fn set_dataschema(&mut self, dataschema: Option<impl Into<Uri>>) -> Option<Uri> {
match self { match self {
Attributes::V03(a) => a.set_dataschema(dataschema), Attributes::V03(a) => a.set_dataschema(dataschema),
Attributes::V10(a) => a.set_dataschema(dataschema), Attributes::V10(a) => a.set_dataschema(dataschema),
@ -253,8 +252,7 @@ impl Attributes {
} }
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub(crate) fn default_hostname() -> Url { pub(crate) fn default_hostname() -> Uri {
Url::parse(
format!( format!(
"http://{}", "http://{}",
hostname::get() hostname::get()
@ -263,21 +261,18 @@ pub(crate) fn default_hostname() -> Url {
.flatten() .flatten()
.unwrap_or_else(|| "localhost".to_string()) .unwrap_or_else(|| "localhost".to_string())
) )
.as_ref(), .into_uri()
)
.unwrap() .unwrap()
} }
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
pub(crate) fn default_hostname() -> Url { pub(crate) fn default_hostname() -> Uri {
use std::str::FromStr; use std::str::FromStr;
Url::from_str(
web_sys::window() web_sys::window()
.map(|w| w.location().host().ok()) .map(|w| w.location().host().ok())
.flatten() .flatten()
.unwrap_or(String::from("http://localhost")) .unwrap_or(String::from("http://localhost"))
.as_str(), .into_uri()
)
.unwrap() .unwrap()
} }

View File

@ -1,3 +1,4 @@
use super::types;
use super::Event; use super::Event;
use snafu::Snafu; use snafu::Snafu;
@ -5,7 +6,6 @@ use snafu::Snafu;
/// ``` /// ```
/// use cloudevents::event::{EventBuilderV10, EventBuilder}; /// use cloudevents::event::{EventBuilderV10, EventBuilder};
/// use chrono::Utc; /// use chrono::Utc;
/// use url::Url;
/// ///
/// let event = EventBuilderV10::new() /// let event = EventBuilderV10::new()
/// .id("my_event.my_application") /// .id("my_event.my_application")
@ -48,9 +48,9 @@ pub enum Error {
attribute_name, attribute_name,
source source
))] ))]
ParseUrlError { ParseUriError {
attribute_name: &'static str, attribute_name: &'static str,
source: url::ParseError, source: types::ParseUriError,
}, },
#[snafu(display( #[snafu(display(
"Invalid value setting attribute '{}' with uriref type", "Invalid value setting attribute '{}' with uriref type",

View File

@ -8,7 +8,7 @@ mod extensions;
mod format; mod format;
mod message; mod message;
mod spec_version; mod spec_version;
mod types; pub mod types;
pub use attributes::Attributes; pub use attributes::Attributes;
pub use attributes::{AttributeValue, AttributesReader, AttributesWriter}; pub use attributes::{AttributeValue, AttributesReader, AttributesWriter};
@ -20,7 +20,6 @@ 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, UriReference};
mod v03; mod v03;
@ -38,11 +37,10 @@ pub use v10::EventBuilder as EventBuilderV10;
pub(crate) use v10::EventFormatDeserializer as EventFormatDeserializerV10; pub(crate) use v10::EventFormatDeserializer as EventFormatDeserializerV10;
pub(crate) use v10::EventFormatSerializer as EventFormatSerializerV10; pub(crate) use v10::EventFormatSerializer as EventFormatSerializerV10;
use chrono::{DateTime, Utc};
use delegate_attr::delegate; use delegate_attr::delegate;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt; use std::fmt;
use url::Url; use types::*;
/// Data structure that represents a [CloudEvent](https://github.com/cloudevents/spec/blob/master/spec.md). /// Data structure that represents a [CloudEvent](https://github.com/cloudevents/spec/blob/master/spec.md).
/// It provides methods to get the attributes through [`AttributesReader`] /// It provides methods to get the attributes through [`AttributesReader`]
@ -89,7 +87,7 @@ impl AttributesReader for Event {
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>;
fn dataschema(&self) -> Option<&Url>; fn dataschema(&self) -> Option<&Uri>;
fn subject(&self) -> Option<&str>; fn subject(&self) -> Option<&str>;
fn time(&self) -> Option<&DateTime<Utc>>; fn time(&self) -> Option<&DateTime<Utc>>;
} }
@ -103,7 +101,7 @@ impl AttributesWriter for Event {
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>>;
fn set_datacontenttype(&mut self, datacontenttype: Option<impl Into<String>>) fn set_datacontenttype(&mut self, datacontenttype: Option<impl Into<String>>)
-> Option<String>; -> Option<String>;
fn set_dataschema(&mut self, dataschema: Option<impl Into<Url>>) -> Option<Url>; fn set_dataschema(&mut self, dataschema: Option<impl Into<Uri>>) -> Option<Uri>;
} }
impl Default for Event { impl Default for Event {
@ -165,10 +163,10 @@ impl Event {
/// ///
/// let (datacontenttype, dataschema, data) = e.take_data(); /// let (datacontenttype, dataschema, data) = e.take_data();
/// ``` /// ```
pub fn take_data(&mut self) -> (Option<String>, Option<Url>, Option<Data>) { pub fn take_data(&mut self) -> (Option<String>, Option<Uri>, Option<Data>) {
( (
self.attributes.set_datacontenttype(None as Option<String>), self.attributes.set_datacontenttype(None as Option<String>),
self.attributes.set_dataschema(None as Option<Url>), self.attributes.set_dataschema(None as Option<Uri>),
self.data.take(), self.data.take(),
) )
} }

View File

@ -1,29 +1,88 @@
use chrono::{DateTime, Utc}; pub use self::uri::ParseUriError;
use url::Url; pub use self::uri::TryIntoUri;
pub use self::uri::Uri;
/// Trait to define conversion to [`Url`] pub use urireference::UriReference;
pub trait TryIntoUrl {
fn into_url(self) -> Result<Url, url::ParseError>; pub use chrono::{DateTime, Utc};
pub use time::TryIntoTime;
mod uri {
#[cfg(feature = "std")]
pub use url::Url as Uri;
#[cfg(not(feature = "std"))]
pub use String as Uri;
#[cfg(feature = "std")]
pub use url::ParseError as ParseUriError;
#[cfg(not(feature = "std"))]
pub use None as ParseUriError;
/// Trait to define conversion to [`Uri`]
pub trait TryIntoUri {
fn into_uri(self) -> Result<Uri, ParseUriError>;
} }
impl TryIntoUrl for Url { #[cfg(feature = "std")]
fn into_url(self) -> Result<Url, url::ParseError> { impl TryIntoUri for Uri {
fn into_uri(self) -> Result<Uri, ParseUriError> {
Ok(self) Ok(self)
} }
} }
impl TryIntoUrl for &str { #[cfg(feature = "std")]
fn into_url(self) -> Result<Url, url::ParseError> { impl TryIntoUri for &str {
Url::parse(self) fn into_uri(self) -> Result<Uri, ParseUriError> {
url::Url::parse(self)
} }
} }
impl TryIntoUrl for String { #[cfg(feature = "std")]
fn into_url(self) -> Result<Url, url::ParseError> { impl TryIntoUri for String {
self.as_str().into_url() fn into_uri(self) -> Result<Uri, ParseUriError> {
self.as_str().into_uri()
} }
} }
#[cfg(not(feature = "std"))]
impl TryIntoUri for Uri {
fn into_uri(self) -> Result<Uri, ParseUriError> {
Ok(self)
}
}
#[cfg(not(feature = "std"))]
impl TryIntoUri for &str {
fn into_uri(self) -> Result<Uri, ParseUriError> {
Ok(String::from(self))
}
}
#[cfg(not(feature = "std"))]
impl TryIntoUri for String {
fn into_uri(self) -> Result<Uri, ParseUriError> {
Ok(self)
}
}
}
mod urireference {
/// The URI-reference type.
///
/// The URI reference can be a URI, or just a relative path.
///
/// As the [`types::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;
}
mod time {
use chrono::{DateTime, Utc};
/// Trait to define conversion to [`DateTime`] /// Trait to define conversion to [`DateTime`]
pub trait TryIntoTime { pub trait TryIntoTime {
fn into_time(self) -> Result<DateTime<Utc>, chrono::ParseError>; fn into_time(self) -> Result<DateTime<Utc>, chrono::ParseError>;
@ -46,15 +105,4 @@ 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,8 +1,7 @@
use crate::event::attributes::{default_hostname, AttributeValue, AttributesConverter}; use crate::event::attributes::{default_hostname, AttributeValue, AttributesConverter};
use crate::event::{AttributesReader, AttributesV10, AttributesWriter, SpecVersion, UriReference}; use crate::event::types::*;
use crate::event::{AttributesReader, AttributesV10, AttributesWriter, SpecVersion};
use crate::message::{BinarySerializer, MessageAttributeValue}; use crate::message::{BinarySerializer, MessageAttributeValue};
use chrono::{DateTime, Utc};
use url::Url;
use uuid::Uuid; use uuid::Uuid;
pub(crate) const ATTRIBUTE_NAMES: [&str; 8] = [ pub(crate) const ATTRIBUTE_NAMES: [&str; 8] = [
@ -23,7 +22,7 @@ pub struct Attributes {
pub(crate) ty: String, pub(crate) ty: String,
pub(crate) source: UriReference, pub(crate) source: UriReference,
pub(crate) datacontenttype: Option<String>, pub(crate) datacontenttype: Option<String>,
pub(crate) schemaurl: Option<Url>, pub(crate) schemaurl: Option<Uri>,
pub(crate) subject: Option<String>, pub(crate) subject: Option<String>,
pub(crate) time: Option<DateTime<Utc>>, pub(crate) time: Option<DateTime<Utc>>,
} }
@ -105,7 +104,7 @@ impl AttributesReader for Attributes {
self.datacontenttype.as_deref() self.datacontenttype.as_deref()
} }
fn dataschema(&self) -> Option<&Url> { fn dataschema(&self) -> Option<&Uri> {
self.schemaurl.as_ref() self.schemaurl.as_ref()
} }
@ -146,7 +145,7 @@ impl AttributesWriter for Attributes {
std::mem::replace(&mut self.datacontenttype, datacontenttype.map(Into::into)) std::mem::replace(&mut self.datacontenttype, datacontenttype.map(Into::into))
} }
fn set_dataschema(&mut self, dataschema: Option<impl Into<Url>>) -> Option<Url> { fn set_dataschema(&mut self, dataschema: Option<impl Into<Uri>>) -> Option<Uri> {
std::mem::replace(&mut self.schemaurl, dataschema.map(Into::into)) std::mem::replace(&mut self.schemaurl, dataschema.map(Into::into))
} }
} }

View File

@ -1,13 +1,9 @@
use super::Attributes as AttributesV03; use super::Attributes as AttributesV03;
use crate::event::{ use crate::event::types::*;
Attributes, Data, Event, EventBuilderError, ExtensionValue, TryIntoTime, TryIntoUrl, use crate::event::{Attributes, Data, Event, EventBuilderError, ExtensionValue};
UriReference,
};
use crate::message::MessageAttributeValue; use crate::message::MessageAttributeValue;
use chrono::{DateTime, Utc};
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryInto; use std::convert::TryInto;
use url::Url;
/// Builder to create a CloudEvent V0.3 /// Builder to create a CloudEvent V0.3
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -16,7 +12,7 @@ pub struct EventBuilder {
ty: Option<String>, ty: Option<String>,
source: Option<UriReference>, source: Option<UriReference>,
datacontenttype: Option<String>, datacontenttype: Option<String>,
schemaurl: Option<Url>, schemaurl: Option<Uri>,
subject: Option<String>, subject: Option<String>,
time: Option<DateTime<Utc>>, time: Option<DateTime<Utc>>,
data: Option<Data>, data: Option<Data>,
@ -89,14 +85,14 @@ impl EventBuilder {
pub fn data_with_schema( pub fn data_with_schema(
mut self, mut self,
datacontenttype: impl Into<String>, datacontenttype: impl Into<String>,
schemaurl: impl TryIntoUrl, schemaurl: impl TryIntoUri,
data: impl Into<Data>, data: impl Into<Data>,
) -> Self { ) -> Self {
self.datacontenttype = Some(datacontenttype.into()); self.datacontenttype = Some(datacontenttype.into());
match schemaurl.into_url() { match schemaurl.into_uri() {
Ok(u) => self.schemaurl = Some(u), Ok(u) => self.schemaurl = Some(u),
Err(e) => { Err(e) => {
self.error = Some(EventBuilderError::ParseUrlError { self.error = Some(EventBuilderError::ParseUriError {
attribute_name: "schemaurl", attribute_name: "schemaurl",
source: e, source: e,
}) })

View File

@ -1,13 +1,12 @@
use super::Attributes; use super::Attributes;
use crate::event::data::is_json_content_type; use crate::event::data::is_json_content_type;
use crate::event::types::*;
use crate::event::{Data, ExtensionValue}; use crate::event::{Data, ExtensionValue};
use chrono::{DateTime, Utc};
use serde::de::IntoDeserializer; use serde::de::IntoDeserializer;
use serde::ser::SerializeMap; use serde::ser::SerializeMap;
use serde::{Deserialize, Serializer}; use serde::{Deserialize, Serializer};
use serde_json::{Map, Value}; use serde_json::{Map, Value};
use std::collections::HashMap; use std::collections::HashMap;
use url::Url;
pub(crate) struct EventFormatDeserializer {} pub(crate) struct EventFormatDeserializer {}
@ -21,7 +20,7 @@ impl crate::event::format::EventFormatDeserializer for EventFormatDeserializer {
source: extract_field!(map, "source", String, E)?, 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) s.into_uri()
})?, })?,
subject: extract_optional_field!(map, "subject", String, E)?, subject: extract_optional_field!(map, "subject", String, E)?,
time: extract_optional_field!(map, "time", String, E, |s: String| { time: extract_optional_field!(map, "time", String, E, |s: String| {

View File

@ -1,9 +1,8 @@
use crate::event::attributes::{default_hostname, AttributeValue, AttributesConverter}; use crate::event::attributes::{default_hostname, AttributeValue, AttributesConverter};
use crate::event::types::*;
use crate::event::{AttributesReader, AttributesV03, AttributesWriter, SpecVersion, UriReference}; use crate::event::{AttributesReader, AttributesV03, AttributesWriter, SpecVersion, UriReference};
use crate::message::{BinarySerializer, MessageAttributeValue}; use crate::message::{BinarySerializer, MessageAttributeValue};
use chrono::{DateTime, Utc};
use core::fmt::Debug; use core::fmt::Debug;
use url::Url;
use uuid::Uuid; use uuid::Uuid;
pub(crate) const ATTRIBUTE_NAMES: [&str; 8] = [ pub(crate) const ATTRIBUTE_NAMES: [&str; 8] = [
@ -24,7 +23,7 @@ pub struct Attributes {
pub(crate) ty: String, pub(crate) ty: String,
pub(crate) source: UriReference, pub(crate) source: UriReference,
pub(crate) datacontenttype: Option<String>, pub(crate) datacontenttype: Option<String>,
pub(crate) dataschema: Option<Url>, pub(crate) dataschema: Option<Uri>,
pub(crate) subject: Option<String>, pub(crate) subject: Option<String>,
pub(crate) time: Option<DateTime<Utc>>, pub(crate) time: Option<DateTime<Utc>>,
} }
@ -106,7 +105,7 @@ impl AttributesReader for Attributes {
self.datacontenttype.as_deref() self.datacontenttype.as_deref()
} }
fn dataschema(&self) -> Option<&Url> { fn dataschema(&self) -> Option<&Uri> {
self.dataschema.as_ref() self.dataschema.as_ref()
} }
@ -147,7 +146,7 @@ impl AttributesWriter for Attributes {
std::mem::replace(&mut self.datacontenttype, datacontenttype.map(Into::into)) std::mem::replace(&mut self.datacontenttype, datacontenttype.map(Into::into))
} }
fn set_dataschema(&mut self, dataschema: Option<impl Into<Url>>) -> Option<Url> { fn set_dataschema(&mut self, dataschema: Option<impl Into<Uri>>) -> Option<Uri> {
std::mem::replace(&mut self.dataschema, dataschema.map(Into::into)) std::mem::replace(&mut self.dataschema, dataschema.map(Into::into))
} }
} }

View File

@ -1,13 +1,12 @@
use super::Attributes as AttributesV10; use super::Attributes as AttributesV10;
use crate::event::types::*;
use crate::event::{ use crate::event::{
Attributes, Data, Event, EventBuilderError, ExtensionValue, TryIntoTime, TryIntoUrl, Attributes, Data, Event, EventBuilderError, ExtensionValue, TryIntoTime, TryIntoUri,
UriReference, UriReference,
}; };
use crate::message::MessageAttributeValue; use crate::message::MessageAttributeValue;
use chrono::{DateTime, Utc};
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryInto; use std::convert::TryInto;
use url::Url;
/// Builder to create a CloudEvent V1.0 /// Builder to create a CloudEvent V1.0
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -16,7 +15,7 @@ pub struct EventBuilder {
ty: Option<String>, ty: Option<String>,
source: Option<UriReference>, source: Option<UriReference>,
datacontenttype: Option<String>, datacontenttype: Option<String>,
dataschema: Option<Url>, dataschema: Option<Uri>,
subject: Option<String>, subject: Option<String>,
time: Option<DateTime<Utc>>, time: Option<DateTime<Utc>>,
data: Option<Data>, data: Option<Data>,
@ -89,14 +88,14 @@ impl EventBuilder {
pub fn data_with_schema( pub fn data_with_schema(
mut self, mut self,
datacontenttype: impl Into<String>, datacontenttype: impl Into<String>,
schemaurl: impl TryIntoUrl, schemaurl: impl TryIntoUri,
data: impl Into<Data>, data: impl Into<Data>,
) -> Self { ) -> Self {
self.datacontenttype = Some(datacontenttype.into()); self.datacontenttype = Some(datacontenttype.into());
match schemaurl.into_url() { match schemaurl.into_uri() {
Ok(u) => self.dataschema = Some(u), Ok(u) => self.dataschema = Some(u),
Err(e) => { Err(e) => {
self.error = Some(EventBuilderError::ParseUrlError { self.error = Some(EventBuilderError::ParseUriError {
attribute_name: "dataschema", attribute_name: "dataschema",
source: e, source: e,
}) })

View File

@ -1,13 +1,12 @@
use super::Attributes; use super::Attributes;
use crate::event::data::is_json_content_type; use crate::event::data::is_json_content_type;
use crate::event::types::*;
use crate::event::{Data, ExtensionValue}; use crate::event::{Data, ExtensionValue};
use chrono::{DateTime, Utc};
use serde::de::IntoDeserializer; use serde::de::IntoDeserializer;
use serde::ser::SerializeMap; use serde::ser::SerializeMap;
use serde::{Deserialize, Serializer}; use serde::{Deserialize, Serializer};
use serde_json::{Map, Value}; use serde_json::{Map, Value};
use std::collections::HashMap; use std::collections::HashMap;
use url::Url;
pub(crate) struct EventFormatDeserializer {} pub(crate) struct EventFormatDeserializer {}
@ -21,7 +20,7 @@ impl crate::event::format::EventFormatDeserializer for EventFormatDeserializer {
source: extract_field!(map, "source", String, E)?, 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) s.into_uri()
})?, })?,
subject: extract_optional_field!(map, "subject", String, E)?, subject: extract_optional_field!(map, "subject", String, E)?,
time: extract_optional_field!(map, "time", String, E, |s: String| { time: extract_optional_field!(map, "time", String, E, |s: String| {

View File

@ -4,8 +4,7 @@
//! # use std::error::Error; //! # use std::error::Error;
//! # fn main() -> Result<(), Box<dyn Error>> { //! # fn main() -> Result<(), Box<dyn Error>> {
//! use cloudevents::{EventBuilder, AttributesReader, EventBuilderV10}; //! use cloudevents::{EventBuilder, AttributesReader, EventBuilderV10};
//! use chrono::{Utc, DateTime}; //! use chrono::Utc;
//! use url::Url;
//! //!
//! let event = EventBuilderV10::new() //! let event = EventBuilderV10::new()
//! .id("my_event.my_application") //! .id("my_event.my_application")
@ -56,7 +55,18 @@
#![doc(html_root_url = "https://docs.rs/cloudevents-sdk/0.4.0")] #![doc(html_root_url = "https://docs.rs/cloudevents-sdk/0.4.0")]
#![deny(broken_intra_doc_links)] #![deny(broken_intra_doc_links)]
#![cfg_attr(not(any(feature = "std", test)), no_std)]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(all(feature = "std", not(feature = "alloc")))]
extern crate std as alloc;
#[cfg(any(feature = "std", test))]
extern crate std as core;
#[cfg(feature = "std")]
pub mod binding; pub mod binding;
pub mod event; pub mod event;
pub mod message; pub mod message;

View File

@ -1,3 +1,4 @@
use crate::event::types;
use snafu::Snafu; use snafu::Snafu;
/// Represents an error during serialization/deserialization process /// Represents an error during serialization/deserialization process
@ -22,7 +23,7 @@ pub enum Error {
ParseTimeError { source: chrono::ParseError }, ParseTimeError { source: chrono::ParseError },
#[snafu(display("Error while parsing a url: {}", source))] #[snafu(display("Error while parsing a url: {}", source))]
#[snafu(context(false))] #[snafu(context(false))]
ParseUrlError { source: url::ParseError }, ParseUrlError { source: types::ParseUriError },
#[snafu(display("Error while decoding base64: {}", source))] #[snafu(display("Error while decoding base64: {}", source))]
#[snafu(context(false))] #[snafu(context(false))]
Base64DecodingError { source: base64::DecodeError }, Base64DecodingError { source: base64::DecodeError },

View File

@ -1,8 +1,7 @@
use crate::event::{ExtensionValue, UriReference}; use crate::event::types::*;
use chrono::{DateTime, Utc}; use crate::event::ExtensionValue;
use std::convert::TryInto; use std::convert::TryInto;
use std::fmt; use std::fmt;
use url::Url;
/// Union type representing a [CloudEvent context attribute type](https://github.com/cloudevents/spec/blob/v1.0/spec.md#type-system). /// Union type representing a [CloudEvent context attribute type](https://github.com/cloudevents/spec/blob/v1.0/spec.md#type-system).
#[derive(PartialEq, Eq, Debug, Clone)] #[derive(PartialEq, Eq, Debug, Clone)]
@ -11,7 +10,7 @@ pub enum MessageAttributeValue {
Integer(i64), Integer(i64),
String(String), String(String),
Binary(Vec<u8>), Binary(Vec<u8>),
Uri(Url), Uri(Uri),
UriRef(UriReference), UriRef(UriReference),
DateTime(DateTime<Utc>), DateTime(DateTime<Utc>),
} }
@ -29,13 +28,13 @@ impl TryInto<DateTime<Utc>> for MessageAttributeValue {
} }
} }
impl TryInto<Url> for MessageAttributeValue { impl TryInto<Uri> for MessageAttributeValue {
type Error = super::Error; type Error = super::Error;
fn try_into(self) -> Result<Url, Self::Error> { fn try_into(self) -> Result<Uri, Self::Error> {
match self { match self {
MessageAttributeValue::Uri(u) => Ok(u), MessageAttributeValue::Uri(u) => Ok(u),
v => Ok(Url::parse(v.to_string().as_ref())?), v => Ok(v.to_string().into_uri()?),
} }
} }
} }