rusty_feeder/exchange/upbit/data/
subscription.rs1use serde::Serialize;
6use smallvec::SmallVec;
7use smartstring::alias::String;
8
9mod smallvec_ser {
11 use serde::{Deserialize, Deserializer, Serialize, Serializer};
12 use smallvec::SmallVec;
13
14 pub fn serialize<S, T>(small_vec: &SmallVec<[T; 8]>, serializer: S) -> Result<S::Ok, S::Error>
16 where
17 S: Serializer,
18 T: Serialize,
19 {
20 small_vec.as_slice().serialize(serializer)
21 }
22
23 pub fn deserialize<'de, D, T>(deserializer: D) -> Result<SmallVec<[T; 8]>, D::Error>
25 where
26 D: Deserializer<'de>,
27 T: Deserialize<'de>,
28 {
29 let items = Vec::<T>::deserialize(deserializer)?;
30 Ok(SmallVec::from_vec(items))
31 }
32}
33
34#[derive(Debug, Clone, Serialize)]
36pub struct TradeSubscription {
37 pub ticket: String,
39
40 #[serde(rename = "type")]
42 pub data_type: String,
43
44 #[serde(with = "smallvec_ser")]
46 pub codes: SmallVec<[String; 8]>,
47
48 #[serde(skip_serializing_if = "Option::is_none")]
50 pub is_only_snapshot: Option<bool>,
51
52 #[serde(skip_serializing_if = "Option::is_none")]
54 pub is_only_realtime: Option<bool>,
55}
56
57#[derive(Debug, Clone, Serialize)]
59pub struct OrderbookSubscription {
60 pub ticket: String,
62
63 #[serde(rename = "type")]
65 pub data_type: String,
66
67 pub codes: SmallVec<[String; 8]>,
69
70 #[serde(skip_serializing_if = "Option::is_none")]
72 pub level: Option<f64>,
73
74 #[serde(skip_serializing_if = "Option::is_none")]
76 pub is_only_snapshot: Option<bool>,
77
78 #[serde(skip_serializing_if = "Option::is_none")]
80 pub is_only_realtime: Option<bool>,
81}
82
83#[derive(Debug, Clone, Serialize)]
85pub struct TickerSubscription {
86 pub ticket: String,
88
89 #[serde(rename = "type")]
91 pub data_type: String,
92
93 pub codes: SmallVec<[String; 8]>,
95
96 #[serde(skip_serializing_if = "Option::is_none")]
98 pub is_only_snapshot: Option<bool>,
99
100 #[serde(skip_serializing_if = "Option::is_none")]
102 pub is_only_realtime: Option<bool>,
103}
104
105#[derive(Debug, Clone, Serialize)]
107pub struct FormatRequest {
108 pub format: String,
110}
111
112#[inline(always)]
114pub fn create_trade_subscription(
115 ticket: &str,
116 symbols: SmallVec<[String; 8]>,
117 is_only_snapshot: Option<bool>,
118 is_only_realtime: Option<bool>,
119 use_simple_format: bool,
120) -> Vec<simd_json::OwnedValue> {
121 let mut payload = SmallVec::<[simd_json::OwnedValue; 3]>::new();
122
123 payload.push(simd_json::json!({
125 "ticket": ticket,
126 }));
127
128 payload.push(simd_json::json!({
130 "type": "trade",
131 "codes": symbols.to_vec(),
132 "is_only_snapshot": is_only_snapshot,
133 "is_only_realtime": is_only_realtime,
134 }));
135
136 payload.push(simd_json::json!({
138 "format": if use_simple_format { "SIMPLE" } else { "DEFAULT" },
139 }));
140
141 payload.into_vec()
142}
143
144#[inline(always)]
146pub fn create_orderbook_subscription(
147 ticket: &str,
148 symbols: SmallVec<[String; 8]>,
149 level: Option<f64>,
150 is_only_snapshot: Option<bool>,
151 is_only_realtime: Option<bool>,
152 use_simple_format: bool,
153) -> Vec<simd_json::OwnedValue> {
154 let mut payload = SmallVec::<[simd_json::OwnedValue; 3]>::new();
155
156 payload.push(simd_json::json!({
158 "ticket": ticket,
159 }));
160
161 let mut type_field = simd_json::json!({
163 "type": "orderbook",
164 "codes": symbols.to_vec(),
165 "is_only_snapshot": is_only_snapshot,
166 "is_only_realtime": is_only_realtime,
167 });
168
169 if let Some(level_value) = level {
171 type_field["level"] = simd_json::json!(level_value);
172 }
173
174 payload.push(type_field);
175
176 payload.push(simd_json::json!({
178 "format": if use_simple_format { "SIMPLE" } else { "DEFAULT" },
179 }));
180
181 payload.into_vec()
182}