Skip to main content

bulk_client/common/
tif.rs

1use std::str::FromStr;
2use eyre::bail;
3use serde::{de, Deserialize, Deserializer, Serialize};
4use serde::de::Error;
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!(
34                "unknown time-in-force '{s}'\n  → expected GTC, IOC, ALO"
35            ),
36        }
37    }
38}
39
40
41impl Default for TimeInForce {
42    fn default() -> TimeInForce {
43        TimeInForce::GTC
44    }
45}
46
47impl Serialize for TimeInForce {
48    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
49        if s.is_human_readable() {
50            s.serialize_str(match self {
51                TimeInForce::GTC => "GTC",
52                TimeInForce::IOC => "IOC",
53                TimeInForce::ALO => "ALO",
54            })
55        } else {
56            s.serialize_u32(*self as u32)
57        }
58    }
59}
60
61impl<'de> Deserialize<'de> for TimeInForce {
62    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
63        if d.is_human_readable() {
64            let s = String::deserialize(d)?;
65            match s.as_str() {
66                "GTC" | "gtc" => Ok(TimeInForce::GTC),
67                "IOC" | "ioc" => Ok(TimeInForce::IOC),
68                "ALO" | "alo" | "postOnly" => Ok(TimeInForce::ALO),
69                _ => Err(de::Error::unknown_variant(&s, &["GTC", "IOC", "ALO"])),
70            }
71        } else {
72            let v = u32::deserialize(d)? as u8;
73            Self::try_from(v).map_err(|_| {
74                D::Error::invalid_value(serde::de::Unexpected::Unsigned(v as u64), &"0..=2")
75            })
76        }
77    }
78}
79