use serde::{Deserialize, Serialize};
use crate::sse::EventStreamRequest;
use crate::types::wire::wire_enum;
wire_enum! {
pub enum CorporateActionRegion {
All => "all",
Us => "us",
NonUs => "non_us",
}
}
wire_enum! {
pub enum CorporateActionEventType {
CashDividend => "cash_dividend_corporateaction_event",
CashMerger => "cash_merger_corporateaction_event",
EquityPartialCall => "equity_partial_call_corporateaction_event",
ForwardSplit => "forward_split_corporateaction_event",
NameChange => "name_change_corporateaction_event",
Redemption => "redemption_corporateaction_event",
Reorganization => "reorganization_corporateaction_event",
ReverseSplit => "reverse_split_corporateaction_event",
RightsDistribution => "rights_distribution_corporateaction_event",
SpinOff => "spin_off_corporateaction_event",
StockAndCashMerger => "stock_and_cash_merger_corporateaction_event",
StockDividend => "stock_dividend_corporateaction_event",
StockMerger => "stock_merger_corporateaction_event",
UnitSplit => "unit_split_corporateaction_event",
WorthlessRemoval => "worthless_removal_corporateaction_event",
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct CorporateActionEventsRequest {
#[serde(flatten)]
pub window: EventStreamRequest,
#[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
pub types: Option<Vec<CorporateActionEventType>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub region: Option<CorporateActionRegion>,
}
impl CorporateActionEventsRequest {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn window(mut self, window: EventStreamRequest) -> Self {
self.window = window;
self
}
#[must_use]
pub fn types(mut self, types: Vec<CorporateActionEventType>) -> Self {
self.types = Some(types);
self
}
#[must_use]
pub fn region(mut self, region: CorporateActionRegion) -> Self {
self.region = Some(region);
self
}
pub(crate) fn query(&self) -> Vec<(&'static str, String)> {
let mut query = self.window.query();
if let Some(types) = &self.types {
query.push((
"type",
types
.iter()
.map(CorporateActionEventType::as_str)
.collect::<Vec<_>>()
.join(","),
));
}
if let Some(region) = &self.region {
query.push(("region", region.as_str().to_owned()));
}
query
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn types_render_as_one_comma_separated_parameter() {
let request = CorporateActionEventsRequest::new()
.types(vec![
CorporateActionEventType::CashDividend,
CorporateActionEventType::StockMerger,
])
.region(CorporateActionRegion::Us);
assert_eq!(
request.query(),
vec![
(
"type",
"cash_dividend_corporateaction_event,stock_merger_corporateaction_event"
.to_owned()
),
("region", "us".to_owned()),
]
);
}
#[test]
fn the_event_types_are_not_the_polled_routes_types() {
assert_eq!(
CorporateActionEventType::CashDividend.as_str(),
"cash_dividend_corporateaction_event"
);
assert_eq!(
crate::data::CorporateActionsType::CashDividend.as_str(),
"cash_dividend"
);
}
#[test]
fn an_empty_filter_sends_nothing() {
assert!(CorporateActionEventsRequest::new().query().is_empty());
}
}