bulk_client/common/
tif.rs1use eyre::bail;
2use serde::de::Error;
3use serde::{de, Deserialize, Deserializer, Serialize};
4use std::str::FromStr;
5
6#[repr(u32)]
7#[derive(Debug, PartialEq, Eq, Clone, Copy)]
8pub enum TimeInForce {
9 GTC = 0,
10 IOC = 1,
11 ALO = 2,
12}
13
14impl From<u8> for TimeInForce {
15 fn from(value: u8) -> TimeInForce {
16 match value {
17 0 => TimeInForce::GTC,
18 1 => TimeInForce::IOC,
19 2 => TimeInForce::ALO,
20 _ => TimeInForce::GTC,
21 }
22 }
23}
24
25impl FromStr for TimeInForce {
26 type Err = eyre::Error;
27
28 fn from_str(s: &str) -> eyre::Result<Self> {
29 match s.to_uppercase().as_str() {
30 "GTC" => Ok(TimeInForce::GTC),
31 "IOC" => Ok(TimeInForce::IOC),
32 "ALO" | "POSTONLY" => Ok(TimeInForce::ALO),
33 _ => bail!("unknown time-in-force '{s}'\n → expected GTC, IOC, ALO"),
34 }
35 }
36}
37
38impl Default for TimeInForce {
39 fn default() -> TimeInForce {
40 TimeInForce::GTC
41 }
42}
43
44impl Serialize for TimeInForce {
45 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
46 if s.is_human_readable() {
47 s.serialize_str(match self {
48 TimeInForce::GTC => "GTC",
49 TimeInForce::IOC => "IOC",
50 TimeInForce::ALO => "ALO",
51 })
52 } else {
53 s.serialize_u32(*self as u32)
54 }
55 }
56}
57
58impl<'de> Deserialize<'de> for TimeInForce {
59 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
60 if d.is_human_readable() {
61 let s = String::deserialize(d)?;
62 match s.as_str() {
63 "GTC" | "gtc" => Ok(TimeInForce::GTC),
64 "IOC" | "ioc" => Ok(TimeInForce::IOC),
65 "ALO" | "alo" | "postOnly" => Ok(TimeInForce::ALO),
66 _ => Err(de::Error::unknown_variant(&s, &["GTC", "IOC", "ALO"])),
67 }
68 } else {
69 let v = u32::deserialize(d)? as u8;
70 Self::try_from(v).map_err(|_| {
71 D::Error::invalid_value(serde::de::Unexpected::Unsigned(v as u64), &"0..=2")
72 })
73 }
74 }
75}