Redesigned EventBuilder (#53)
* Progress Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Builder finished Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Fixed all integrations Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Fmt'ed Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Fmt'ed part 2 Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Fixed tests in reqwest integration Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * fmt'ed again Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>
This commit is contained in:
parent
2b91ee8d7a
commit
b832b6bcf4
|
@ -35,14 +35,15 @@ cloudevents-sdk = "0.1.0"
|
||||||
Now you can start creating events:
|
Now you can start creating events:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use cloudevents::EventBuilder;
|
use cloudevents::{EventBuilder, EventBuilderV10};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
let event = EventBuilder::v03()
|
let event = EventBuilderV10::new()
|
||||||
.id("aaa")
|
.id("aaa")
|
||||||
.source(Url::parse("http://localhost").unwrap())
|
.source(Url::parse("http://localhost").unwrap())
|
||||||
.ty("example.demo")
|
.ty("example.demo")
|
||||||
.build();
|
.build()
|
||||||
|
.unwrap();
|
||||||
```
|
```
|
||||||
|
|
||||||
Checkout the examples using our integrations with `actix-web` and `reqwest` to learn how to send and receive events:
|
Checkout the examples using our integrations with `actix-web` and `reqwest` to learn how to send and receive events:
|
||||||
|
|
|
@ -17,7 +17,8 @@ actix-rt = "1"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
bytes = "^0.5"
|
bytes = "^0.5"
|
||||||
futures = "^0.3"
|
futures = "^0.3"
|
||||||
serde_json = "^1.0"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
url = { version = "^2.1", features = ["serde"] }
|
url = { version = "^2.1", features = ["serde"] }
|
||||||
|
serde_json = "^1.0"
|
||||||
|
chrono = { version = "^0.4", features = ["serde"] }
|
|
@ -117,25 +117,32 @@ mod tests {
|
||||||
use actix_web::test;
|
use actix_web::test;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use cloudevents::EventBuilder;
|
use chrono::Utc;
|
||||||
|
use cloudevents::{EventBuilder, EventBuilderV10};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_request() {
|
async fn test_request() {
|
||||||
let expected = EventBuilder::new()
|
let time = Utc::now();
|
||||||
|
let expected = EventBuilderV10::new()
|
||||||
.id("0001")
|
.id("0001")
|
||||||
.ty("example.test")
|
.ty("example.test")
|
||||||
.source(Url::from_str("http://localhost").unwrap())
|
.source("http://localhost/")
|
||||||
|
//TODO this is required now because the message deserializer implictly set default values
|
||||||
|
// As soon as this defaulting doesn't happen anymore, we can remove it (Issues #40/#41)
|
||||||
|
.time(time)
|
||||||
.extension("someint", "10")
|
.extension("someint", "10")
|
||||||
.build();
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let (req, payload) = test::TestRequest::post()
|
let (req, payload) = test::TestRequest::post()
|
||||||
.header("ce-specversion", "1.0")
|
.header("ce-specversion", "1.0")
|
||||||
.header("ce-id", "0001")
|
.header("ce-id", "0001")
|
||||||
.header("ce-type", "example.test")
|
.header("ce-type", "example.test")
|
||||||
.header("ce-source", "http://localhost")
|
.header("ce-source", "http://localhost/")
|
||||||
.header("ce-someint", "10")
|
.header("ce-someint", "10")
|
||||||
|
.header("ce-time", time.to_rfc3339())
|
||||||
.to_http_parts();
|
.to_http_parts();
|
||||||
|
|
||||||
let resp = request_to_event(&req, web::Payload(payload)).await.unwrap();
|
let resp = request_to_event(&req, web::Payload(payload)).await.unwrap();
|
||||||
|
@ -144,15 +151,20 @@ mod tests {
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_request_with_full_data() {
|
async fn test_request_with_full_data() {
|
||||||
|
let time = Utc::now();
|
||||||
let j = json!({"hello": "world"});
|
let j = json!({"hello": "world"});
|
||||||
|
|
||||||
let expected = EventBuilder::new()
|
let expected = EventBuilderV10::new()
|
||||||
.id("0001")
|
.id("0001")
|
||||||
.ty("example.test")
|
.ty("example.test")
|
||||||
.source(Url::from_str("http://localhost").unwrap())
|
.source(Url::from_str("http://localhost").unwrap())
|
||||||
|
//TODO this is required now because the message deserializer implictly set default values
|
||||||
|
// As soon as this defaulting doesn't happen anymore, we can remove it (Issues #40/#41)
|
||||||
|
.time(time)
|
||||||
.data("application/json", j.clone())
|
.data("application/json", j.clone())
|
||||||
.extension("someint", "10")
|
.extension("someint", "10")
|
||||||
.build();
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let (req, payload) = test::TestRequest::post()
|
let (req, payload) = test::TestRequest::post()
|
||||||
.header("ce-specversion", "1.0")
|
.header("ce-specversion", "1.0")
|
||||||
|
@ -160,6 +172,7 @@ mod tests {
|
||||||
.header("ce-type", "example.test")
|
.header("ce-type", "example.test")
|
||||||
.header("ce-source", "http://localhost")
|
.header("ce-source", "http://localhost")
|
||||||
.header("ce-someint", "10")
|
.header("ce-someint", "10")
|
||||||
|
.header("ce-time", time.to_rfc3339())
|
||||||
.header("content-type", "application/json")
|
.header("content-type", "application/json")
|
||||||
.set_json(&j)
|
.set_json(&j)
|
||||||
.to_http_parts();
|
.to_http_parts();
|
||||||
|
|
|
@ -82,19 +82,20 @@ mod tests {
|
||||||
|
|
||||||
use actix_web::http::StatusCode;
|
use actix_web::http::StatusCode;
|
||||||
use actix_web::test;
|
use actix_web::test;
|
||||||
use cloudevents::EventBuilder;
|
use cloudevents::{EventBuilder, EventBuilderV10};
|
||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_response() {
|
async fn test_response() {
|
||||||
let input = EventBuilder::new()
|
let input = EventBuilderV10::new()
|
||||||
.id("0001")
|
.id("0001")
|
||||||
.ty("example.test")
|
.ty("example.test")
|
||||||
.source(Url::from_str("http://localhost/").unwrap())
|
.source(Url::from_str("http://localhost/").unwrap())
|
||||||
.extension("someint", "10")
|
.extension("someint", "10")
|
||||||
.build();
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let resp = event_to_response(input, HttpResponseBuilder::new(StatusCode::OK))
|
let resp = event_to_response(input, HttpResponseBuilder::new(StatusCode::OK))
|
||||||
.await
|
.await
|
||||||
|
@ -130,13 +131,14 @@ mod tests {
|
||||||
async fn test_response_with_full_data() {
|
async fn test_response_with_full_data() {
|
||||||
let j = json!({"hello": "world"});
|
let j = json!({"hello": "world"});
|
||||||
|
|
||||||
let input = EventBuilder::new()
|
let input = EventBuilderV10::new()
|
||||||
.id("0001")
|
.id("0001")
|
||||||
.ty("example.test")
|
.ty("example.test")
|
||||||
.source(Url::from_str("http://localhost").unwrap())
|
.source(Url::from_str("http://localhost").unwrap())
|
||||||
.data("application/json", j.clone())
|
.data("application/json", j.clone())
|
||||||
.extension("someint", "10")
|
.extension("someint", "10")
|
||||||
.build();
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mut resp = event_to_response(input, HttpResponseBuilder::new(StatusCode::OK))
|
let mut resp = event_to_response(input, HttpResponseBuilder::new(StatusCode::OK))
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -14,7 +14,6 @@ repository = "https://github.com/cloudevents/sdk-rust"
|
||||||
cloudevents-sdk = { version = "0.1.0", path = ".." }
|
cloudevents-sdk = { version = "0.1.0", path = ".." }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
bytes = "^0.5"
|
bytes = "^0.5"
|
||||||
serde_json = "^1.0"
|
|
||||||
|
|
||||||
[dependencies.reqwest]
|
[dependencies.reqwest]
|
||||||
version = "0.10.4"
|
version = "0.10.4"
|
||||||
|
@ -25,3 +24,5 @@ features = ["rustls-tls"]
|
||||||
mockito = "0.25.1"
|
mockito = "0.25.1"
|
||||||
tokio = { version = "^0.2", features = ["full"] }
|
tokio = { version = "^0.2", features = ["full"] }
|
||||||
url = { version = "^2.1" }
|
url = { version = "^2.1" }
|
||||||
|
serde_json = "^1.0"
|
||||||
|
chrono = { version = "^0.4", features = ["serde"] }
|
|
@ -73,7 +73,7 @@ mod tests {
|
||||||
use mockito::{mock, Matcher};
|
use mockito::{mock, Matcher};
|
||||||
|
|
||||||
use cloudevents::message::StructuredDeserializer;
|
use cloudevents::message::StructuredDeserializer;
|
||||||
use cloudevents::EventBuilder;
|
use cloudevents::{EventBuilder, EventBuilderV10};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -89,12 +89,13 @@ mod tests {
|
||||||
.match_body(Matcher::Missing)
|
.match_body(Matcher::Missing)
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
let input = EventBuilder::new()
|
let input = EventBuilderV10::new()
|
||||||
.id("0001")
|
.id("0001")
|
||||||
.ty("example.test")
|
.ty("example.test")
|
||||||
.source(Url::from_str("http://localhost/").unwrap())
|
.source(Url::from_str("http://localhost/").unwrap())
|
||||||
.extension("someint", "10")
|
.extension("someint", "10")
|
||||||
.build();
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
event_to_request(input, client.post(&url))
|
event_to_request(input, client.post(&url))
|
||||||
|
@ -121,13 +122,14 @@ mod tests {
|
||||||
.match_body(Matcher::Exact(j.to_string()))
|
.match_body(Matcher::Exact(j.to_string()))
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
let input = EventBuilder::new()
|
let input = EventBuilderV10::new()
|
||||||
.id("0001")
|
.id("0001")
|
||||||
.ty("example.test")
|
.ty("example.test")
|
||||||
.source(Url::from_str("http://localhost").unwrap())
|
.source(Url::from_str("http://localhost").unwrap())
|
||||||
.data("application/json", j.clone())
|
.data("application/json", j.clone())
|
||||||
.extension("someint", "10")
|
.extension("someint", "10")
|
||||||
.build();
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
event_to_request(input, client.post(&url))
|
event_to_request(input, client.post(&url))
|
||||||
|
@ -143,13 +145,14 @@ mod tests {
|
||||||
async fn test_structured_request_with_full_data() {
|
async fn test_structured_request_with_full_data() {
|
||||||
let j = json!({"hello": "world"});
|
let j = json!({"hello": "world"});
|
||||||
|
|
||||||
let input = EventBuilder::new()
|
let input = EventBuilderV10::new()
|
||||||
.id("0001")
|
.id("0001")
|
||||||
.ty("example.test")
|
.ty("example.test")
|
||||||
.source(Url::from_str("http://localhost").unwrap())
|
.source(Url::from_str("http://localhost").unwrap())
|
||||||
.data("application/json", j.clone())
|
.data("application/json", j.clone())
|
||||||
.extension("someint", "10")
|
.extension("someint", "10")
|
||||||
.build();
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let url = mockito::server_url();
|
let url = mockito::server_url();
|
||||||
let m = mock("POST", "/")
|
let m = mock("POST", "/")
|
||||||
|
|
|
@ -112,13 +112,15 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use mockito::mock;
|
use mockito::mock;
|
||||||
|
|
||||||
use cloudevents::EventBuilder;
|
use chrono::Utc;
|
||||||
|
use cloudevents::{EventBuilder, EventBuilderV10};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_response() {
|
async fn test_response() {
|
||||||
|
let time = Utc::now();
|
||||||
let url = mockito::server_url();
|
let url = mockito::server_url();
|
||||||
let _m = mock("GET", "/")
|
let _m = mock("GET", "/")
|
||||||
.with_status(200)
|
.with_status(200)
|
||||||
|
@ -127,14 +129,19 @@ mod tests {
|
||||||
.with_header("ce-type", "example.test")
|
.with_header("ce-type", "example.test")
|
||||||
.with_header("ce-source", "http://localhost")
|
.with_header("ce-source", "http://localhost")
|
||||||
.with_header("ce-someint", "10")
|
.with_header("ce-someint", "10")
|
||||||
|
.with_header("ce-time", &time.to_rfc3339())
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
let expected = EventBuilder::new()
|
let expected = EventBuilderV10::new()
|
||||||
.id("0001")
|
.id("0001")
|
||||||
.ty("example.test")
|
.ty("example.test")
|
||||||
|
//TODO this is required now because the message deserializer implictly set default values
|
||||||
|
// As soon as this defaulting doesn't happen anymore, we can remove it (Issues #40/#41)
|
||||||
|
.time(time)
|
||||||
.source(Url::from_str("http://localhost").unwrap())
|
.source(Url::from_str("http://localhost").unwrap())
|
||||||
.extension("someint", "10")
|
.extension("someint", "10")
|
||||||
.build();
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
let res = client.get(&url).send().await.unwrap();
|
let res = client.get(&url).send().await.unwrap();
|
||||||
|
@ -145,6 +152,7 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_response_with_full_data() {
|
async fn test_response_with_full_data() {
|
||||||
|
let time = Utc::now();
|
||||||
let j = json!({"hello": "world"});
|
let j = json!({"hello": "world"});
|
||||||
|
|
||||||
let url = mockito::server_url();
|
let url = mockito::server_url();
|
||||||
|
@ -156,16 +164,21 @@ mod tests {
|
||||||
.with_header("ce-source", "http://localhost/")
|
.with_header("ce-source", "http://localhost/")
|
||||||
.with_header("content-type", "application/json")
|
.with_header("content-type", "application/json")
|
||||||
.with_header("ce-someint", "10")
|
.with_header("ce-someint", "10")
|
||||||
|
.with_header("ce-time", &time.to_rfc3339())
|
||||||
.with_body(j.to_string())
|
.with_body(j.to_string())
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
let expected = EventBuilder::new()
|
let expected = EventBuilderV10::new()
|
||||||
.id("0001")
|
.id("0001")
|
||||||
.ty("example.test")
|
.ty("example.test")
|
||||||
|
//TODO this is required now because the message deserializer implictly set default values
|
||||||
|
// As soon as this defaulting doesn't happen anymore, we can remove it (Issues #40/#41)
|
||||||
|
.time(time)
|
||||||
.source(Url::from_str("http://localhost").unwrap())
|
.source(Url::from_str("http://localhost").unwrap())
|
||||||
.data("application/json", j.clone())
|
.data("application/json", j.clone())
|
||||||
.extension("someint", "10")
|
.extension("someint", "10")
|
||||||
.build();
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
let res = client.get(&url).send().await.unwrap();
|
let res = client.get(&url).send().await.unwrap();
|
||||||
|
@ -176,14 +189,20 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_structured_response_with_full_data() {
|
async fn test_structured_response_with_full_data() {
|
||||||
|
let time = Utc::now();
|
||||||
|
|
||||||
let j = json!({"hello": "world"});
|
let j = json!({"hello": "world"});
|
||||||
let expected = EventBuilder::new()
|
let expected = EventBuilderV10::new()
|
||||||
.id("0001")
|
.id("0001")
|
||||||
.ty("example.test")
|
.ty("example.test")
|
||||||
|
//TODO this is required now because the message deserializer implictly set default values
|
||||||
|
// As soon as this defaulting doesn't happen anymore, we can remove it (Issues #40/#41)
|
||||||
|
.time(time)
|
||||||
.source(Url::from_str("http://localhost").unwrap())
|
.source(Url::from_str("http://localhost").unwrap())
|
||||||
.data("application/json", j.clone())
|
.data("application/json", j.clone())
|
||||||
.extension("someint", "10")
|
.extension("someint", "10")
|
||||||
.build();
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let url = mockito::server_url();
|
let url = mockito::server_url();
|
||||||
let _m = mock("GET", "/")
|
let _m = mock("GET", "/")
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use actix_web::{get, post, web, App, HttpRequest, HttpResponse, HttpServer};
|
use actix_web::{get, post, web, App, HttpRequest, HttpResponse, HttpServer};
|
||||||
use cloudevents::EventBuilder;
|
use cloudevents::{EventBuilder, EventBuilderV10};
|
||||||
use url::Url;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
#[post("/")]
|
#[post("/")]
|
||||||
async fn post_event(req: HttpRequest, payload: web::Payload) -> Result<String, actix_web::Error> {
|
async fn post_event(req: HttpRequest, payload: web::Payload) -> Result<String, actix_web::Error> {
|
||||||
|
@ -16,15 +16,17 @@ async fn get_event() -> Result<HttpResponse, actix_web::Error> {
|
||||||
let payload = json!({"hello": "world"});
|
let payload = json!({"hello": "world"});
|
||||||
|
|
||||||
Ok(cloudevents_sdk_actix_web::event_to_response(
|
Ok(cloudevents_sdk_actix_web::event_to_response(
|
||||||
EventBuilder::new()
|
EventBuilderV10::new()
|
||||||
.id("0001")
|
.id("0001")
|
||||||
.ty("example.test")
|
.ty("example.test")
|
||||||
.source(Url::from_str("http://localhost/").unwrap())
|
.source(Url::from_str("http://localhost/").unwrap())
|
||||||
.data("application/json", payload)
|
.data("application/json", payload)
|
||||||
.extension("someint", "10")
|
.extension("someint", "10")
|
||||||
.build(),
|
.build()
|
||||||
HttpResponse::Ok()
|
.unwrap(),
|
||||||
).await?)
|
HttpResponse::Ok(),
|
||||||
|
)
|
||||||
|
.await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
|
@ -39,8 +41,8 @@ async fn main() -> std::io::Result<()> {
|
||||||
.service(post_event)
|
.service(post_event)
|
||||||
.service(get_event)
|
.service(get_event)
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:9000")?
|
.bind("127.0.0.1:9000")?
|
||||||
.workers(1)
|
.workers(1)
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
|
use cloudevents::{EventBuilder, EventBuilderV10};
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub async fn run(target: String, ty: String, datacontenttype: String, data: String) -> Result<(), String> {
|
pub async fn run(
|
||||||
let event = cloudevents::EventBuilder::new()
|
target: String,
|
||||||
|
ty: String,
|
||||||
|
datacontenttype: String,
|
||||||
|
data: String,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let event = EventBuilderV10::new()
|
||||||
.ty(ty)
|
.ty(ty)
|
||||||
.data(datacontenttype, data)
|
.data(datacontenttype, data)
|
||||||
.build();
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
println!("Going to send event: {:?}", event);
|
println!("Going to send event: {:?}", event);
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,55 @@
|
||||||
use super::{EventBuilderV03, EventBuilderV10};
|
use super::Event;
|
||||||
|
use snafu::Snafu;
|
||||||
|
|
||||||
/// Builder to create [`super::Event`]:
|
/// Trait to implement a builder for [`Event`]:
|
||||||
/// ```
|
/// ```
|
||||||
/// use cloudevents::EventBuilder;
|
/// use cloudevents::event::{EventBuilderV10, EventBuilder};
|
||||||
/// use chrono::Utc;
|
/// use chrono::Utc;
|
||||||
/// use url::Url;
|
/// use url::Url;
|
||||||
///
|
///
|
||||||
/// let event = EventBuilder::v10()
|
/// let event = EventBuilderV10::new()
|
||||||
/// .id("my_event.my_application")
|
/// .id("my_event.my_application")
|
||||||
/// .source(Url::parse("http://localhost:8080").unwrap())
|
/// .source("http://localhost:8080")
|
||||||
|
/// .ty("example.demo")
|
||||||
/// .time(Utc::now())
|
/// .time(Utc::now())
|
||||||
/// .build();
|
/// .build()
|
||||||
|
/// .unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
pub struct EventBuilder {}
|
///
|
||||||
|
/// You can create an [`EventBuilder`] starting from an existing [`Event`] using the [`From`] trait.
|
||||||
|
/// You can create a default [`EventBuilder`] setting default values for some attributes.
|
||||||
|
pub trait EventBuilder
|
||||||
|
where
|
||||||
|
Self: Clone + Sized + From<Event> + Default,
|
||||||
|
{
|
||||||
|
/// Create a new empty builder
|
||||||
|
fn new() -> Self;
|
||||||
|
|
||||||
impl EventBuilder {
|
/// Build [`super::Event`]
|
||||||
/// Creates a new builder for latest CloudEvents version
|
fn build(self) -> Result<super::Event, Error>;
|
||||||
pub fn new() -> EventBuilderV10 {
|
}
|
||||||
return Self::v10();
|
|
||||||
}
|
/// Represents an error during build process
|
||||||
|
#[derive(Debug, Snafu, Clone)]
|
||||||
/// Creates a new builder for CloudEvents V1.0
|
pub enum Error {
|
||||||
pub fn v10() -> EventBuilderV10 {
|
#[snafu(display("Missing required attribute {}", attribute_name))]
|
||||||
return EventBuilderV10::new();
|
MissingRequiredAttribute { attribute_name: &'static str },
|
||||||
}
|
#[snafu(display(
|
||||||
|
"Error while setting attribute '{}' with timestamp type: {}",
|
||||||
/// Creates a new builder for CloudEvents V0.3
|
attribute_name,
|
||||||
pub fn v03() -> EventBuilderV03 {
|
source
|
||||||
return EventBuilderV03::new();
|
))]
|
||||||
}
|
ParseTimeError {
|
||||||
|
attribute_name: &'static str,
|
||||||
|
source: chrono::ParseError,
|
||||||
|
},
|
||||||
|
#[snafu(display(
|
||||||
|
"Error while setting attribute '{}' with uri/uriref type: {}",
|
||||||
|
attribute_name,
|
||||||
|
source
|
||||||
|
))]
|
||||||
|
ParseUrlError {
|
||||||
|
attribute_name: &'static str,
|
||||||
|
source: url::ParseError,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,15 +7,18 @@ mod extensions;
|
||||||
mod format;
|
mod format;
|
||||||
mod message;
|
mod message;
|
||||||
mod spec_version;
|
mod spec_version;
|
||||||
|
mod types;
|
||||||
|
|
||||||
pub use attributes::Attributes;
|
pub use attributes::Attributes;
|
||||||
pub use attributes::{AttributesReader, AttributesWriter};
|
pub use attributes::{AttributesReader, AttributesWriter};
|
||||||
|
pub use builder::Error as EventBuilderError;
|
||||||
pub use builder::EventBuilder;
|
pub use builder::EventBuilder;
|
||||||
pub use data::Data;
|
pub use data::Data;
|
||||||
pub use event::Event;
|
pub use event::Event;
|
||||||
pub use extensions::ExtensionValue;
|
pub use extensions::ExtensionValue;
|
||||||
pub use spec_version::InvalidSpecVersion;
|
pub use spec_version::InvalidSpecVersion;
|
||||||
pub use spec_version::SpecVersion;
|
pub use spec_version::SpecVersion;
|
||||||
|
pub use types::{TryIntoTime, TryIntoUrl};
|
||||||
|
|
||||||
mod v03;
|
mod v03;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
/// Trait to define conversion to [`Url`]
|
||||||
|
pub trait TryIntoUrl {
|
||||||
|
fn into_url(self) -> Result<Url, url::ParseError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryIntoUrl for Url {
|
||||||
|
fn into_url(self) -> Result<Url, url::ParseError> {
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryIntoUrl for &str {
|
||||||
|
fn into_url(self) -> Result<Url, url::ParseError> {
|
||||||
|
Url::parse(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryIntoUrl for String {
|
||||||
|
fn into_url(self) -> Result<Url, url::ParseError> {
|
||||||
|
self.as_str().into_url()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait TryIntoTime {
|
||||||
|
fn into_time(self) -> Result<DateTime<Utc>, chrono::ParseError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryIntoTime for DateTime<Utc> {
|
||||||
|
fn into_time(self) -> Result<DateTime<Utc>, chrono::ParseError> {
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait to define conversion to [`DateTime`]
|
||||||
|
impl TryIntoTime for &str {
|
||||||
|
fn into_time(self) -> Result<DateTime<Utc>, chrono::ParseError> {
|
||||||
|
Ok(DateTime::<Utc>::from(DateTime::parse_from_rfc3339(self)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryIntoTime for String {
|
||||||
|
fn into_time(self) -> Result<DateTime<Utc>, chrono::ParseError> {
|
||||||
|
self.as_str().into_time()
|
||||||
|
}
|
||||||
|
}
|
|
@ -159,7 +159,7 @@ impl Default for Attributes {
|
||||||
datacontenttype: None,
|
datacontenttype: None,
|
||||||
schemaurl: None,
|
schemaurl: None,
|
||||||
subject: None,
|
subject: None,
|
||||||
time: None,
|
time: Some(Utc::now()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,58 +1,66 @@
|
||||||
use super::Attributes as AttributesV03;
|
use super::Attributes as AttributesV03;
|
||||||
use crate::event::{Attributes, AttributesWriter, Data, Event, ExtensionValue};
|
use crate::event::{
|
||||||
|
Attributes, Data, Event, EventBuilderError, ExtensionValue, TryIntoTime, TryIntoUrl,
|
||||||
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
/// Builder to create a CloudEvent V0.3
|
/// Builder to create a CloudEvent V0.3
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct EventBuilder {
|
pub struct EventBuilder {
|
||||||
event: Event,
|
id: Option<String>,
|
||||||
|
ty: Option<String>,
|
||||||
|
source: Option<Url>,
|
||||||
|
datacontenttype: Option<String>,
|
||||||
|
schemaurl: Option<Url>,
|
||||||
|
subject: Option<String>,
|
||||||
|
time: Option<DateTime<Utc>>,
|
||||||
|
data: Option<Data>,
|
||||||
|
extensions: HashMap<String, ExtensionValue>,
|
||||||
|
error: Option<EventBuilderError>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventBuilder {
|
impl EventBuilder {
|
||||||
pub fn from(event: Event) -> Self {
|
|
||||||
EventBuilder {
|
|
||||||
event: Event {
|
|
||||||
attributes: event.attributes.into_v03(),
|
|
||||||
data: event.data,
|
|
||||||
extensions: event.extensions,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new() -> Self {
|
|
||||||
EventBuilder {
|
|
||||||
event: Event {
|
|
||||||
attributes: Attributes::V03(AttributesV03::default()),
|
|
||||||
data: None,
|
|
||||||
extensions: HashMap::new(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id(mut self, id: impl Into<String>) -> Self {
|
pub fn id(mut self, id: impl Into<String>) -> Self {
|
||||||
self.event.set_id(id);
|
self.id = Some(id.into());
|
||||||
return self;
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn source(mut self, source: impl Into<Url>) -> Self {
|
pub fn source(mut self, source: impl TryIntoUrl) -> Self {
|
||||||
self.event.set_source(source);
|
match source.into_url() {
|
||||||
return self;
|
Ok(u) => self.source = Some(u),
|
||||||
|
Err(e) => {
|
||||||
|
self.error = Some(EventBuilderError::ParseUrlError {
|
||||||
|
attribute_name: "source",
|
||||||
|
source: e,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ty(mut self, ty: impl Into<String>) -> Self {
|
pub fn ty(mut self, ty: impl Into<String>) -> Self {
|
||||||
self.event.set_type(ty);
|
self.ty = Some(ty.into());
|
||||||
return self;
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subject(mut self, subject: impl Into<String>) -> Self {
|
pub fn subject(mut self, subject: impl Into<String>) -> Self {
|
||||||
self.event.set_subject(Some(subject));
|
self.subject = Some(subject.into());
|
||||||
return self;
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn time(mut self, time: impl Into<DateTime<Utc>>) -> Self {
|
pub fn time(mut self, time: impl TryIntoTime) -> Self {
|
||||||
self.event.set_time(Some(time));
|
match time.into_time() {
|
||||||
return self;
|
Ok(u) => self.time = Some(u),
|
||||||
|
Err(e) => {
|
||||||
|
self.error = Some(EventBuilderError::ParseTimeError {
|
||||||
|
attribute_name: "time",
|
||||||
|
source: e,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extension(
|
pub fn extension(
|
||||||
|
@ -60,75 +68,108 @@ impl EventBuilder {
|
||||||
extension_name: &str,
|
extension_name: &str,
|
||||||
extension_value: impl Into<ExtensionValue>,
|
extension_value: impl Into<ExtensionValue>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.event.set_extension(extension_name, extension_value);
|
self.extensions
|
||||||
return self;
|
.insert(extension_name.to_owned(), extension_value.into());
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn data(mut self, datacontenttype: impl Into<String>, data: impl Into<Data>) -> Self {
|
pub fn data(mut self, datacontenttype: impl Into<String>, data: impl Into<Data>) -> Self {
|
||||||
self.event.write_data(datacontenttype, data);
|
self.datacontenttype = Some(datacontenttype.into());
|
||||||
return self;
|
self.data = Some(data.into());
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn data_with_schema(
|
pub fn data_with_schema(
|
||||||
mut self,
|
mut self,
|
||||||
datacontenttype: impl Into<String>,
|
datacontenttype: impl Into<String>,
|
||||||
schemaurl: impl Into<Url>,
|
schemaurl: impl TryIntoUrl,
|
||||||
data: impl Into<Data>,
|
data: impl Into<Data>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.event
|
self.datacontenttype = Some(datacontenttype.into());
|
||||||
.write_data_with_schema(datacontenttype, schemaurl, data);
|
match schemaurl.into_url() {
|
||||||
return self;
|
Ok(u) => self.schemaurl = Some(u),
|
||||||
}
|
Err(e) => {
|
||||||
|
self.error = Some(EventBuilderError::ParseUrlError {
|
||||||
pub fn build(self) -> Event {
|
attribute_name: "schemaurl",
|
||||||
self.event
|
source: e,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.data = Some(data.into());
|
||||||
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
impl From<Event> for EventBuilder {
|
||||||
mod tests {
|
fn from(event: Event) -> Self {
|
||||||
use super::*;
|
let attributes = match event.attributes.into_v03() {
|
||||||
use crate::event::{AttributesReader, SpecVersion};
|
Attributes::V03(attr) => attr,
|
||||||
|
// This branch is unreachable because into_v03() returns
|
||||||
|
// always a Attributes::V03
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
#[test]
|
EventBuilder {
|
||||||
fn build_event() {
|
id: Some(attributes.id),
|
||||||
let id = "aaa";
|
ty: Some(attributes.ty),
|
||||||
let source = Url::parse("http://localhost:8080").unwrap();
|
source: Some(attributes.source),
|
||||||
let ty = "bbb";
|
datacontenttype: attributes.datacontenttype,
|
||||||
let subject = "francesco";
|
schemaurl: attributes.schemaurl,
|
||||||
let time: DateTime<Utc> = Utc::now();
|
subject: attributes.subject,
|
||||||
let extension_name = "ext";
|
time: attributes.time,
|
||||||
let extension_value = 10i64;
|
data: event.data,
|
||||||
let content_type = "application/json";
|
extensions: event.extensions,
|
||||||
let schema = Url::parse("http://localhost:8080/schema").unwrap();
|
error: None,
|
||||||
let data = serde_json::json!({
|
}
|
||||||
"hello": "world"
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
let event = EventBuilder::new()
|
impl Default for EventBuilder {
|
||||||
.id(id)
|
fn default() -> Self {
|
||||||
.source(source.clone())
|
Self::from(Event::default())
|
||||||
.ty(ty)
|
}
|
||||||
.subject(subject)
|
}
|
||||||
.time(time)
|
|
||||||
.extension(extension_name, extension_value)
|
impl crate::event::builder::EventBuilder for EventBuilder {
|
||||||
.data_with_schema(content_type, schema.clone(), data.clone())
|
fn new() -> Self {
|
||||||
.build();
|
EventBuilder {
|
||||||
|
id: None,
|
||||||
assert_eq!(SpecVersion::V03, event.get_specversion());
|
ty: None,
|
||||||
assert_eq!(id, event.get_id());
|
source: None,
|
||||||
assert_eq!(source, event.get_source().clone());
|
datacontenttype: None,
|
||||||
assert_eq!(ty, event.get_type());
|
schemaurl: None,
|
||||||
assert_eq!(subject, event.get_subject().unwrap());
|
subject: None,
|
||||||
assert_eq!(time, event.get_time().unwrap().clone());
|
time: None,
|
||||||
assert_eq!(
|
data: None,
|
||||||
ExtensionValue::from(extension_value),
|
extensions: Default::default(),
|
||||||
event.get_extension(extension_name).unwrap().clone()
|
error: None,
|
||||||
);
|
}
|
||||||
assert_eq!(content_type, event.get_datacontenttype().unwrap());
|
}
|
||||||
assert_eq!(schema, event.get_dataschema().unwrap().clone());
|
|
||||||
|
fn build(self) -> Result<Event, EventBuilderError> {
|
||||||
let event_data: serde_json::Value = event.try_get_data().unwrap().unwrap();
|
match self.error {
|
||||||
assert_eq!(data, event_data);
|
Some(e) => Err(e),
|
||||||
|
None => Ok(Event {
|
||||||
|
attributes: Attributes::V03(AttributesV03 {
|
||||||
|
id: self.id.ok_or(EventBuilderError::MissingRequiredAttribute {
|
||||||
|
attribute_name: "id",
|
||||||
|
})?,
|
||||||
|
ty: self.ty.ok_or(EventBuilderError::MissingRequiredAttribute {
|
||||||
|
attribute_name: "type",
|
||||||
|
})?,
|
||||||
|
source: self
|
||||||
|
.source
|
||||||
|
.ok_or(EventBuilderError::MissingRequiredAttribute {
|
||||||
|
attribute_name: "source",
|
||||||
|
})?,
|
||||||
|
datacontenttype: self.datacontenttype,
|
||||||
|
schemaurl: self.schemaurl,
|
||||||
|
subject: self.subject,
|
||||||
|
time: self.time,
|
||||||
|
}),
|
||||||
|
data: self.data,
|
||||||
|
extensions: self.extensions,
|
||||||
|
}),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ mod builder;
|
||||||
mod format;
|
mod format;
|
||||||
mod message;
|
mod message;
|
||||||
|
|
||||||
pub(crate) use crate::event::v03::format::EventFormatDeserializer;
|
|
||||||
pub(crate) use crate::event::v03::format::EventFormatSerializer;
|
|
||||||
pub use attributes::Attributes;
|
pub use attributes::Attributes;
|
||||||
pub(crate) use attributes::ATTRIBUTE_NAMES;
|
pub(crate) use attributes::ATTRIBUTE_NAMES;
|
||||||
pub use builder::EventBuilder;
|
pub use builder::EventBuilder;
|
||||||
|
pub(crate) use format::EventFormatDeserializer;
|
||||||
|
pub(crate) use format::EventFormatSerializer;
|
||||||
|
|
|
@ -158,7 +158,7 @@ impl Default for Attributes {
|
||||||
datacontenttype: None,
|
datacontenttype: None,
|
||||||
dataschema: None,
|
dataschema: None,
|
||||||
subject: None,
|
subject: None,
|
||||||
time: None,
|
time: Some(Utc::now()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,58 +1,66 @@
|
||||||
use super::Attributes as AttributesV10;
|
use super::Attributes as AttributesV10;
|
||||||
use crate::event::{Attributes, AttributesWriter, Data, Event, ExtensionValue};
|
use crate::event::{
|
||||||
|
Attributes, Data, Event, EventBuilderError, ExtensionValue, TryIntoTime, TryIntoUrl,
|
||||||
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
/// Builder to create a CloudEvent V1.0
|
/// Builder to create a CloudEvent V1.0
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct EventBuilder {
|
pub struct EventBuilder {
|
||||||
event: Event,
|
id: Option<String>,
|
||||||
|
ty: Option<String>,
|
||||||
|
source: Option<Url>,
|
||||||
|
datacontenttype: Option<String>,
|
||||||
|
dataschema: Option<Url>,
|
||||||
|
subject: Option<String>,
|
||||||
|
time: Option<DateTime<Utc>>,
|
||||||
|
data: Option<Data>,
|
||||||
|
extensions: HashMap<String, ExtensionValue>,
|
||||||
|
error: Option<EventBuilderError>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventBuilder {
|
impl EventBuilder {
|
||||||
pub fn from(event: Event) -> Self {
|
|
||||||
EventBuilder {
|
|
||||||
event: Event {
|
|
||||||
attributes: event.attributes.into_v10(),
|
|
||||||
data: event.data,
|
|
||||||
extensions: event.extensions,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new() -> Self {
|
|
||||||
EventBuilder {
|
|
||||||
event: Event {
|
|
||||||
attributes: Attributes::V10(AttributesV10::default()),
|
|
||||||
data: None,
|
|
||||||
extensions: HashMap::new(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id(mut self, id: impl Into<String>) -> Self {
|
pub fn id(mut self, id: impl Into<String>) -> Self {
|
||||||
self.event.set_id(id);
|
self.id = Some(id.into());
|
||||||
return self;
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn source(mut self, source: impl Into<Url>) -> Self {
|
pub fn source(mut self, source: impl TryIntoUrl) -> Self {
|
||||||
self.event.set_source(source);
|
match source.into_url() {
|
||||||
return self;
|
Ok(u) => self.source = Some(u),
|
||||||
|
Err(e) => {
|
||||||
|
self.error = Some(EventBuilderError::ParseUrlError {
|
||||||
|
attribute_name: "source",
|
||||||
|
source: e,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ty(mut self, ty: impl Into<String>) -> Self {
|
pub fn ty(mut self, ty: impl Into<String>) -> Self {
|
||||||
self.event.set_type(ty);
|
self.ty = Some(ty.into());
|
||||||
return self;
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subject(mut self, subject: impl Into<String>) -> Self {
|
pub fn subject(mut self, subject: impl Into<String>) -> Self {
|
||||||
self.event.set_subject(Some(subject));
|
self.subject = Some(subject.into());
|
||||||
return self;
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn time(mut self, time: impl Into<DateTime<Utc>>) -> Self {
|
pub fn time(mut self, time: impl TryIntoTime) -> Self {
|
||||||
self.event.set_time(Some(time));
|
match time.into_time() {
|
||||||
return self;
|
Ok(u) => self.time = Some(u),
|
||||||
|
Err(e) => {
|
||||||
|
self.error = Some(EventBuilderError::ParseTimeError {
|
||||||
|
attribute_name: "time",
|
||||||
|
source: e,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extension(
|
pub fn extension(
|
||||||
|
@ -60,75 +68,108 @@ impl EventBuilder {
|
||||||
extension_name: &str,
|
extension_name: &str,
|
||||||
extension_value: impl Into<ExtensionValue>,
|
extension_value: impl Into<ExtensionValue>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.event.set_extension(extension_name, extension_value);
|
self.extensions
|
||||||
return self;
|
.insert(extension_name.to_owned(), extension_value.into());
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn data(mut self, datacontenttype: impl Into<String>, data: impl Into<Data>) -> Self {
|
pub fn data(mut self, datacontenttype: impl Into<String>, data: impl Into<Data>) -> Self {
|
||||||
self.event.write_data(datacontenttype, data);
|
self.datacontenttype = Some(datacontenttype.into());
|
||||||
return self;
|
self.data = Some(data.into());
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn data_with_schema(
|
pub fn data_with_schema(
|
||||||
mut self,
|
mut self,
|
||||||
datacontenttype: impl Into<String>,
|
datacontenttype: impl Into<String>,
|
||||||
dataschema: impl Into<Url>,
|
schemaurl: impl TryIntoUrl,
|
||||||
data: impl Into<Data>,
|
data: impl Into<Data>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.event
|
self.datacontenttype = Some(datacontenttype.into());
|
||||||
.write_data_with_schema(datacontenttype, dataschema, data);
|
match schemaurl.into_url() {
|
||||||
return self;
|
Ok(u) => self.dataschema = Some(u),
|
||||||
}
|
Err(e) => {
|
||||||
|
self.error = Some(EventBuilderError::ParseUrlError {
|
||||||
pub fn build(self) -> Event {
|
attribute_name: "dataschema",
|
||||||
self.event
|
source: e,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.data = Some(data.into());
|
||||||
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
impl From<Event> for EventBuilder {
|
||||||
mod tests {
|
fn from(event: Event) -> Self {
|
||||||
use super::*;
|
let attributes = match event.attributes.into_v10() {
|
||||||
use crate::event::{AttributesReader, SpecVersion};
|
Attributes::V10(attr) => attr,
|
||||||
|
// This branch is unreachable because into_v10() returns
|
||||||
|
// always a Attributes::V10
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
#[test]
|
EventBuilder {
|
||||||
fn build_event() {
|
id: Some(attributes.id),
|
||||||
let id = "aaa";
|
ty: Some(attributes.ty),
|
||||||
let source = Url::parse("http://localhost:8080").unwrap();
|
source: Some(attributes.source),
|
||||||
let ty = "bbb";
|
datacontenttype: attributes.datacontenttype,
|
||||||
let subject = "francesco";
|
dataschema: attributes.dataschema,
|
||||||
let time: DateTime<Utc> = Utc::now();
|
subject: attributes.subject,
|
||||||
let extension_name = "ext";
|
time: attributes.time,
|
||||||
let extension_value = 10i64;
|
data: event.data,
|
||||||
let content_type = "application/json";
|
extensions: event.extensions,
|
||||||
let schema = Url::parse("http://localhost:8080/schema").unwrap();
|
error: None,
|
||||||
let data = serde_json::json!({
|
}
|
||||||
"hello": "world"
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
let event = EventBuilder::new()
|
impl Default for EventBuilder {
|
||||||
.id(id)
|
fn default() -> Self {
|
||||||
.source(source.clone())
|
Self::from(Event::default())
|
||||||
.ty(ty)
|
}
|
||||||
.subject(subject)
|
}
|
||||||
.time(time)
|
|
||||||
.extension(extension_name, extension_value)
|
impl crate::event::builder::EventBuilder for EventBuilder {
|
||||||
.data_with_schema(content_type, schema.clone(), data.clone())
|
fn new() -> Self {
|
||||||
.build();
|
EventBuilder {
|
||||||
|
id: None,
|
||||||
assert_eq!(SpecVersion::V10, event.get_specversion());
|
ty: None,
|
||||||
assert_eq!(id, event.get_id());
|
source: None,
|
||||||
assert_eq!(source, event.get_source().clone());
|
datacontenttype: None,
|
||||||
assert_eq!(ty, event.get_type());
|
dataschema: None,
|
||||||
assert_eq!(subject, event.get_subject().unwrap());
|
subject: None,
|
||||||
assert_eq!(time, event.get_time().unwrap().clone());
|
time: None,
|
||||||
assert_eq!(
|
data: None,
|
||||||
ExtensionValue::from(extension_value),
|
extensions: Default::default(),
|
||||||
event.get_extension(extension_name).unwrap().clone()
|
error: None,
|
||||||
);
|
}
|
||||||
assert_eq!(content_type, event.get_datacontenttype().unwrap());
|
}
|
||||||
assert_eq!(schema, event.get_dataschema().unwrap().clone());
|
|
||||||
|
fn build(self) -> Result<Event, EventBuilderError> {
|
||||||
let event_data: serde_json::Value = event.try_get_data().unwrap().unwrap();
|
match self.error {
|
||||||
assert_eq!(data, event_data);
|
Some(e) => Err(e),
|
||||||
|
None => Ok(Event {
|
||||||
|
attributes: Attributes::V10(AttributesV10 {
|
||||||
|
id: self.id.ok_or(EventBuilderError::MissingRequiredAttribute {
|
||||||
|
attribute_name: "id",
|
||||||
|
})?,
|
||||||
|
ty: self.ty.ok_or(EventBuilderError::MissingRequiredAttribute {
|
||||||
|
attribute_name: "type",
|
||||||
|
})?,
|
||||||
|
source: self
|
||||||
|
.source
|
||||||
|
.ok_or(EventBuilderError::MissingRequiredAttribute {
|
||||||
|
attribute_name: "source",
|
||||||
|
})?,
|
||||||
|
datacontenttype: self.datacontenttype,
|
||||||
|
dataschema: self.dataschema,
|
||||||
|
subject: self.subject,
|
||||||
|
time: self.time,
|
||||||
|
}),
|
||||||
|
data: self.data,
|
||||||
|
extensions: self.extensions,
|
||||||
|
}),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ mod builder;
|
||||||
mod format;
|
mod format;
|
||||||
mod message;
|
mod message;
|
||||||
|
|
||||||
pub(crate) use crate::event::v10::format::EventFormatDeserializer;
|
|
||||||
pub(crate) use crate::event::v10::format::EventFormatSerializer;
|
|
||||||
pub use attributes::Attributes;
|
pub use attributes::Attributes;
|
||||||
pub(crate) use attributes::ATTRIBUTE_NAMES;
|
pub(crate) use attributes::ATTRIBUTE_NAMES;
|
||||||
pub use builder::EventBuilder;
|
pub use builder::EventBuilder;
|
||||||
|
pub(crate) use format::EventFormatDeserializer;
|
||||||
|
pub(crate) use format::EventFormatSerializer;
|
||||||
|
|
12
src/lib.rs
12
src/lib.rs
|
@ -1,15 +1,17 @@
|
||||||
//! This crate implements the [CloudEvents](https://cloudevents.io/) Spec for Rust.
|
//! This crate implements the [CloudEvents](https://cloudevents.io/) Spec for Rust.
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! use cloudevents::{EventBuilder, AttributesReader};
|
//! use cloudevents::{EventBuilder, AttributesReader, EventBuilderV10};
|
||||||
//! use chrono::Utc;
|
//! use chrono::Utc;
|
||||||
//! use url::Url;
|
//! use url::Url;
|
||||||
//!
|
//!
|
||||||
//! let event = EventBuilder::v10()
|
//! let event = EventBuilderV10::new()
|
||||||
//! .id("my_event.my_application")
|
//! .id("my_event.my_application")
|
||||||
//! .source(Url::parse("http://localhost:8080").unwrap())
|
//! .source("http://localhost:8080")
|
||||||
|
//! .ty("example.demo")
|
||||||
//! .time(Utc::now())
|
//! .time(Utc::now())
|
||||||
//! .build();
|
//! .build()
|
||||||
|
//! .unwrap();
|
||||||
//!
|
//!
|
||||||
//! println!("CloudEvent Id: {}", event.get_id());
|
//! println!("CloudEvent Id: {}", event.get_id());
|
||||||
//! println!("CloudEvent Time: {}", event.get_time().unwrap());
|
//! println!("CloudEvent Time: {}", event.get_time().unwrap());
|
||||||
|
@ -32,5 +34,5 @@ pub mod event;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
|
|
||||||
pub use event::Event;
|
pub use event::Event;
|
||||||
pub use event::EventBuilder;
|
|
||||||
pub use event::{AttributesReader, AttributesWriter};
|
pub use event::{AttributesReader, AttributesWriter};
|
||||||
|
pub use event::{EventBuilder, EventBuilderV03, EventBuilderV10};
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
#[macro_use]
|
||||||
|
mod util;
|
||||||
|
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use cloudevents::event::{
|
||||||
|
AttributesReader, EventBuilder, EventBuilderError, ExtensionValue, SpecVersion,
|
||||||
|
};
|
||||||
|
use cloudevents::EventBuilderV03;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn build_event() {
|
||||||
|
let id = "aaa";
|
||||||
|
let source = Url::parse("http://localhost:8080").unwrap();
|
||||||
|
let ty = "bbb";
|
||||||
|
let subject = "francesco";
|
||||||
|
let time: DateTime<Utc> = Utc::now();
|
||||||
|
let extension_name = "ext";
|
||||||
|
let extension_value = 10i64;
|
||||||
|
let content_type = "application/json";
|
||||||
|
let schema = Url::parse("http://localhost:8080/schema").unwrap();
|
||||||
|
let data = serde_json::json!({
|
||||||
|
"hello": "world"
|
||||||
|
});
|
||||||
|
|
||||||
|
let event = EventBuilderV03::new()
|
||||||
|
.id(id)
|
||||||
|
.source(source.clone())
|
||||||
|
.ty(ty)
|
||||||
|
.subject(subject)
|
||||||
|
.time(time)
|
||||||
|
.extension(extension_name, extension_value)
|
||||||
|
.data_with_schema(content_type, schema.clone(), data.clone())
|
||||||
|
.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!(
|
||||||
|
ExtensionValue::from(extension_value),
|
||||||
|
event.get_extension(extension_name).unwrap().clone()
|
||||||
|
);
|
||||||
|
assert_eq!(content_type, event.get_datacontenttype().unwrap());
|
||||||
|
assert_eq!(schema, event.get_dataschema().unwrap().clone());
|
||||||
|
|
||||||
|
let event_data: serde_json::Value = event.try_get_data().unwrap().unwrap();
|
||||||
|
assert_eq!(data, event_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn build_missing_id() {
|
||||||
|
let res = EventBuilderV03::new()
|
||||||
|
.source("http://localhost:8080")
|
||||||
|
.build();
|
||||||
|
assert_match_pattern!(
|
||||||
|
res,
|
||||||
|
Err(EventBuilderError::MissingRequiredAttribute {
|
||||||
|
attribute_name: "id"
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn source_invalid_url() {
|
||||||
|
let res = EventBuilderV03::new().source("").build();
|
||||||
|
assert_match_pattern!(
|
||||||
|
res,
|
||||||
|
Err(EventBuilderError::ParseUrlError {
|
||||||
|
attribute_name: "source",
|
||||||
|
..
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_builds() {
|
||||||
|
let res = EventBuilderV03::default().build();
|
||||||
|
assert_match_pattern!(res, Ok(_));
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
#[macro_use]
|
||||||
|
mod util;
|
||||||
|
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use cloudevents::event::{
|
||||||
|
AttributesReader, EventBuilder, EventBuilderError, ExtensionValue, SpecVersion,
|
||||||
|
};
|
||||||
|
use cloudevents::EventBuilderV10;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn build_event() {
|
||||||
|
let id = "aaa";
|
||||||
|
let source = Url::parse("http://localhost:8080").unwrap();
|
||||||
|
let ty = "bbb";
|
||||||
|
let subject = "francesco";
|
||||||
|
let time: DateTime<Utc> = Utc::now();
|
||||||
|
let extension_name = "ext";
|
||||||
|
let extension_value = 10i64;
|
||||||
|
let content_type = "application/json";
|
||||||
|
let schema = Url::parse("http://localhost:8080/schema").unwrap();
|
||||||
|
let data = serde_json::json!({
|
||||||
|
"hello": "world"
|
||||||
|
});
|
||||||
|
|
||||||
|
let event = EventBuilderV10::new()
|
||||||
|
.id(id)
|
||||||
|
.source(source.clone())
|
||||||
|
.ty(ty)
|
||||||
|
.subject(subject)
|
||||||
|
.time(time)
|
||||||
|
.extension(extension_name, extension_value)
|
||||||
|
.data_with_schema(content_type, schema.clone(), data.clone())
|
||||||
|
.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!(
|
||||||
|
ExtensionValue::from(extension_value),
|
||||||
|
event.get_extension(extension_name).unwrap().clone()
|
||||||
|
);
|
||||||
|
assert_eq!(content_type, event.get_datacontenttype().unwrap());
|
||||||
|
assert_eq!(schema, event.get_dataschema().unwrap().clone());
|
||||||
|
|
||||||
|
let event_data: serde_json::Value = event.try_get_data().unwrap().unwrap();
|
||||||
|
assert_eq!(data, event_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn build_missing_id() {
|
||||||
|
let res = EventBuilderV10::new()
|
||||||
|
.source("http://localhost:8080")
|
||||||
|
.build();
|
||||||
|
assert_match_pattern!(
|
||||||
|
res,
|
||||||
|
Err(EventBuilderError::MissingRequiredAttribute {
|
||||||
|
attribute_name: "id"
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn source_invalid_url() {
|
||||||
|
let res = EventBuilderV10::new().source("").build();
|
||||||
|
assert_match_pattern!(
|
||||||
|
res,
|
||||||
|
Err(EventBuilderError::ParseUrlError {
|
||||||
|
attribute_name: "source",
|
||||||
|
..
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_builds() {
|
||||||
|
let res = EventBuilderV10::default().build();
|
||||||
|
assert_match_pattern!(res, Ok(_));
|
||||||
|
}
|
|
@ -1,15 +1,16 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use cloudevents::{Event, EventBuilder};
|
use cloudevents::{Event, EventBuilder, EventBuilderV03};
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub fn minimal() -> Event {
|
pub fn minimal() -> Event {
|
||||||
EventBuilder::v03()
|
EventBuilderV03::new()
|
||||||
.id(id())
|
.id(id())
|
||||||
.source(Url::parse(source().as_ref()).unwrap())
|
.source(Url::parse(source().as_ref()).unwrap())
|
||||||
.ty(ty())
|
.ty(ty())
|
||||||
.build()
|
.build()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn minimal_json() -> Value {
|
pub fn minimal_json() -> Value {
|
||||||
|
@ -26,7 +27,7 @@ pub fn full_no_data() -> Event {
|
||||||
let (bool_ext_name, bool_ext_value) = bool_extension();
|
let (bool_ext_name, bool_ext_value) = bool_extension();
|
||||||
let (int_ext_name, int_ext_value) = int_extension();
|
let (int_ext_name, int_ext_value) = int_extension();
|
||||||
|
|
||||||
EventBuilder::v03()
|
EventBuilderV03::new()
|
||||||
.id(id())
|
.id(id())
|
||||||
.source(Url::parse(source().as_ref()).unwrap())
|
.source(Url::parse(source().as_ref()).unwrap())
|
||||||
.ty(ty())
|
.ty(ty())
|
||||||
|
@ -36,6 +37,7 @@ pub fn full_no_data() -> Event {
|
||||||
.extension(&bool_ext_name, bool_ext_value)
|
.extension(&bool_ext_name, bool_ext_value)
|
||||||
.extension(&int_ext_name, int_ext_value)
|
.extension(&int_ext_name, int_ext_value)
|
||||||
.build()
|
.build()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full_no_data_json() -> Value {
|
pub fn full_no_data_json() -> Value {
|
||||||
|
@ -61,7 +63,7 @@ pub fn full_json_data() -> Event {
|
||||||
let (bool_ext_name, bool_ext_value) = bool_extension();
|
let (bool_ext_name, bool_ext_value) = bool_extension();
|
||||||
let (int_ext_name, int_ext_value) = int_extension();
|
let (int_ext_name, int_ext_value) = int_extension();
|
||||||
|
|
||||||
EventBuilder::v03()
|
EventBuilderV03::new()
|
||||||
.id(id())
|
.id(id())
|
||||||
.source(Url::parse(source().as_ref()).unwrap())
|
.source(Url::parse(source().as_ref()).unwrap())
|
||||||
.ty(ty())
|
.ty(ty())
|
||||||
|
@ -76,6 +78,7 @@ pub fn full_json_data() -> Event {
|
||||||
json_data(),
|
json_data(),
|
||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full_json_data_json() -> Value {
|
pub fn full_json_data_json() -> Value {
|
||||||
|
@ -126,7 +129,7 @@ pub fn full_xml_string_data() -> Event {
|
||||||
let (bool_ext_name, bool_ext_value) = bool_extension();
|
let (bool_ext_name, bool_ext_value) = bool_extension();
|
||||||
let (int_ext_name, int_ext_value) = int_extension();
|
let (int_ext_name, int_ext_value) = int_extension();
|
||||||
|
|
||||||
EventBuilder::v03()
|
EventBuilderV03::new()
|
||||||
.id(id())
|
.id(id())
|
||||||
.source(Url::parse(source().as_ref()).unwrap())
|
.source(Url::parse(source().as_ref()).unwrap())
|
||||||
.ty(ty())
|
.ty(ty())
|
||||||
|
@ -137,6 +140,7 @@ pub fn full_xml_string_data() -> Event {
|
||||||
.extension(&int_ext_name, int_ext_value)
|
.extension(&int_ext_name, int_ext_value)
|
||||||
.data(xml_datacontenttype(), xml_data())
|
.data(xml_datacontenttype(), xml_data())
|
||||||
.build()
|
.build()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full_xml_binary_data() -> Event {
|
pub fn full_xml_binary_data() -> Event {
|
||||||
|
@ -144,7 +148,7 @@ pub fn full_xml_binary_data() -> Event {
|
||||||
let (bool_ext_name, bool_ext_value) = bool_extension();
|
let (bool_ext_name, bool_ext_value) = bool_extension();
|
||||||
let (int_ext_name, int_ext_value) = int_extension();
|
let (int_ext_name, int_ext_value) = int_extension();
|
||||||
|
|
||||||
EventBuilder::v03()
|
EventBuilderV03::new()
|
||||||
.id(id())
|
.id(id())
|
||||||
.source(Url::parse(source().as_ref()).unwrap())
|
.source(Url::parse(source().as_ref()).unwrap())
|
||||||
.ty(ty())
|
.ty(ty())
|
||||||
|
@ -155,6 +159,7 @@ pub fn full_xml_binary_data() -> Event {
|
||||||
.extension(&int_ext_name, int_ext_value)
|
.extension(&int_ext_name, int_ext_value)
|
||||||
.data(xml_datacontenttype(), Vec::from(xml_data()))
|
.data(xml_datacontenttype(), Vec::from(xml_data()))
|
||||||
.build()
|
.build()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full_xml_string_data_json() -> Value {
|
pub fn full_xml_string_data_json() -> Value {
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use cloudevents::{Event, EventBuilder};
|
use cloudevents::{Event, EventBuilder, EventBuilderV10};
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub fn minimal() -> Event {
|
pub fn minimal() -> Event {
|
||||||
EventBuilder::v10()
|
EventBuilderV10::new()
|
||||||
.id(id())
|
.id(id())
|
||||||
.source(Url::parse(source().as_ref()).unwrap())
|
.source(Url::parse(source().as_ref()).unwrap())
|
||||||
.ty(ty())
|
.ty(ty())
|
||||||
.build()
|
.build()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn minimal_json() -> Value {
|
pub fn minimal_json() -> Value {
|
||||||
|
@ -25,7 +26,7 @@ pub fn full_no_data() -> Event {
|
||||||
let (bool_ext_name, bool_ext_value) = bool_extension();
|
let (bool_ext_name, bool_ext_value) = bool_extension();
|
||||||
let (int_ext_name, int_ext_value) = int_extension();
|
let (int_ext_name, int_ext_value) = int_extension();
|
||||||
|
|
||||||
EventBuilder::v10()
|
EventBuilderV10::new()
|
||||||
.id(id())
|
.id(id())
|
||||||
.source(Url::parse(source().as_ref()).unwrap())
|
.source(Url::parse(source().as_ref()).unwrap())
|
||||||
.ty(ty())
|
.ty(ty())
|
||||||
|
@ -35,6 +36,7 @@ pub fn full_no_data() -> Event {
|
||||||
.extension(&bool_ext_name, bool_ext_value)
|
.extension(&bool_ext_name, bool_ext_value)
|
||||||
.extension(&int_ext_name, int_ext_value)
|
.extension(&int_ext_name, int_ext_value)
|
||||||
.build()
|
.build()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full_no_data_json() -> Value {
|
pub fn full_no_data_json() -> Value {
|
||||||
|
@ -60,7 +62,7 @@ pub fn full_json_data() -> Event {
|
||||||
let (bool_ext_name, bool_ext_value) = bool_extension();
|
let (bool_ext_name, bool_ext_value) = bool_extension();
|
||||||
let (int_ext_name, int_ext_value) = int_extension();
|
let (int_ext_name, int_ext_value) = int_extension();
|
||||||
|
|
||||||
EventBuilder::v10()
|
EventBuilderV10::new()
|
||||||
.id(id())
|
.id(id())
|
||||||
.source(Url::parse(source().as_ref()).unwrap())
|
.source(Url::parse(source().as_ref()).unwrap())
|
||||||
.ty(ty())
|
.ty(ty())
|
||||||
|
@ -75,6 +77,7 @@ pub fn full_json_data() -> Event {
|
||||||
json_data(),
|
json_data(),
|
||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full_json_data_json() -> Value {
|
pub fn full_json_data_json() -> Value {
|
||||||
|
@ -124,7 +127,7 @@ pub fn full_xml_string_data() -> Event {
|
||||||
let (bool_ext_name, bool_ext_value) = bool_extension();
|
let (bool_ext_name, bool_ext_value) = bool_extension();
|
||||||
let (int_ext_name, int_ext_value) = int_extension();
|
let (int_ext_name, int_ext_value) = int_extension();
|
||||||
|
|
||||||
EventBuilder::v10()
|
EventBuilderV10::new()
|
||||||
.id(id())
|
.id(id())
|
||||||
.source(Url::parse(source().as_ref()).unwrap())
|
.source(Url::parse(source().as_ref()).unwrap())
|
||||||
.ty(ty())
|
.ty(ty())
|
||||||
|
@ -135,6 +138,7 @@ pub fn full_xml_string_data() -> Event {
|
||||||
.extension(&int_ext_name, int_ext_value)
|
.extension(&int_ext_name, int_ext_value)
|
||||||
.data(xml_datacontenttype(), xml_data())
|
.data(xml_datacontenttype(), xml_data())
|
||||||
.build()
|
.build()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full_xml_binary_data() -> Event {
|
pub fn full_xml_binary_data() -> Event {
|
||||||
|
@ -142,7 +146,7 @@ pub fn full_xml_binary_data() -> Event {
|
||||||
let (bool_ext_name, bool_ext_value) = bool_extension();
|
let (bool_ext_name, bool_ext_value) = bool_extension();
|
||||||
let (int_ext_name, int_ext_value) = int_extension();
|
let (int_ext_name, int_ext_value) = int_extension();
|
||||||
|
|
||||||
EventBuilder::v10()
|
EventBuilderV10::new()
|
||||||
.id(id())
|
.id(id())
|
||||||
.source(Url::parse(source().as_ref()).unwrap())
|
.source(Url::parse(source().as_ref()).unwrap())
|
||||||
.ty(ty())
|
.ty(ty())
|
||||||
|
@ -153,6 +157,7 @@ pub fn full_xml_binary_data() -> Event {
|
||||||
.extension(&int_ext_name, int_ext_value)
|
.extension(&int_ext_name, int_ext_value)
|
||||||
.data(xml_datacontenttype(), Vec::from(xml_data()))
|
.data(xml_datacontenttype(), Vec::from(xml_data()))
|
||||||
.build()
|
.build()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full_xml_string_data_json() -> Value {
|
pub fn full_xml_string_data_json() -> Value {
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
macro_rules! assert_match_pattern (
|
||||||
|
($e:expr, $p:pat) => (
|
||||||
|
match $e {
|
||||||
|
$p => (),
|
||||||
|
_ => panic!(r#"assertion failed (value doesn't match pattern):
|
||||||
|
value: `{:?}`,
|
||||||
|
pattern: `{}`"#, $e, stringify!($p))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
|
@ -1,17 +1,18 @@
|
||||||
mod test_data;
|
mod test_data;
|
||||||
use cloudevents::event::{EventBuilderV03, EventBuilderV10};
|
use cloudevents::event::{EventBuilderV03, EventBuilderV10};
|
||||||
|
use cloudevents::EventBuilder;
|
||||||
use test_data::*;
|
use test_data::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn v10_to_v03() {
|
fn v10_to_v03() {
|
||||||
let in_event = v10::full_json_data();
|
let in_event = v10::full_json_data();
|
||||||
let out_event = EventBuilderV03::from(in_event).build();
|
let out_event = EventBuilderV03::from(in_event).build().unwrap();
|
||||||
assert_eq!(v03::full_json_data(), out_event)
|
assert_eq!(v03::full_json_data(), out_event)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn v03_to_v10() {
|
fn v03_to_v10() {
|
||||||
let in_event = v03::full_json_data();
|
let in_event = v03::full_json_data();
|
||||||
let out_event = EventBuilderV10::from(in_event).build();
|
let out_event = EventBuilderV10::from(in_event).build().unwrap();
|
||||||
assert_eq!(v10::full_json_data(), out_event)
|
assert_eq!(v10::full_json_data(), out_event)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue