use serde::{Deserialize, Serialize};
use std::fmt;
#[cfg(feature = "diesel")]
use std::io::Write;
#[cfg(feature = "diesel")]
use diesel::deserialize::{self, FromSql, FromSqlRow};
#[cfg(feature = "diesel")]
use diesel::prelude::*;
#[cfg(feature = "diesel")]
use diesel::serialize::{self, IsNull, Output, ToSql};
#[cfg(feature = "diesel")]
use diesel::{expression::AsExpression, sql_types::Text};
#[cfg(feature = "diesel")]
use diesel::mysql::{Mysql, MysqlValue};
use crate::protocol::webhook::WebhookEventType;
#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)]
#[cfg_attr(
feature = "diesel",
derive(diesel::expression::AsExpression, diesel::deserialize::FromSqlRow)
)]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[cfg_attr(test, derive(strum::EnumIter))]
pub enum EventType {
#[serde(rename = "booking")]
Booking,
#[serde(rename = "invoice")]
Invoice,
#[serde(rename = "itinerary")]
Itinerary,
#[serde(rename = "receipt")]
Receipt,
#[serde(rename = "transit_route.status.updated")]
TransitRouteStatusUpdated,
#[serde(rename = "transit_route.location.updated")]
TransitRouteLocationUpdated,
}
#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)]
#[cfg_attr(
feature = "diesel",
derive(diesel::expression::AsExpression, diesel::deserialize::FromSqlRow)
)]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[cfg_attr(test, derive(strum::EnumIter))]
pub enum InitialEventType {
#[serde(rename = "booking")]
Booking,
#[serde(rename = "invoice")]
Invoice,
#[serde(rename = "itinerary")]
Itinerary,
#[serde(rename = "receipt")]
Receipt,
}
#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)]
#[cfg_attr(
feature = "diesel",
derive(diesel::expression::AsExpression, diesel::deserialize::FromSqlRow)
)]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[cfg_attr(test, derive(strum::EnumIter))]
pub enum UpdateEventType {
#[serde(rename = "transit_route.status.updated")]
TransitRouteStatusUpdated,
#[serde(rename = "transit_route.location.updated")]
TransitRouteLocationUpdated,
}
impl From<InitialEventType> for EventType {
fn from(event: InitialEventType) -> Self {
match event {
InitialEventType::Booking => EventType::Booking,
InitialEventType::Invoice => EventType::Invoice,
InitialEventType::Itinerary => EventType::Itinerary,
InitialEventType::Receipt => EventType::Receipt,
}
}
}
impl From<UpdateEventType> for EventType {
fn from(event: UpdateEventType) -> Self {
match event {
UpdateEventType::TransitRouteStatusUpdated => EventType::TransitRouteStatusUpdated,
UpdateEventType::TransitRouteLocationUpdated => EventType::TransitRouteLocationUpdated,
}
}
}
impl fmt::Display for EventType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let serialized = serde_json::to_string(self).unwrap().replace("\"", "");
write!(f, "{}", serialized)
}
}
impl fmt::Display for InitialEventType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let serialized = serde_json::to_string(self).unwrap().replace("\"", "");
write!(f, "{}", serialized)
}
}
impl fmt::Display for UpdateEventType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let serialized = serde_json::to_string(self).unwrap().replace("\"", "");
write!(f, "{}", serialized)
}
}
impl EventType {
pub fn is_update_event(&self) -> bool {
matches!(
self,
EventType::TransitRouteStatusUpdated | EventType::TransitRouteLocationUpdated
)
}
pub fn is_initial_event(&self) -> bool {
matches!(self, EventType::Itinerary | EventType::Receipt)
}
pub fn update_event_type(&self) -> Option<UpdateEventType> {
match self {
EventType::TransitRouteStatusUpdated => Some(UpdateEventType::TransitRouteStatusUpdated),
EventType::TransitRouteLocationUpdated => Some(UpdateEventType::TransitRouteLocationUpdated),
_ => None,
}
}
pub fn initial_event_type(&self) -> Option<InitialEventType> {
match self {
EventType::Itinerary => Some(InitialEventType::Itinerary),
EventType::Receipt => Some(InitialEventType::Receipt),
_ => None,
}
}
}
impl From<EventType> for WebhookEventType {
fn from(event: EventType) -> Self {
match event {
EventType::Booking => WebhookEventType::Booking,
EventType::Invoice => WebhookEventType::Invoice,
EventType::Itinerary => WebhookEventType::Itinerary,
EventType::Receipt => WebhookEventType::Receipt,
EventType::TransitRouteStatusUpdated => WebhookEventType::TransitRouteStatusUpdated,
EventType::TransitRouteLocationUpdated => WebhookEventType::TransitRouteLocationUpdated,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use strum::IntoEnumIterator;
#[test]
fn test_all_event_types_serialize_to_webhook_event_type() {
for event_type in EventType::iter() {
let serialized = serde_json::to_string(&event_type).unwrap();
let deserialized_result: Result<WebhookEventType, _> = serde_json::from_str(&serialized);
assert!(
deserialized_result.is_ok(),
"EventType::{:?} failed to deserialize into WebhookEventType",
event_type
);
}
}
}