use std::io;
use std::str;
use std::str::FromStr;
use std::vec::Vec;
use std::{f64, i32};
use bytes::Buf;
use bytes::BytesMut;
use memchr;
use rust_decimal::Decimal;
pub trait TwsWireEncoder {
fn push_slice(&mut self, extend: &[u8]);
#[inline(always)]
fn push_u8(&mut self, v: u8) {
self.push_slice(&[v]);
}
#[inline(always)]
fn push_string(&mut self, v: &str) {
self.push_slice(v.as_bytes());
self.push_u8(0);
}
#[inline(always)]
fn push_bool(&mut self, v: bool) {
if v {
self.push_string("1");
} else {
self.push_string("0");
}
}
#[inline(always)]
fn push_int(&mut self, v: i32) {
self.push_string(&v.to_string());
}
#[inline(always)]
fn push_long(&mut self, v: i64) {
self.push_string(&v.to_string());
}
#[inline(always)]
fn push_int_max(&mut self, v: i32) {
if v == i32::MAX {
self.push_u8(0);
} else {
self.push_int(v);
}
}
#[inline(always)]
fn push_double(&mut self, v: f64) {
self.push_string(&v.to_string());
}
#[inline(always)]
fn push_double_max(&mut self, v: f64) {
if v == f64::MAX {
self.push_u8(0);
} else {
self.push_double(v);
}
}
}
impl TwsWireEncoder for BytesMut {
#[inline(always)]
fn push_slice(&mut self, slice: &[u8]) {
self.extend_from_slice(slice);
}
}
impl TwsWireEncoder for Vec<u8> {
#[inline(always)]
fn push_slice(&mut self, slice: &[u8]) {
self.extend_from_slice(slice);
}
}
pub trait TwsWireDecoder {
fn split(&mut self) -> Result<BytesMut, io::Error>;
fn read_decimal(&mut self) -> Result<Decimal, io::Error> {
let str = self.read_string()?;
if str.is_empty() {
Ok(Decimal::new(0, 0))
} else {
Decimal::from_str(&str)
.map_err(|_| {
io::Error::new(io::ErrorKind::InvalidData, "cannot read decimal from stream")
})
}
}
fn read_int(&mut self) -> Result<i32, io::Error> {
let s = self.split()?;
let s = unsafe { str::from_utf8_unchecked(&s) };
if s.is_empty() {
Ok(0i32)
} else {
s.parse::<i32>().map_err(|_| {
io::Error::new(io::ErrorKind::InvalidData, "cannot read i32 from stream")
})
}
}
fn read_int_max(&mut self) -> Result<i32, io::Error> {
let s = self.split()?;
let s = unsafe { str::from_utf8_unchecked(&s) };
if s.is_empty() {
Ok(i32::MAX)
} else {
s.parse::<i32>().map_err(|_| {
io::Error::new(io::ErrorKind::InvalidData, "cannot read i32 from stream")
})
}
}
fn read_bool(&mut self) -> Result<bool, io::Error> {
let v = self.read_int()?;
if v > 0 {
Ok(true)
} else {
Ok(false)
}
}
fn read_bool_from_str(&mut self) -> Result<bool, io::Error> {
let s = self.split()?;
let s = unsafe { str::from_utf8_unchecked(&s) };
if s == "true" {
Ok(true)
} else {
Ok(false)
}
}
fn read_long(&mut self) -> Result<i64, io::Error> {
let s = self.split()?;
let s = unsafe { str::from_utf8_unchecked(&s) };
if s.is_empty() {
Ok(0i64)
} else {
s.parse::<i64>().map_err(|_| {
io::Error::new(io::ErrorKind::InvalidData, "cannot read i64 from stream")
})
}
}
fn read_double(&mut self) -> Result<f64, io::Error> {
let s = self.split()?;
let s = unsafe { str::from_utf8_unchecked(&s) };
if s.is_empty() {
Ok(0.0)
} else {
f64::from_str(s).map_err(|_| {
io::Error::new(io::ErrorKind::InvalidData, "cannot read f64 from stream")
})
}
}
fn read_double_max(&mut self) -> Result<f64, io::Error> {
let s = self.split()?;
let s = unsafe { str::from_utf8_unchecked(&s) };
if s.is_empty() {
Ok(f64::MAX)
} else {
f64::from_str(s).map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidData,
"cannot read f64 max from stream",
)
})
}
}
fn read_string(&mut self) -> Result<String, io::Error> {
let s = self.split()?;
str::from_utf8(&s)
.map_err(|_e| io::Error::new(io::ErrorKind::InvalidData, "utf8 error"))
.map(ToString::to_string)
}
}
impl TwsWireDecoder for BytesMut {
fn split(&mut self) -> Result<BytesMut, io::Error> {
let n = memchr::memchr(b'\0', self);
match n {
None => Err(io::Error::new(
io::ErrorKind::InvalidData,
"cannot find '\0'",
)),
Some(index) => {
let res = self.split_to(index);
if !self.is_empty() {
self.advance(1);
}; Ok(res)
}
}
}
}