|
|
@@ -70,7 +70,7 @@ mod try_from_u8 { |
|
|
|
} |
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Debug, Clone)] |
|
|
|
pub struct Trade { |
|
|
|
pub struct Serde32BytesTrade { |
|
|
|
pub time: u64, |
|
|
|
#[serde(with = "try_from_u8")] |
|
|
|
pub exch: Exchange, |
|
|
@@ -183,6 +183,11 @@ impl<'a> PackedTradeData<'a> { |
|
|
|
lexical::parse(&self.0[Self::AMOUNT_OFFSET..(Self::AMOUNT_OFFSET + 8)]) |
|
|
|
} |
|
|
|
|
|
|
|
/// `server_time` is stored in milliseconds, while `time` is nanoseconds. |
|
|
|
/// this is what you need to multiply the stored `server_time` data by to |
|
|
|
/// get it back to nanoseconds. |
|
|
|
const SERVER_TIME_DOWNSCALE_FACTOR: u64 = 1_000_000; |
|
|
|
|
|
|
|
#[inline] |
|
|
|
pub fn server_time(&self) -> Result<Option<u64>, ParseError> { |
|
|
|
let st: i32 = |
|
|
@@ -192,12 +197,21 @@ impl<'a> PackedTradeData<'a> { |
|
|
|
std::str::from_utf8(&self.0[Self::SERVER_TIME_OFFSET..(Self::SERVER_TIME_OFFSET + 4)]).unwrap_or("uft8 error") |
|
|
|
))) |
|
|
|
})?; |
|
|
|
|
|
|
|
// while the `server_time` delta is stored as a signed integer, to be able to express a |
|
|
|
// delta in both directions relative to `time`, we can't just add a negative `i64` to a |
|
|
|
// `u64`, it doesn't work like that. this match either subtracts the absolute value of a |
|
|
|
// negative delta, or adds a positive delta, to get around this conundrum. |
|
|
|
// |
|
|
|
// `SERVER_TIME_DOWNSCALE_FACTOR` is used to rescale the delta to nanoseconds prior to its |
|
|
|
// being applied to `time`. |
|
|
|
|
|
|
|
match st { |
|
|
|
0 => Ok(None), |
|
|
|
|
|
|
|
x @ std::i32::MIN .. 0 => Ok(Some(self.time()? - x.abs() as u64)), |
|
|
|
x @ std::i32::MIN .. 0 => Ok(Some(self.time()? - (x.abs() as u64 * Self::SERVER_TIME_DOWNSCALE_FACTOR))), |
|
|
|
|
|
|
|
x @ 1 ..= std::i32::MAX => Ok(Some(self.time()? + x as u64)), |
|
|
|
x @ 1 ..= std::i32::MAX => Ok(Some(self.time()? + (x as u64 * Self::SERVER_TIME_DOWNSCALE_FACTOR))), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@@ -216,37 +230,17 @@ mod tests { |
|
|
|
|
|
|
|
#[test] |
|
|
|
fn check_bincode_serialized_size() { |
|
|
|
let trade = Trade { |
|
|
|
let trade = Serde32BytesTrade { |
|
|
|
time: 1586996977191449698, |
|
|
|
exch: e!(bmex), |
|
|
|
ticker: t!(btc-usd), |
|
|
|
price: 1.234, |
|
|
|
amount: 4.567, |
|
|
|
side: None, |
|
|
|
//server_time: NonZeroU64::new(1586996977191449698 + 1_000_000), |
|
|
|
server_time: NonZeroI32::new(1_000_000), |
|
|
|
//server_time: Some(1586996977191449698 + 1_000_000), |
|
|
|
}; |
|
|
|
|
|
|
|
/* |
|
|
|
let packed = PackedTrade { |
|
|
|
time: trade.time, |
|
|
|
exch: u8::from(trade.exch), |
|
|
|
base: u8::from(trade.ticker.base), |
|
|
|
quote: u8::from(trade.ticker.quote), |
|
|
|
amount: trade.amount, |
|
|
|
price: trade.price, |
|
|
|
//side: trade.side.and_then(|s| NonZeroU8::new(u8::from(s))), |
|
|
|
//server_time: NonZeroI32::new(1_000_000), |
|
|
|
side: trade.side.map(|s| u8::from(s)).unwrap_or(0), |
|
|
|
server_time: 1_000_000, |
|
|
|
|
|
|
|
}; |
|
|
|
*/ |
|
|
|
|
|
|
|
assert_eq!(size_of::<Trade>(), 32); |
|
|
|
|
|
|
|
//assert_eq!(serde_json::to_string(&trade).unwrap().len(), 32); |
|
|
|
assert_eq!(size_of::<Serde32BytesTrade>(), 32); |
|
|
|
assert_eq!(bincode::serialized_size(&trade).unwrap(), 32); |
|
|
|
} |
|
|
|
|
|
|
|