1use byteserde_derive::{ByteDeserializeSlice, ByteSerializeStack, ByteSerializedLenOf};
2use derive_more::TryInto;
3use serde::{Deserialize, Serialize};
4use soupbintcp_model::prelude::{CltSoupBinTcpMsg, SoupBinTcpPayload, SvcSoupBinTcpMsg, UniSoupBinTcpMsg, SOUPBINTCP_MAX_FRAME_SIZE_EXCLUDING_PAYLOAD_DEBUG};
5
6use crate::prelude::*;
7
8pub const SVC_OUCH_MAX_PLD_SIZE: usize = 151; pub const SVC_OUCH_MAX_FRAME_SIZE: usize = SVC_OUCH_MAX_PLD_SIZE + SOUPBINTCP_MAX_FRAME_SIZE_EXCLUDING_PAYLOAD_DEBUG;
10
11pub const CLT_OUCH_MAX_PLD_SIZE: usize = 134; pub const CLT_OUCH_MAX_FRAME_SIZE: usize = CLT_OUCH_MAX_PLD_SIZE + SOUPBINTCP_MAX_FRAME_SIZE_EXCLUDING_PAYLOAD_DEBUG;
13
14pub const OUCH_MAX_FRAME_SIZE: usize = {
15 if SVC_OUCH_MAX_FRAME_SIZE > CLT_OUCH_MAX_FRAME_SIZE {
16 SVC_OUCH_MAX_FRAME_SIZE
17 } else {
18 CLT_OUCH_MAX_FRAME_SIZE
19 }
20};
21#[derive(ByteSerializeStack, ByteDeserializeSlice, ByteSerializedLenOf, Serialize, Deserialize, PartialEq, Clone, Debug, TryInto)]
22#[try_into(owned, ref, ref_mut)]
23#[byteserde(peek(0, 1))]
24pub enum CltOuchPayload {
25 #[byteserde(eq(PacketTypeEnterOrder::as_slice()))]
26 EnterOrder(EnterOrder),
27 #[byteserde(eq(PacketTypeReplaceOrder::as_slice()))]
28 ReplaceOrder(ReplaceOrder),
29 #[byteserde(eq(PacketTypeCancelOrder::as_slice()))]
30 CancelOrder(CancelOrder),
31 #[byteserde(eq(PacketTypeModifyOrder::as_slice()))]
32 ModifyOrder(ModifyOrder),
33 #[byteserde(eq(PacketTypeAccountQueryRequest::as_slice()))]
34 AccountQueryRequest(AccountQueryRequest),
35}
36impl SoupBinTcpPayload<CltOuchPayload> for CltOuchPayload {}
37
38#[derive(ByteSerializeStack, ByteDeserializeSlice, ByteSerializedLenOf, Serialize, Deserialize, PartialEq, Clone, Debug, TryInto)]
40#[try_into(owned, ref, ref_mut)]
41#[byteserde(peek(0, 1))]
42pub enum SvcOuchPayload {
43 #[byteserde(eq(PacketTypeSystemEvent::as_slice()))]
44 SystemEvent(SystemEvent),
45 #[byteserde(eq(PacketTypeOrderAccepted::as_slice()))]
46 OrderAccepted(OrderAccepted),
47 #[byteserde(eq(PacketTypeOrderReplaced::as_slice()))]
48 OrderReplaced(OrderReplaced),
49 #[byteserde(eq(PacketTypeOrderCanceled::as_slice()))]
50 OrderCanceled(OrderCanceled),
51 #[byteserde(eq(PacketTypeOrderAiqCanceled::as_slice()))]
52 OrderAiqCanceled(OrderAiqCanceled),
53 #[byteserde(eq(PacketTypeOrderExecuted::as_slice()))]
54 OrderExecuted(OrderExecuted),
55 #[byteserde(eq(PacketTypeBrokenTrade::as_slice()))]
56 BrokenTrade(BrokenTrade),
57 #[byteserde(eq(PacketTypeOrderRejected::as_slice()))]
58 OrderRejected(OrderRejected),
59 #[byteserde(eq(PacketTypeCancelPending::as_slice()))]
60 CancelPending(CancelPending),
61 #[byteserde(eq(PacketTypeCancelReject::as_slice()))]
62 CancelReject(CancelReject),
63 #[byteserde(eq(PacketTypePriorityUpdate::as_slice()))]
64 PriorityUpdate(PriorityUpdate),
65 #[byteserde(eq(PacketTypeOrderModified::as_slice()))]
66 OrderModified(OrderModified),
67 #[byteserde(eq(PacketTypeOrderRestated::as_slice()))]
68 OrderRestated(OrderRestated),
69 #[byteserde(eq(PacketTypeAccountQueryResponse::as_slice()))]
70 AccountQueryResponse(AccountQueryResponse),
71}
72
73impl SoupBinTcpPayload<SvcOuchPayload> for SvcOuchPayload {}
74pub type CltOuchMsg = CltSoupBinTcpMsg<CltOuchPayload>;
75pub type SvcOuchMsg = SvcSoupBinTcpMsg<SvcOuchPayload>;
76
77pub type UniOuchMsg = UniSoupBinTcpMsg<CltOuchPayload, SvcOuchPayload>;
78
79macro_rules! for_uni_ouch_msg {
80 ($FROM:ty, $ENUM:path) => {
81 impl From<$FROM> for UniOuchMsg {
82 #[inline(always)]
83 fn from(payload: $FROM) -> Self {
84 $ENUM(payload.into())
85 }
86 }
87 };
88}
89
90mod froms_clt_pld {
91 use super::*;
92 macro_rules! for_clt_ouch_msg {
93 ($FROM:ty, $PAYLOAD_ENUM:path) => {
94 impl From<$FROM> for CltOuchMsg {
95 #[inline(always)]
96 fn from(payload: $FROM) -> Self {
97 Self::udata($PAYLOAD_ENUM(payload))
98 }
99 }
100 };
101 }
102 for_clt_ouch_msg!(EnterOrder, CltOuchPayload::EnterOrder);
103 for_clt_ouch_msg!(ReplaceOrder, CltOuchPayload::ReplaceOrder);
104 for_clt_ouch_msg!(CancelOrder, CltOuchPayload::CancelOrder);
105 for_clt_ouch_msg!(ModifyOrder, CltOuchPayload::ModifyOrder);
106 for_clt_ouch_msg!(AccountQueryRequest, CltOuchPayload::AccountQueryRequest);
107
108 for_uni_ouch_msg!(EnterOrder, UniOuchMsg::Clt);
109 for_uni_ouch_msg!(ReplaceOrder, UniOuchMsg::Clt);
110 for_uni_ouch_msg!(CancelOrder, UniOuchMsg::Clt);
111 for_uni_ouch_msg!(ModifyOrder, UniOuchMsg::Clt);
112 for_uni_ouch_msg!(AccountQueryRequest, UniOuchMsg::Clt);
113}
114
115mod froms_svc_pld {
116 use super::*;
117 macro_rules! for_svc_ouch_msg {
118 ($FROM:ty, $PAYLOAD_ENUM:path) => {
119 impl From<$FROM> for SvcOuchMsg {
120 #[inline(always)]
121 fn from(payload: $FROM) -> Self {
122 Self::sdata($PAYLOAD_ENUM(payload))
123 }
124 }
125 };
126 }
127 for_svc_ouch_msg!(SystemEvent, SvcOuchPayload::SystemEvent);
128 for_svc_ouch_msg!(OrderAccepted, SvcOuchPayload::OrderAccepted);
129 for_svc_ouch_msg!(OrderReplaced, SvcOuchPayload::OrderReplaced);
130 for_svc_ouch_msg!(OrderCanceled, SvcOuchPayload::OrderCanceled);
131 for_svc_ouch_msg!(OrderAiqCanceled, SvcOuchPayload::OrderAiqCanceled);
132 for_svc_ouch_msg!(OrderExecuted, SvcOuchPayload::OrderExecuted);
133 for_svc_ouch_msg!(BrokenTrade, SvcOuchPayload::BrokenTrade);
134 for_svc_ouch_msg!(OrderRejected, SvcOuchPayload::OrderRejected);
135 for_svc_ouch_msg!(CancelPending, SvcOuchPayload::CancelPending);
136 for_svc_ouch_msg!(CancelReject, SvcOuchPayload::CancelReject);
137 for_svc_ouch_msg!(PriorityUpdate, SvcOuchPayload::PriorityUpdate);
138 for_svc_ouch_msg!(OrderModified, SvcOuchPayload::OrderModified);
139 for_svc_ouch_msg!(OrderRestated, SvcOuchPayload::OrderRestated);
140 for_svc_ouch_msg!(AccountQueryResponse, SvcOuchPayload::AccountQueryResponse);
141
142 for_uni_ouch_msg!(SystemEvent, UniOuchMsg::Svc);
143 for_uni_ouch_msg!(OrderAccepted, UniOuchMsg::Svc);
144 for_uni_ouch_msg!(OrderReplaced, UniOuchMsg::Svc);
145 for_uni_ouch_msg!(OrderCanceled, UniOuchMsg::Svc);
146 for_uni_ouch_msg!(OrderAiqCanceled, UniOuchMsg::Svc);
147 for_uni_ouch_msg!(OrderExecuted, UniOuchMsg::Svc);
148 for_uni_ouch_msg!(BrokenTrade, UniOuchMsg::Svc);
149 for_uni_ouch_msg!(OrderRejected, UniOuchMsg::Svc);
150 for_uni_ouch_msg!(CancelPending, UniOuchMsg::Svc);
151 for_uni_ouch_msg!(CancelReject, UniOuchMsg::Svc);
152 for_uni_ouch_msg!(PriorityUpdate, UniOuchMsg::Svc);
153 for_uni_ouch_msg!(OrderModified, UniOuchMsg::Svc);
154 for_uni_ouch_msg!(OrderRestated, UniOuchMsg::Svc);
155 for_uni_ouch_msg!(AccountQueryResponse, UniOuchMsg::Svc);
156}
157
158#[cfg(test)]
159#[cfg(feature = "unittest")]
160mod test {
161
162 use crate::{
163 model::ouch::{CLT_OUCH_MAX_PLD_SIZE, SVC_OUCH_MAX_PLD_SIZE},
164 prelude::*,
165 unittest::setup::model::{clt_ouch_default_msgs, svc_ouch_default_msgs},
166 };
167 use byteserde::prelude::*;
168 use links_core::unittest::setup;
169 use log::info;
170 use serde_json::to_string;
171
172 #[test]
173 fn test_ouch_with_envelope_ser_des() {
174 setup::log::configure_compact(log::LevelFilter::Info);
175
176 let mut msg_inp = vec![];
177 for clt in clt_ouch_default_msgs() {
178 msg_inp.push((&clt).into());
179 }
180 for svc in svc_ouch_default_msgs() {
181 msg_inp.push((&svc).into());
182 }
183 let mut ser = ByteSerializerStack::<{ 1024 * 2 }>::default();
184 for msg in msg_inp.iter() {
185 match msg {
186 UniOuchMsg::Clt(msg_inp_inb) => {
187 info!("msg_inp_inb: {}", to_string(msg_inp_inb).unwrap());
189 let _ = ser.serialize(msg_inp_inb).unwrap();
190 }
191 UniOuchMsg::Svc(msg_inp_oub) => {
192 info!("msg_inp_oub: {}", to_string(msg_inp_oub).unwrap());
194 let _ = ser.serialize(msg_inp_oub).unwrap();
195 }
196 }
197 }
198 let mut des = ByteDeserializerSlice::new(ser.as_slice());
199
200 for ouch in msg_inp.iter() {
201 match ouch {
202 UniOuchMsg::Clt(msg_inp_inb) => {
203 let msg_out_inb = des.deserialize::<CltOuchMsg>().unwrap();
204 info!("msg_out_inb: {}", to_string(&msg_out_inb).unwrap());
205 assert_eq!(msg_inp_inb, &msg_out_inb);
206 }
207 UniOuchMsg::Svc(msg_inp_oub) => {
208 let msg_out_oub = des.deserialize::<SvcOuchMsg>().unwrap();
209 info!("msg_out_oub: {}", to_string(&msg_out_oub).unwrap());
210 assert_eq!(msg_inp_oub, &msg_out_oub);
211 }
212 }
213 }
214 assert!(des.is_empty());
215 }
216
217 #[test]
218 fn test_ouch5_max_size() {
219 setup::log::configure_compact(log::LevelFilter::Info);
220
221 let inb = clt_ouch_default_msgs().into_iter().map(|msg| (msg.byte_len(), msg)).collect::<Vec<_>>();
222 for (byte_len, clt_msg) in inb.iter() {
223 info!("byte_len: {:>3}, clt_msg: {}", byte_len, to_string(clt_msg).unwrap());
224 }
225 let max_frame_size_clt = inb.iter().map(|(len, _)| *len).max().unwrap();
226 info!("max_frame_size_clt: {}", max_frame_size_clt);
227 assert_eq!(max_frame_size_clt, CLT_OUCH_MAX_PLD_SIZE);
228
229 let oub = svc_ouch_default_msgs().into_iter().map(|msg| (msg.byte_len(), msg)).collect::<Vec<_>>();
230 for (byte_len, svc_msg) in oub.iter() {
231 info!("byte_len: {:>3}, svc_msg: {}", byte_len, to_string(svc_msg).unwrap());
232 }
233 let max_frame_size_svc = oub.iter().map(|(len, _)| *len).max().unwrap();
234 info!("max_frame_size_svc: {}", max_frame_size_svc);
235 assert_eq!(max_frame_size_svc, SVC_OUCH_MAX_PLD_SIZE);
236 }
237}