From d99bcd1537f4b4983e9e064d24a4a3698178b5d8 Mon Sep 17 00:00:00 2001 From: "adpranavb2000@gmail.com" Date: Mon, 4 Jan 2021 04:56:19 +0530 Subject: [PATCH] fixes#2 --- Cargo.toml | 19 ++++---- src/event/attributes.rs | 4 +- src/event/builder.rs | 2 +- src/event/format.rs | 33 ++++++++++++++ src/event/mod.rs | 32 ++++++++++++- src/event/spec_version.rs | 1 - src/event/types.rs | 16 ++++++- src/event/v03/attributes.rs | 45 ++++++++++++++++++- src/event/v03/builder.rs | 4 ++ src/event/v03/format.rs | 4 ++ src/event/v10/attributes.rs | 43 +++++++++++++++++- src/event/v10/builder.rs | 4 ++ src/event/v10/format.rs | 4 ++ src/message/error.rs | 12 +++++ .../{no_std_io.rs => hello_no_std_io.rs} | 0 tests/attributes_iter.rs | 2 + tests/builder_v03.rs | 6 +++ tests/builder_v10.rs | 6 +++ tests/message.rs | 4 ++ tests/serde_json.rs | 2 + tests/test_data/v03.rs | 9 ++++ tests/test_data/v10.rs | 10 +++++ tests/version_conversion.rs | 2 + 23 files changed, 245 insertions(+), 19 deletions(-) rename src/message/{no_std_io.rs => hello_no_std_io.rs} (100%) diff --git a/Cargo.toml b/Cargo.toml index 2a8332d6..249749d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,26 +17,25 @@ categories = ["web-programming", "encoding", "data-structures"] name = "cloudevents" [features] -default = ["std"] +default = ["no_std"] +std = ["no_std_compat_bypass","snafu/std", "snafu/guide", "serde/std", "serde_json/std", "chrono/std", "base64/std", "url"] +no_std = ["no_std_compat_bypass", "serde_no_std", "chrono_no_std", "base64/alloc"] + +no_std_compat_bypass=["no-std-compat/std"] +no_std_compat_layer=["no-std-compat/alloc", "no-std-compat/compat_hash", "no-std-compat/compat_sync"] chrono_no_std = ["chrono/serde", "chrono/alloc", "chrono/clock"] -no_std = ["no-std-compat", "serde_no_std", "chrono_no_std", "base64/alloc"] serde_no_std = ["serde/derive", "serde/alloc", "serde_json/alloc"] -std = ["snafu/std", "snafu/guide", "serde/std", "serde_json/std", "chrono/std", "base64/std", "url"] [dependencies] base64 = { version = "^0.12", default-features = false } -chrono = { version = "^0.4", default-features = false } +chrono = { version = "^0.4", default-features = false , features = ["serde", "clock"]} delegate-attr = "^0.2" serde = { version = "^1.0", default-features=false } serde_json = { version = "^1.0", default-features = false, features = ["alloc"] } -serde-value = "^0.7" -snafu = { version = "^0.6",default-features = false } +snafu = { version = "^0.6", default-features = false } url = { version = "^2.1", features = ["serde"], optional=true } -[dependencies.no-std-compat] -version = "^0.4.1" -features = ["alloc", "compat_hash", "compat_sync", "compat_macros"] -optional=true +no-std-compat = { version = "^0.4.1", features = ["alloc", "compat_hash", "compat_sync"], optional=true } [target."cfg(not(target_arch = \"wasm32\"))".dependencies] hostname = "^0.3" diff --git a/src/event/attributes.rs b/src/event/attributes.rs index 4c43549e..beffab1d 100644 --- a/src/event/attributes.rs +++ b/src/event/attributes.rs @@ -7,10 +7,10 @@ use serde::Serializer; use std::fmt; use std::prelude::v1::*; +#[cfg(not(feature = "std"))] +use std::string::String as Url; #[cfg(feature = "std")] use url::Url; -#[cfg(not(feature = "std"))] -use String as Url; /// 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) diff --git a/src/event/builder.rs b/src/event/builder.rs index d018fbb7..5d95bed2 100644 --- a/src/event/builder.rs +++ b/src/event/builder.rs @@ -1,4 +1,4 @@ -use super::{DisplayError, Event}; +use super::{url, DisplayError, Event}; use snafu::Snafu; /// Trait to implement a builder for [`Event`]: diff --git a/src/event/format.rs b/src/event/format.rs index 76ef0524..bb6cfc65 100644 --- a/src/event/format.rs +++ b/src/event/format.rs @@ -9,6 +9,7 @@ use serde_value::Value; use std::collections::{BTreeMap, HashMap}; use std::prelude::v1::*; +#[cfg(feature = "std")] macro_rules! parse_optional_field { ($map:ident, $name:literal, $value_variant:ident, $error:ty) => { $map.remove($name) @@ -40,6 +41,38 @@ macro_rules! parse_optional_field { }; } +#[cfg(not(feature = "std"))] +macro_rules! parse_optional_field { + ($map:ident, $name:literal, $value_variant:ident, $error:ty) => { + $map.remove($name) + .map(|val| match val { + Value::$value_variant(v) => Ok(v), + other => Err(<$error>::invalid_type( + crate::event::format::value_to_unexpected(&other), + &stringify!($value_variant), + )), + }) + .transpose() + }; + + ($map:ident, $name:literal, $value_variant:ident, $error:ty, $mapper:expr) => { + $map.remove($name) + .map(|val| match val { + Value::$value_variant(v) => $mapper(&v.to_string()).map_err(|e| { + <$error>::invalid_value( + crate::event::format::value_to_unexpected(&Value::$value_variant(v)), + &e.to_string().as_str(), + ) + }), + other => Err(<$error>::invalid_type( + crate::event::format::value_to_unexpected(&other), + &stringify!($value_variant), + )), + }) + .transpose() + }; +} + macro_rules! parse_field { ($map:ident, $name:literal, $value_variant:ident, $error:ty) => { parse_optional_field!($map, $name, $value_variant, $error)? diff --git a/src/event/mod.rs b/src/event/mod.rs index defbe239..e8a8b24a 100644 --- a/src/event/mod.rs +++ b/src/event/mod.rs @@ -41,9 +41,39 @@ pub(crate) use v10::EventFormatSerializer as EventFormatSerializerV10; use chrono::{DateTime, Utc}; use delegate_attr::delegate; use std::collections::HashMap; -//use std::fmt; use std::prelude::v1::*; + +#[cfg(feature = "std")] use url::Url; +#[cfg(not(feature = "std"))] +use String as Url; + +pub trait UrlExtend { + fn parse(&self) -> Result; +} + +impl UrlExtend for Url { + fn parse(&self) -> Result { + Ok(self.to_string()) + } +} + +pub mod url { + use super::{fmt, String}; + + #[derive(Debug, Clone)] + pub enum ParseError { + Error(String), + } + + impl snafu::Error for ParseError {} + + impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.fmt(f) + } + } +} use core::fmt::{self, Debug, Display}; /// Data structure that represents a [CloudEvent](https://github.com/cloudevents/spec/blob/master/spec.md). diff --git a/src/event/spec_version.rs b/src/event/spec_version.rs index 8ab76aba..d6c68e3d 100644 --- a/src/event/spec_version.rs +++ b/src/event/spec_version.rs @@ -3,7 +3,6 @@ use serde::export::Formatter; use std::convert::TryFrom; use std::fmt; use std::prelude::v1::*; -use std::vec; pub(crate) const SPEC_VERSIONS: [&str; 2] = ["0.3", "1.0"]; diff --git a/src/event/types.rs b/src/event/types.rs index 2d4dd77a..b9db6839 100644 --- a/src/event/types.rs +++ b/src/event/types.rs @@ -1,6 +1,11 @@ use chrono::{DateTime, Utc}; use std::prelude::v1::*; -use url::Url; + +use super::url; +#[cfg(not(feature = "std"))] +use super::{Url, UrlExtend}; +#[cfg(feature = "std")] +use url::{self, ParseError, Url}; /// Trait to define conversion to [`Url`] pub trait TryIntoUrl { @@ -13,12 +18,21 @@ impl TryIntoUrl for Url { } } +#[cfg(not(feature = "std"))] +impl TryIntoUrl for &str { + fn into_url(self) -> Result { + Url::parse(&self.to_string()) + } +} + +#[cfg(feature = "std")] impl TryIntoUrl for &str { fn into_url(self) -> Result { Url::parse(self) } } +#[cfg(feature = "std")] impl TryIntoUrl for String { fn into_url(self) -> Result { self.as_str().into_url() diff --git a/src/event/v03/attributes.rs b/src/event/v03/attributes.rs index 51723cd3..37b189ae 100644 --- a/src/event/v03/attributes.rs +++ b/src/event/v03/attributes.rs @@ -4,9 +4,13 @@ use crate::event::{AttributesReader, AttributesWriter, SpecVersion}; use crate::message::{BinarySerializer, MessageAttributeValue}; use chrono::{DateTime, Utc}; use std::prelude::v1::*; -use url::Url; use uuid::Uuid; +#[cfg(not(feature = "std"))] +use super::super::Url; +#[cfg(feature = "std")] +use url::Url; + pub(crate) const ATTRIBUTE_NAMES: [&str; 8] = [ "specversion", "id", @@ -222,8 +226,10 @@ impl crate::event::message::AttributesDeserializer for super::Attributes { #[cfg(test)] mod tests { use super::*; + use crate::event::UrlExtend; use chrono::NaiveDateTime; + #[cfg(feature = "std")] #[test] fn iterator_test_v03() { let a = Attributes { @@ -259,4 +265,41 @@ mod tests { ); assert_eq!(("time", AttributeValue::Time(&time)), b.next().unwrap()); } + + #[cfg(not(feature = "std"))] + #[test] + fn iterator_test_v03() { + let a = Attributes { + id: String::from("1"), + ty: String::from("someType"), + source: Url::parse(&"https://example.net".to_string()).unwrap(), + datacontenttype: None, + schemaurl: None, + subject: None, + time: Some(DateTime::::from_utc( + NaiveDateTime::from_timestamp(61, 0), + Utc, + )), + }; + let b = &mut a.into_iter(); + let time = DateTime::::from_utc(NaiveDateTime::from_timestamp(61, 0), Utc); + + assert_eq!( + ("specversion", AttributeValue::SpecVersion(SpecVersion::V03)), + b.next().unwrap() + ); + assert_eq!(("id", AttributeValue::String("1")), b.next().unwrap()); + assert_eq!( + ("type", AttributeValue::String("someType")), + b.next().unwrap() + ); + assert_eq!( + ( + "source", + AttributeValue::URIRef(&Url::parse(&"https://example.net".to_string()).unwrap()) + ), + b.next().unwrap() + ); + assert_eq!(("time", AttributeValue::Time(&time)), b.next().unwrap()); + } } diff --git a/src/event/v03/builder.rs b/src/event/v03/builder.rs index 1997aa8e..2dfbc052 100644 --- a/src/event/v03/builder.rs +++ b/src/event/v03/builder.rs @@ -8,6 +8,10 @@ use chrono::{DateTime, Utc}; use std::collections::HashMap; use std::convert::TryInto; use std::prelude::v1::*; + +#[cfg(not(feature = "std"))] +use super::super::Url; +#[cfg(feature = "std")] use url::Url; /// Builder to create a CloudEvent V0.3 diff --git a/src/event/v03/format.rs b/src/event/v03/format.rs index e3e33c4f..f99866a0 100644 --- a/src/event/v03/format.rs +++ b/src/event/v03/format.rs @@ -8,6 +8,10 @@ use serde::{Deserialize, Serializer}; use serde_value::Value; use std::collections::{BTreeMap, HashMap}; use std::prelude::v1::*; + +#[cfg(not(feature = "std"))] +use super::super::{Url, UrlExtend}; +#[cfg(feature = "std")] use url::Url; pub(crate) struct EventFormatDeserializer {} diff --git a/src/event/v10/attributes.rs b/src/event/v10/attributes.rs index 9b109370..a8288bc3 100644 --- a/src/event/v10/attributes.rs +++ b/src/event/v10/attributes.rs @@ -6,10 +6,10 @@ use core::fmt::Debug; use std::prelude::v1::*; use uuid::Uuid; +#[cfg(not(feature = "std"))] +use crate::event::Url; #[cfg(feature = "std")] use url::Url; -#[cfg(not(feature = "std"))] -use String as Url; pub(crate) const ATTRIBUTE_NAMES: [&str; 8] = [ "specversion", @@ -240,8 +240,10 @@ impl AttributesConverter for Attributes { #[cfg(test)] mod tests { use super::*; + use crate::event::UrlExtend; use chrono::NaiveDateTime; + #[cfg(feature = "std")] #[test] fn iterator_test_v10() { let a = Attributes { @@ -277,4 +279,41 @@ mod tests { ); assert_eq!(("time", AttributeValue::Time(&time)), b.next().unwrap()); } + + #[cfg(not(feature = "std"))] + #[test] + fn iterator_test_v10() { + let a = Attributes { + id: String::from("1"), + ty: String::from("someType"), + source: Url::parse(&"https://example.net".to_string()).unwrap(), + datacontenttype: None, + dataschema: None, + subject: None, + time: Some(DateTime::::from_utc( + NaiveDateTime::from_timestamp(61, 0), + Utc, + )), + }; + let b = &mut a.into_iter(); + let time = DateTime::::from_utc(NaiveDateTime::from_timestamp(61, 0), Utc); + + assert_eq!( + ("specversion", AttributeValue::SpecVersion(SpecVersion::V10)), + b.next().unwrap() + ); + assert_eq!(("id", AttributeValue::String("1")), b.next().unwrap()); + assert_eq!( + ("type", AttributeValue::String("someType")), + b.next().unwrap() + ); + assert_eq!( + ( + "source", + AttributeValue::URIRef(&Url::parse(&"https://example.net".to_string()).unwrap()) + ), + b.next().unwrap() + ); + assert_eq!(("time", AttributeValue::Time(&time)), b.next().unwrap()); + } } diff --git a/src/event/v10/builder.rs b/src/event/v10/builder.rs index c1afed67..5f659f52 100644 --- a/src/event/v10/builder.rs +++ b/src/event/v10/builder.rs @@ -8,6 +8,10 @@ use chrono::{DateTime, Utc}; use std::collections::HashMap; use std::convert::TryInto; use std::prelude::v1::*; + +#[cfg(not(feature = "std"))] +use super::super::Url; +#[cfg(feature = "std")] use url::Url; /// Builder to create a CloudEvent V1.0 diff --git a/src/event/v10/format.rs b/src/event/v10/format.rs index 9f7a093c..e49d3f8b 100644 --- a/src/event/v10/format.rs +++ b/src/event/v10/format.rs @@ -8,6 +8,10 @@ use serde::{Deserialize, Serializer}; use serde_value::Value; use std::collections::{BTreeMap, HashMap}; use std::prelude::v1::*; + +#[cfg(not(feature = "std"))] +use super::super::{Url, UrlExtend}; +#[cfg(feature = "std")] use url::Url; pub(crate) struct EventFormatDeserializer {} diff --git a/src/message/error.rs b/src/message/error.rs index 642c2320..7267d9a4 100644 --- a/src/message/error.rs +++ b/src/message/error.rs @@ -2,6 +2,11 @@ use core::fmt::{self, Debug, Display}; use snafu::Snafu; use std::prelude::v1::*; +#[cfg(feature = "std")] +use url; +#[cfg(not(feature = "std"))] +use String as url; + pub struct DisplayError(pub T); impl Debug for DisplayError @@ -47,12 +52,19 @@ pub enum Error { #[snafu(source(from(chrono::ParseError, DisplayError)))] source: DisplayError, }, + #[snafu(display("Error while parsing a url: {}", source))] #[snafu(context(false))] ParseUrlError { + #[cfg(not(feature = "std"))] + #[snafu(source(from(String, DisplayError)))] + source: DisplayError, + + #[cfg(feature = "std")] #[snafu(source(from(url::ParseError, DisplayError)))] source: DisplayError, }, + #[snafu(display("Error while decoding base64: {}", source))] #[snafu(context(false))] Base64DecodingError { diff --git a/src/message/no_std_io.rs b/src/message/hello_no_std_io.rs similarity index 100% rename from src/message/no_std_io.rs rename to src/message/hello_no_std_io.rs diff --git a/tests/attributes_iter.rs b/tests/attributes_iter.rs index d7d8c6e4..3c8aaad8 100644 --- a/tests/attributes_iter.rs +++ b/tests/attributes_iter.rs @@ -3,6 +3,7 @@ use cloudevents::event::AttributeValue; use cloudevents::event::SpecVersion; use test_data::*; +#[cfg(feature="std")] #[test] fn iter_v10_test() { let in_event = v10::full_no_data(); @@ -14,6 +15,7 @@ fn iter_v10_test() { ); } +#[cfg(feature="std")] #[test] fn iter_v03_test() { let in_event = v03::full_json_data(); diff --git a/tests/builder_v03.rs b/tests/builder_v03.rs index 6524aa9c..838e752e 100644 --- a/tests/builder_v03.rs +++ b/tests/builder_v03.rs @@ -7,8 +7,14 @@ use cloudevents::event::{ }; use cloudevents::EventBuilderV03; use std::convert::TryInto; + +use cloudevents::event::UrlExtend; +#[cfg(feature = "std")] use url::Url; +#[cfg(not(feature = "std"))] +use String as Url; +#[cfg(feature = "std")] #[test] fn build_event() { let id = "aaa"; diff --git a/tests/builder_v10.rs b/tests/builder_v10.rs index 60f8bade..a6f7020d 100644 --- a/tests/builder_v10.rs +++ b/tests/builder_v10.rs @@ -7,8 +7,14 @@ use cloudevents::event::{ }; use cloudevents::EventBuilderV10; use std::convert::TryInto; + +use cloudevents::event::UrlExtend; +#[cfg(feature = "std")] use url::Url; +#[cfg(not(feature = "std"))] +use String as Url; +#[cfg(feature = "std")] #[test] fn build_event() { let id = "aaa"; diff --git a/tests/message.rs b/tests/message.rs index 4bb3763a..a655747a 100644 --- a/tests/message.rs +++ b/tests/message.rs @@ -5,6 +5,7 @@ use cloudevents::{AttributesReader, EventBuilder, EventBuilderV03, EventBuilderV use std::convert::TryInto; use test_data::*; +#[cfg(feature="std")] #[test] fn message_v03_roundtrip_structured() -> Result<()> { assert_eq!( @@ -14,6 +15,7 @@ fn message_v03_roundtrip_structured() -> Result<()> { Ok(()) } +#[cfg(feature="std")] #[test] fn message_v03_roundtrip_binary() -> Result<()> { //TODO this code smells because we're missing a proper way in the public APIs @@ -33,6 +35,7 @@ fn message_v03_roundtrip_binary() -> Result<()> { Ok(()) } +#[cfg(feature="std")] #[test] fn message_v10_roundtrip_structured() -> Result<()> { assert_eq!( @@ -42,6 +45,7 @@ fn message_v10_roundtrip_structured() -> Result<()> { Ok(()) } +#[cfg(feature="std")] #[test] fn message_v10_roundtrip_binary() -> Result<()> { //TODO this code smells because we're missing a proper way in the public APIs diff --git a/tests/serde_json.rs b/tests/serde_json.rs index 14f01619..e126a018 100644 --- a/tests/serde_json.rs +++ b/tests/serde_json.rs @@ -7,6 +7,7 @@ mod test_data; use test_data::*; /// This test is a parametrized test that uses data from tests/test_data +#[cfg(feature="std")] #[rstest( in_event, out_json, @@ -53,6 +54,7 @@ fn serialize_should_succeed(in_event: Event, out_json: Value) { } /// This test is a parametrized test that uses data from tests/test_data +#[cfg(feature="std")] #[rstest( in_json, out_event, diff --git a/tests/test_data/v03.rs b/tests/test_data/v03.rs index 2ff1c665..121904ac 100644 --- a/tests/test_data/v03.rs +++ b/tests/test_data/v03.rs @@ -2,8 +2,13 @@ use super::*; use cloudevents::{Event, EventBuilder, EventBuilderV03}; use serde_json::{json, Value}; +use cloudevents::event::UrlExtend; +#[cfg(feature = "std")] use url::Url; +#[cfg(not(feature = "std"))] +use String as Url; +#[cfg(feature = "std")] pub fn minimal() -> Event { EventBuilderV03::new() .id(id()) @@ -22,6 +27,7 @@ pub fn minimal_json() -> Value { }) } +#[cfg(feature = "std")] pub fn full_no_data() -> Event { let (string_ext_name, string_ext_value) = string_extension(); let (bool_ext_name, bool_ext_value) = bool_extension(); @@ -58,6 +64,7 @@ pub fn full_no_data_json() -> Value { }) } +#[cfg(feature = "std")] pub fn full_json_data() -> Event { let (string_ext_name, string_ext_value) = string_extension(); let (bool_ext_name, bool_ext_value) = bool_extension(); @@ -124,6 +131,7 @@ pub fn full_json_base64_data_json() -> Value { }) } +#[cfg(feature = "std")] pub fn full_xml_string_data() -> Event { let (string_ext_name, string_ext_value) = string_extension(); let (bool_ext_name, bool_ext_value) = bool_extension(); @@ -143,6 +151,7 @@ pub fn full_xml_string_data() -> Event { .unwrap() } +#[cfg(feature = "std")] pub fn full_xml_binary_data() -> Event { let (string_ext_name, string_ext_value) = string_extension(); let (bool_ext_name, bool_ext_value) = bool_extension(); diff --git a/tests/test_data/v10.rs b/tests/test_data/v10.rs index a4faa9af..b59b0ff7 100644 --- a/tests/test_data/v10.rs +++ b/tests/test_data/v10.rs @@ -1,8 +1,14 @@ use super::*; use cloudevents::{Event, EventBuilder, EventBuilderV10}; use serde_json::{json, Value}; + +#[cfg(feature="std")] use url::Url; +#[cfg(not(feature="std"))] +use String as Url; +use cloudevents::event::UrlExtend; +#[cfg(feature="std")] pub fn minimal() -> Event { EventBuilderV10::new() .id(id()) @@ -21,6 +27,7 @@ pub fn minimal_json() -> Value { }) } +#[cfg(feature="std")] pub fn full_no_data() -> Event { let (string_ext_name, string_ext_value) = string_extension(); let (bool_ext_name, bool_ext_value) = bool_extension(); @@ -57,6 +64,7 @@ pub fn full_no_data_json() -> Value { }) } +#[cfg(feature="std")] pub fn full_json_data() -> Event { let (string_ext_name, string_ext_value) = string_extension(); let (bool_ext_name, bool_ext_value) = bool_extension(); @@ -122,6 +130,7 @@ pub fn full_json_base64_data_json() -> Value { }) } +#[cfg(feature="std")] pub fn full_xml_string_data() -> Event { let (string_ext_name, string_ext_value) = string_extension(); let (bool_ext_name, bool_ext_value) = bool_extension(); @@ -141,6 +150,7 @@ pub fn full_xml_string_data() -> Event { .unwrap() } +#[cfg(feature="std")] pub fn full_xml_binary_data() -> Event { let (string_ext_name, string_ext_value) = string_extension(); let (bool_ext_name, bool_ext_value) = bool_extension(); diff --git a/tests/version_conversion.rs b/tests/version_conversion.rs index bbbb29bb..e6782d09 100644 --- a/tests/version_conversion.rs +++ b/tests/version_conversion.rs @@ -3,6 +3,7 @@ use cloudevents::event::{EventBuilderV03, EventBuilderV10}; use cloudevents::EventBuilder; use test_data::*; +#[cfg(feature = "std")] #[test] fn v10_to_v03() { let in_event = v10::full_json_data(); @@ -10,6 +11,7 @@ fn v10_to_v03() { assert_eq!(v03::full_json_data(), out_event) } +#[cfg(feature = "std")] #[test] fn v03_to_v10() { let in_event = v03::full_json_data();