|
| 1 | +//! Decoders for configuration messages. Proto-only; text framing surfaces as |
| 2 | +//! `Error::UnexpectedResponse` via `require_proto()`. |
| 3 | +
|
| 4 | +use prost::Message; |
| 5 | + |
| 6 | +use crate::config::{ApiConfig, ApiPrecautions, ApiSettings, Config, LockAndExit, MessageSetting, OrdersConfig, OrdersSmartRouting}; |
| 7 | +use crate::messages::{IncomingMessages, ResponseMessage}; |
| 8 | +use crate::proto; |
| 9 | +use crate::Error; |
| 10 | + |
| 11 | +/// Dispatch on the incoming message type and forward to the typed decoder. |
| 12 | +/// Routes `Error` frames into `Error::from` and any other variant into |
| 13 | +/// `Error::UnexpectedResponse`. |
| 14 | +pub(in crate::config) fn decode_config_message(message: &ResponseMessage) -> Result<Config, Error> { |
| 15 | + match message.message_type() { |
| 16 | + IncomingMessages::ConfigResponse => decode_config_proto(message.require_proto()?), |
| 17 | + IncomingMessages::Error => Err(Error::from(message)), |
| 18 | + _ => Err(Error::unexpected_response(message)), |
| 19 | + } |
| 20 | +} |
| 21 | + |
| 22 | +fn decode_config_proto(bytes: &[u8]) -> Result<Config, Error> { |
| 23 | + let p = proto::ConfigResponse::decode(bytes)?; |
| 24 | + Ok(Config { |
| 25 | + lock_and_exit: p.lock_and_exit.map(convert_lock_and_exit), |
| 26 | + messages: p.messages.into_iter().map(convert_message).collect(), |
| 27 | + api: p.api.map(convert_api), |
| 28 | + orders: p.orders.map(convert_orders), |
| 29 | + }) |
| 30 | +} |
| 31 | + |
| 32 | +fn convert_lock_and_exit(p: proto::LockAndExitConfig) -> LockAndExit { |
| 33 | + LockAndExit { |
| 34 | + auto_logoff_time: p.auto_logoff_time, |
| 35 | + auto_logoff_period: p.auto_logoff_period, |
| 36 | + auto_logoff_type: p.auto_logoff_type, |
| 37 | + } |
| 38 | +} |
| 39 | + |
| 40 | +fn convert_message(p: proto::MessageConfig) -> MessageSetting { |
| 41 | + MessageSetting { |
| 42 | + id: p.id, |
| 43 | + title: p.title, |
| 44 | + message: p.message, |
| 45 | + default_action: p.default_action, |
| 46 | + enabled: p.enabled, |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +fn convert_api(p: proto::ApiConfig) -> ApiConfig { |
| 51 | + ApiConfig { |
| 52 | + precautions: p.precautions.map(convert_precautions), |
| 53 | + settings: p.settings.map(convert_settings), |
| 54 | + } |
| 55 | +} |
| 56 | + |
| 57 | +fn convert_precautions(p: proto::ApiPrecautionsConfig) -> ApiPrecautions { |
| 58 | + ApiPrecautions { |
| 59 | + bypass_order_precautions: p.bypass_order_precautions, |
| 60 | + bypass_bond_warning: p.bypass_bond_warning, |
| 61 | + bypass_negative_yield_confirmation: p.bypass_negative_yield_confirmation, |
| 62 | + bypass_called_bond_warning: p.bypass_called_bond_warning, |
| 63 | + bypass_same_action_pair_trade_warning: p.bypass_same_action_pair_trade_warning, |
| 64 | + bypass_flagged_accounts_warning: p.bypass_flagged_accounts_warning, |
| 65 | + bypass_price_based_volatility_warning: p.bypass_price_based_volatility_warning, |
| 66 | + bypass_redirect_order_warning: p.bypass_redirect_order_warning, |
| 67 | + bypass_no_overfill_protection: p.bypass_no_overfill_protection, |
| 68 | + bypass_route_marketable_to_bbo: p.bypass_route_marketable_to_bbo, |
| 69 | + } |
| 70 | +} |
| 71 | + |
| 72 | +fn convert_settings(p: proto::ApiSettingsConfig) -> ApiSettings { |
| 73 | + ApiSettings { |
| 74 | + read_only_api: p.read_only_api, |
| 75 | + total_quantity_for_mutual_funds: p.total_quantity_for_mutual_funds, |
| 76 | + download_open_orders_on_connection: p.download_open_orders_on_connection, |
| 77 | + include_virtual_fx_positions: p.include_virtual_fx_positions, |
| 78 | + prepare_daily_pnl: p.prepare_daily_pn_l, |
| 79 | + send_status_updates_for_volatility_orders: p.send_status_updates_for_volatility_orders, |
| 80 | + encode_api_messages: p.encode_api_messages, |
| 81 | + socket_port: p.socket_port, |
| 82 | + use_negative_auto_range: p.use_negative_auto_range, |
| 83 | + create_api_message_log_file: p.create_api_message_log_file, |
| 84 | + include_market_data_in_log_file: p.include_market_data_in_log_file, |
| 85 | + expose_trading_schedule_to_api: p.expose_trading_schedule_to_api, |
| 86 | + split_insured_deposit_from_cash_balance: p.split_insured_deposit_from_cash_balance, |
| 87 | + send_zero_positions_for_today_only: p.send_zero_positions_for_today_only, |
| 88 | + let_api_account_requests_switch_subscription: p.let_api_account_requests_switch_subscription, |
| 89 | + use_account_groups_with_allocation_methods: p.use_account_groups_with_allocation_methods, |
| 90 | + logging_level: p.logging_level, |
| 91 | + master_client_id: p.master_client_id, |
| 92 | + bulk_data_timeout: p.bulk_data_timeout, |
| 93 | + component_exch_separator: p.component_exch_separator, |
| 94 | + show_forex_data_in_1_10_pips: p.show_forex_data_in1_10pips, |
| 95 | + allow_forex_trading_in_1_10_pips: p.allow_forex_trading_in1_10pips, |
| 96 | + round_account_values_to_nearest_whole_number: p.round_account_values_to_nearest_whole_number, |
| 97 | + send_market_data_in_lots_for_us_stocks: p.send_market_data_in_lots_for_us_stocks, |
| 98 | + show_advanced_order_reject_in_ui: p.show_advanced_order_reject_in_ui, |
| 99 | + reject_messages_above_max_rate: p.reject_messages_above_max_rate, |
| 100 | + maintain_connection_on_incorrect_fields: p.maintain_connection_on_incorrect_fields, |
| 101 | + compatibility_mode_nasdaq_stocks: p.compatibility_mode_nasdaq_stocks, |
| 102 | + send_instrument_timezone: p.send_instrument_timezone, |
| 103 | + send_forex_data_in_compatibility_mode: p.send_forex_data_in_compatibility_mode, |
| 104 | + maintain_and_resubmit_orders_on_reconnect: p.maintain_and_resubmit_orders_on_reconnect, |
| 105 | + historical_data_max_size: p.historical_data_max_size, |
| 106 | + auto_report_netting_event_contract_trades: p.auto_report_netting_event_contract_trades, |
| 107 | + option_exercise_request_type: p.option_exercise_request_type, |
| 108 | + allow_localhost_only: p.allow_localhost_only, |
| 109 | + trusted_ips: p.trusted_i_ps, |
| 110 | + } |
| 111 | +} |
| 112 | + |
| 113 | +fn convert_orders(p: proto::OrdersConfig) -> OrdersConfig { |
| 114 | + OrdersConfig { |
| 115 | + smart_routing: p.smart_routing.map(convert_smart_routing), |
| 116 | + } |
| 117 | +} |
| 118 | + |
| 119 | +fn convert_smart_routing(p: proto::OrdersSmartRoutingConfig) -> OrdersSmartRouting { |
| 120 | + OrdersSmartRouting { |
| 121 | + seek_price_improvement: p.seek_price_improvement, |
| 122 | + pre_open_reroute: p.pre_open_reroute, |
| 123 | + do_not_route_to_dark_pools: p.do_not_route_to_dark_pools, |
| 124 | + default_algorithm: p.default_algorithm, |
| 125 | + } |
| 126 | +} |
| 127 | + |
| 128 | +#[cfg(test)] |
| 129 | +#[path = "decoders_tests.rs"] |
| 130 | +mod tests; |
0 commit comments