use std::str;
use serde::{Deserialize, Serialize};
mod common;
#[cfg(test)]
use common::decoders;
use common::encoders;
#[cfg(feature = "sync")]
mod sync;
#[cfg(feature = "async")]
mod r#async;
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct WshMetadata {
pub data_json: String,
}
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct WshEventData {
pub data_json: String,
}
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[derive(Debug, Default, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct AutoFill {
pub competitors: bool,
pub portfolio: bool,
pub watchlist: bool,
}
impl AutoFill {
pub fn is_specified(&self) -> bool {
self.competitors || self.portfolio || self.watchlist
}
}
#[cfg(feature = "sync")]
pub mod blocking {
pub(crate) use super::sync::{wsh_event_data_by_contract, wsh_event_data_by_filter, wsh_metadata};
}
#[cfg(feature = "async")]
pub(crate) use r#async::{wsh_event_data_by_contract, wsh_event_data_by_filter, wsh_metadata};
#[cfg(test)]
mod common_tests {
use super::*;
use crate::messages::ResponseMessage;
#[test]
fn test_autofill_is_specified() {
assert!(!AutoFill::default().is_specified());
assert!(AutoFill {
competitors: true,
portfolio: false,
watchlist: false,
}
.is_specified());
assert!(AutoFill {
competitors: false,
portfolio: true,
watchlist: false,
}
.is_specified());
assert!(AutoFill {
competitors: false,
portfolio: false,
watchlist: true,
}
.is_specified());
}
#[test]
fn test_autofill_combinations() {
let combinations = vec![
(false, false, false, false),
(true, false, false, true),
(false, true, false, true),
(false, false, true, true),
(true, true, false, true),
(true, false, true, true),
(false, true, true, true),
(true, true, true, true),
];
for (competitors, portfolio, watchlist, expected) in combinations {
let autofill = AutoFill {
competitors,
portfolio,
watchlist,
};
assert_eq!(
autofill.is_specified(),
expected,
"Failed for combination: competitors={}, portfolio={}, watchlist={}",
competitors,
portfolio,
watchlist
);
}
}
#[test]
fn test_decode_wsh_metadata() {
use super::decoders::decode_wsh_metadata;
let message = ResponseMessage::from("104\09000\0{\"test\":\"data\"}\0");
let result = decode_wsh_metadata(message);
assert!(result.is_ok(), "failed to decode wsh metadata: {}", result.err().unwrap());
assert_eq!(result.unwrap().data_json, "{\"test\":\"data\"}");
}
#[test]
fn test_decode_wsh_event_data() {
use super::decoders::decode_wsh_event_data;
let message = ResponseMessage::from("105\09000\0{\"test\":\"data\"}\0");
let result = decode_wsh_event_data(message);
assert!(result.is_ok(), "failed to decode wsh event data: {}", result.err().unwrap());
assert_eq!(result.unwrap().data_json, "{\"test\":\"data\"}");
}
#[test]
fn test_encode_request_wsh_metadata() {
use super::encoders::encode_request_wsh_metadata;
let result = encode_request_wsh_metadata(9000);
assert!(result.is_ok());
assert_eq!(result.unwrap().encode_simple(), "100|9000|");
}
#[test]
fn test_encode_cancel_wsh_metadata() {
use super::encoders::encode_cancel_wsh_metadata;
let result = encode_cancel_wsh_metadata(9000);
assert!(result.is_ok());
assert_eq!(result.unwrap().encode_simple(), "101|9000|");
}
#[test]
fn test_encode_request_wsh_event_data() {
use super::encoders::encode_request_wsh_event_data;
use crate::server_versions;
use time::macros::date;
let result = encode_request_wsh_event_data(server_versions::WSHE_CALENDAR, 9000, Some(12345), None, None, None, None, None);
assert!(result.is_ok());
assert_eq!(result.unwrap().encode_simple(), "102|9000|12345|");
let result = encode_request_wsh_event_data(
server_versions::WSH_EVENT_DATA_FILTERS_DATE,
9000,
Some(12345),
Some("filter"),
Some(date!(2024 - 01 - 01)),
Some(date!(2024 - 12 - 31)),
Some(100),
Some(AutoFill {
competitors: true,
portfolio: false,
watchlist: true,
}),
);
assert!(result.is_ok());
assert_eq!(result.unwrap().encode_simple(), "102|9000|12345|filter|1|0|1|20240101|20241231|100|");
}
#[test]
fn test_encode_cancel_wsh_event_data() {
use super::encoders::encode_cancel_wsh_event_data;
let result = encode_cancel_wsh_event_data(9000);
assert!(result.is_ok());
assert_eq!(result.unwrap().encode_simple(), "103|9000|");
}
#[test]
fn test_decode_wsh_metadata_empty_json() {
use super::decoders::decode_wsh_metadata;
let message = ResponseMessage::from("104\09000\0\0");
let result = decode_wsh_metadata(message);
assert!(result.is_ok(), "failed to decode empty wsh metadata: {}", result.err().unwrap());
assert_eq!(result.unwrap().data_json, "");
}
#[test]
fn test_decode_wsh_event_data_empty_json() {
use super::decoders::decode_wsh_event_data;
let message = ResponseMessage::from("105\09000\0\0");
let result = decode_wsh_event_data(message);
assert!(result.is_ok(), "failed to decode empty wsh event data: {}", result.err().unwrap());
assert_eq!(result.unwrap().data_json, "");
}
#[test]
fn test_decode_wsh_metadata_with_special_chars() {
use super::decoders::decode_wsh_metadata;
let message = ResponseMessage::from("104\09000\0{\"data\":\"test\\nwith\\tspecial\\rchars\"}\0");
let result = decode_wsh_metadata(message);
assert!(result.is_ok());
assert_eq!(result.unwrap().data_json, "{\"data\":\"test\\nwith\\tspecial\\rchars\"}");
}
#[test]
fn test_encode_request_wsh_event_data_edge_cases() {
use super::encoders::encode_request_wsh_event_data;
use crate::server_versions;
let result = encode_request_wsh_event_data(server_versions::WSH_EVENT_DATA_FILTERS, 9000, None, Some(""), None, None, None, None);
assert!(result.is_ok());
assert_eq!(result.unwrap().encode_simple(), "102|9000|||0|0|0|");
let result = encode_request_wsh_event_data(
server_versions::WSH_EVENT_DATA_FILTERS,
9001,
None,
Some("filter=\"test\" AND type='earnings'"),
None,
None,
None,
None,
);
assert!(result.is_ok());
assert_eq!(result.unwrap().encode_simple(), "102|9001||filter=\"test\" AND type='earnings'|0|0|0|");
let result = encode_request_wsh_event_data(
server_versions::WSH_EVENT_DATA_FILTERS_DATE,
9002,
Some(12345),
None,
None,
None,
Some(-10),
None,
);
assert!(result.is_ok());
assert_eq!(result.unwrap().encode_simple(), "102|9002|12345||0|0|0|||-10|");
}
}