use std::time::SystemTime;
use azure_iot_operations_mqtt::aio::cloud_event::{
CloudEventFields, DEFAULT_CLOUD_EVENT_SPEC_VERSION,
};
use chrono::{DateTime, SecondsFormat, Utc};
use uuid::Uuid;
#[derive(Builder, Clone, Debug)]
#[builder(setter(into), build_fn(validate = "Self::validate"))]
pub struct CloudEvent {
source: String,
#[builder(default = "DEFAULT_CLOUD_EVENT_SPEC_VERSION.to_string()")]
pub spec_version: String,
#[builder(default = "self.custom_default_event_type()")]
event_type: String,
#[builder(default = "None")]
data_schema: Option<String>,
#[builder(default = "Uuid::new_v4().to_string()")]
id: String,
#[builder(default = "Some(DateTime::<Utc>::from(SystemTime::now()))")]
time: Option<DateTime<Utc>>,
#[builder(default = "CloudEventSubject::PublishTopic")]
subject: CloudEventSubject,
#[builder(private)]
_default_event_type: String,
}
#[derive(Clone, Debug)]
pub enum CloudEventSubject {
PublishTopic,
Custom(String),
None,
}
impl CloudEventBuilder {
pub fn new(default_event_type: String) -> Self {
CloudEventBuilder {
_default_event_type: Some(default_event_type),
..Default::default()
}
}
fn custom_default_event_type(&self) -> String {
self._default_event_type.clone().expect("This CloudEventBuilder must be initialized with a default event type or one must be set on the builder")
}
fn validate(&self) -> Result<(), String> {
let mut spec_version = DEFAULT_CLOUD_EVENT_SPEC_VERSION.to_string();
if let Some(sv) = &self.spec_version {
CloudEventFields::SpecVersion.validate(sv, &spec_version)?;
spec_version.clone_from(sv);
}
if let Some(source) = &self.source {
CloudEventFields::Source.validate(source, &spec_version)?;
}
if let Some(event_type) = &self.event_type {
CloudEventFields::EventType.validate(event_type, &spec_version)?;
}
if let Some(Some(data_schema)) = &self.data_schema {
CloudEventFields::DataSchema.validate(data_schema, &spec_version)?;
}
if let Some(id) = &self.id {
CloudEventFields::Id.validate(id, &spec_version)?;
}
if let Some(CloudEventSubject::Custom(subject)) = &self.subject {
CloudEventFields::Subject.validate(subject, &spec_version)?;
}
Ok(())
}
}
impl CloudEvent {
#[must_use]
pub fn into_headers(self, publish_topic: &str) -> Vec<(String, String)> {
let mut headers = vec![
(CloudEventFields::Id.to_string(), self.id),
(CloudEventFields::Source.to_string(), self.source),
(CloudEventFields::SpecVersion.to_string(), self.spec_version),
(CloudEventFields::EventType.to_string(), self.event_type),
];
match self.subject {
CloudEventSubject::Custom(subject) => {
headers.push((CloudEventFields::Subject.to_string(), subject));
}
CloudEventSubject::PublishTopic => {
headers.push((
CloudEventFields::Subject.to_string(),
publish_topic.to_string(),
));
}
CloudEventSubject::None => {}
}
if let Some(time) = self.time {
headers.push((
CloudEventFields::Time.to_string(),
time.to_rfc3339_opts(SecondsFormat::Secs, true),
));
}
if let Some(data_schema) = self.data_schema {
headers.push((CloudEventFields::DataSchema.to_string(), data_schema));
}
headers
}
}