ouch_model/model/
ouch.rs

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; // TODO revise Options fields and remeasure
9pub 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; // TODO revise Options fields and remeasure
12pub 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/// Both [ReplaceOrder] & [OrderReplaced] are serialized as b'U' hence it is impossible to distinguish deserialization type unless they are in two different enums.
39#[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: {:?}", msg_inp_inb);
188                    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: {:?}", msg_inp_oub);
193                    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}