use crate::app::slr;
use crate::app::TsrMessageRef;
use std::collections::BTreeMap;
use std::time::SystemTime;
#[derive(Clone, Debug, PartialEq)]
pub enum FixFieldValue {
Int(i64),
Float(f64),
Char(char),
String(String),
Data(Vec<u8>),
Group(Vec<BTreeMap<i64, FixFieldValue>>),
}
impl From<i64> for FixFieldValue {
fn from(v: i64) -> Self {
FixFieldValue::Int(v)
}
}
impl From<String> for FixFieldValue {
fn from(v: String) -> Self {
FixFieldValue::String(v)
}
}
impl From<f64> for FixFieldValue {
fn from(v: f64) -> Self {
FixFieldValue::Float(v)
}
}
impl From<(u8, u16)> for FixFieldValue {
fn from(v: (u8, u16)) -> Self {
FixFieldValue::Int(((v.0 as i64) << 16) + (v.1 as i64))
}
}
impl From<char> for FixFieldValue {
fn from(v: char) -> Self {
FixFieldValue::Char(v)
}
}
impl From<usize> for FixFieldValue {
fn from(v: usize) -> Self {
FixFieldValue::Int(v as i64)
}
}
impl From<Vec<u8>> for FixFieldValue {
fn from(v: Vec<u8>) -> Self {
FixFieldValue::Data(v)
}
}
impl From<bool> for FixFieldValue {
fn from(v: bool) -> Self {
FixFieldValue::Char(if v { 't' } else { 'f' })
}
}
impl From<u8> for FixFieldValue {
fn from(v: u8) -> Self {
FixFieldValue::Int(v.into())
}
}
impl From<SystemTime> for FixFieldValue {
fn from(v: SystemTime) -> Self {
FixFieldValue::Int(v.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as i64)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Field {
tag: i64,
value: FixFieldValue,
}
impl Field {
pub fn new(tag: u32, value: FixFieldValue) -> Self {
Self { tag: tag as i64, value }
}
pub fn tag(&self) -> i64 {
self.tag
}
pub fn value(&self) -> &FixFieldValue {
&self.value
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Message {
pub fields: BTreeMap<i64, FixFieldValue>,
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct PushyMessage {
fields: Vec<(u32, FixFieldValue)>,
}
impl TsrMessageRef for PushyMessage {
fn set_field(&mut self, msg_type: u32, val: slr::FixFieldValue) {
PushyMessage::add_field(self, msg_type, val)
}
fn get_field(&self, msg_type: u32) -> Option<&slr::FixFieldValue> {
PushyMessage::get_field(self, msg_type)
}
}
impl PushyMessage {
pub fn new() -> Self {
Self {
fields: Vec::new(),
}
}
pub fn add_field<K: Into<u32>>(&mut self, tag: K, value: slr::FixFieldValue) {
self.fields.push((tag.into(), value));
}
pub fn add_str<K: Into<u32>, S: Into<String>>(&mut self, tag: K, value: S) {
self.add_field(tag, slr::FixFieldValue::String(value.into()))
}
pub fn add_int<K: Into<u32>>(&mut self, tag: K, value: i64) {
self.add_field(tag, slr::FixFieldValue::Int(value))
}
pub fn get_field<K: Into<u32>>(&self, tag: K) -> Option<&slr::FixFieldValue> {
let tag = tag.into();
let index = self.fields.iter().position(|(t, _)| *t == tag);
index.map(|i| &self.fields[i].1)
}
pub fn msg_type(&self) -> Option<&str> {
match self.get_field(35u32) {
Some(FixFieldValue::String(s)) => Some(s.as_str()),
_ => None,
}
}
pub fn seq_num(&self) -> Option<u64> {
match self.get_field(34u32) {
Some(FixFieldValue::Int(n)) => Some(*n as u64),
_ => None,
}
}
pub fn test_indicator(&self) -> Option<bool> {
match self.get_field(464u32) {
Some(FixFieldValue::Char('Y')) => Some(true),
Some(FixFieldValue::Char('N')) => Some(false),
_ => Some(false),
}
}
}
impl TsrMessageRef for Message {
fn get_field(&self, msg_type: u32) -> Option<&slr::FixFieldValue> {
self.fields.get(&(msg_type as i64))
}
fn set_field(&mut self, msg_type: u32, val: slr::FixFieldValue) {
self.fields.insert(msg_type as i64, val);
}
}
impl<'a> Iterator for &'a Message {
type Item = slr::FixFieldValue;
fn next(&mut self) -> Option<Self::Item> {
None
}
}
impl Message {
pub fn new() -> Self {
Message {
fields: BTreeMap::new(),
}
}
pub fn add_field<K: Into<i64>>(&mut self, tag: K, value: slr::FixFieldValue) {
self.fields.insert(tag.into(), value);
}
pub fn add_str<K: Into<i64>, S: Into<String>>(&mut self, tag: K, value: S) {
self.add_field(tag, slr::FixFieldValue::String(value.into()))
}
pub fn add_int<K: Into<i64>>(&mut self, tag: K, value: i64) {
self.add_field(tag, slr::FixFieldValue::Int(value))
}
pub fn get_field<K: Into<i64>>(&self, tag: K) -> Option<&slr::FixFieldValue> {
self.fields.get(&tag.into())
}
pub fn msg_type(&self) -> Option<&str> {
match self.fields.get(&35) {
Some(FixFieldValue::String(s)) => Some(s.as_str()),
_ => None,
}
}
pub fn seq_num(&self) -> Option<u64> {
match self.fields.get(&34) {
Some(FixFieldValue::Int(n)) => Some(*n as u64),
_ => None,
}
}
pub fn test_indicator(&self) -> Option<bool> {
match self.fields.get(&464) {
Some(FixFieldValue::Char('Y')) => Some(true),
Some(FixFieldValue::Char('N')) => Some(false),
_ => Some(false),
}
}
}