1use ringkernel_core::message::{CorrelationId, MessageId};
13use ringkernel_derive::RingMessage;
14use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
15
16use crate::types::{Order, Price, Quantity, Side};
17
18#[derive(Debug, Clone, Archive, RkyvSerialize, RkyvDeserialize, RingMessage)]
39#[message(type_id = 500)]
40#[archive(check_bytes)]
41pub struct SubmitOrderRing {
42 #[message(id)]
44 pub id: MessageId,
45 #[message(correlation)]
47 pub correlation_id: CorrelationId,
48 pub order_id: u64,
50 pub symbol_id: u32,
52 pub side: RingSide,
54 pub order_type: RingOrderType,
56 pub price: i64,
58 pub quantity: u64,
60 pub trader_id: u64,
62 pub timestamp: u64,
64}
65
66impl SubmitOrderRing {
67 pub fn limit(
69 order_id: u64,
70 symbol_id: u32,
71 side: Side,
72 price: Price,
73 quantity: Quantity,
74 trader_id: u64,
75 timestamp: u64,
76 ) -> Self {
77 Self {
78 id: MessageId::generate(),
79 correlation_id: CorrelationId::generate(),
80 order_id,
81 symbol_id,
82 side: side.into(),
83 order_type: RingOrderType::Limit,
84 price: price.0,
85 quantity: quantity.0,
86 trader_id,
87 timestamp,
88 }
89 }
90
91 pub fn market(
93 order_id: u64,
94 symbol_id: u32,
95 side: Side,
96 quantity: Quantity,
97 trader_id: u64,
98 timestamp: u64,
99 ) -> Self {
100 Self {
101 id: MessageId::generate(),
102 correlation_id: CorrelationId::generate(),
103 order_id,
104 symbol_id,
105 side: side.into(),
106 order_type: RingOrderType::Market,
107 price: 0,
108 quantity: quantity.0,
109 trader_id,
110 timestamp,
111 }
112 }
113
114 pub fn to_order(&self) -> Order {
116 match self.order_type {
117 RingOrderType::Limit => Order::limit(
118 self.order_id,
119 self.symbol_id,
120 self.side.into(),
121 Price(self.price),
122 Quantity(self.quantity),
123 self.trader_id,
124 self.timestamp,
125 ),
126 RingOrderType::Market => Order::market(
127 self.order_id,
128 self.symbol_id,
129 self.side.into(),
130 Quantity(self.quantity),
131 self.trader_id,
132 self.timestamp,
133 ),
134 }
135 }
136}
137
138#[derive(Debug, Clone, RingMessage, Archive, RkyvSerialize, RkyvDeserialize)]
142#[message(type_id = 501)]
143#[archive(check_bytes)]
144pub struct SubmitOrderResponse {
145 #[message(correlation)]
147 pub correlation_id: CorrelationId,
148 pub order_id: u64,
150 pub status: RingOrderStatus,
152 pub filled_quantity: u64,
154 pub avg_price: i64,
156 pub remaining: u64,
158 pub trade_count: u32,
160 pub error: RingString,
162}
163
164#[derive(Debug, Clone, RingMessage, Archive, RkyvSerialize, RkyvDeserialize)]
172#[message(type_id = 520)]
173#[archive(check_bytes)]
174pub struct CancelOrderRing {
175 #[message(id)]
177 pub id: MessageId,
178 #[message(correlation)]
180 pub correlation_id: CorrelationId,
181 pub order_id: u64,
183}
184
185impl CancelOrderRing {
186 pub fn new(order_id: u64) -> Self {
188 Self {
189 id: MessageId::generate(),
190 correlation_id: CorrelationId::generate(),
191 order_id,
192 }
193 }
194}
195
196#[derive(Debug, Clone, RingMessage, Archive, RkyvSerialize, RkyvDeserialize)]
200#[message(type_id = 521)]
201#[archive(check_bytes)]
202pub struct CancelOrderResponse {
203 #[message(correlation)]
205 pub correlation_id: CorrelationId,
206 pub order_id: u64,
208 pub success: bool,
210 pub remaining: u64,
212}
213
214#[derive(Debug, Clone, RingMessage, Archive, RkyvSerialize, RkyvDeserialize)]
222#[message(type_id = 530)]
223#[archive(check_bytes)]
224pub struct QueryBookRing {
225 #[message(id)]
227 pub id: MessageId,
228 #[message(correlation)]
230 pub correlation_id: CorrelationId,
231 pub symbol_id: u32,
233 pub depth: u32,
235}
236
237impl QueryBookRing {
238 pub fn new(symbol_id: u32, depth: u32) -> Self {
240 Self {
241 id: MessageId::generate(),
242 correlation_id: CorrelationId::generate(),
243 symbol_id,
244 depth,
245 }
246 }
247}
248
249#[derive(Debug, Clone, RingMessage, Archive, RkyvSerialize, RkyvDeserialize)]
253#[message(type_id = 531)]
254#[archive(check_bytes)]
255pub struct QueryBookResponse {
256 #[message(correlation)]
258 pub correlation_id: CorrelationId,
259 pub symbol_id: u32,
261 pub best_bid: i64,
263 pub best_ask: i64,
265 pub bid_depth: u64,
267 pub ask_depth: u64,
269 pub spread: i64,
271 pub mid_price: i64,
273}
274
275#[derive(Debug, Clone, RingMessage, Archive, RkyvSerialize, RkyvDeserialize)]
283#[message(type_id = 540)]
284#[archive(check_bytes)]
285pub struct CrossSymbolTrade {
286 #[message(id)]
288 pub id: MessageId,
289 #[message(correlation)]
291 pub correlation_id: CorrelationId,
292 pub source_symbol: u32,
294 pub target_symbol: u32,
296 pub quantity: u64,
298 pub price: i64,
300 pub timestamp: u64,
302}
303
304#[derive(Debug, Clone, Copy, PartialEq, Eq, Archive, RkyvSerialize, RkyvDeserialize)]
310#[archive(check_bytes)]
311#[repr(u8)]
312pub enum RingSide {
313 Buy = 0,
315 Sell = 1,
317}
318
319impl From<Side> for RingSide {
320 fn from(side: Side) -> Self {
321 match side {
322 Side::Buy => RingSide::Buy,
323 Side::Sell => RingSide::Sell,
324 }
325 }
326}
327
328impl From<RingSide> for Side {
329 fn from(side: RingSide) -> Self {
330 match side {
331 RingSide::Buy => Side::Buy,
332 RingSide::Sell => Side::Sell,
333 }
334 }
335}
336
337#[derive(Debug, Clone, Copy, PartialEq, Eq, Archive, RkyvSerialize, RkyvDeserialize)]
339#[archive(check_bytes)]
340#[repr(u8)]
341pub enum RingOrderType {
342 Limit = 0,
344 Market = 1,
346}
347
348#[derive(Debug, Clone, Copy, PartialEq, Eq, Archive, RkyvSerialize, RkyvDeserialize)]
350#[archive(check_bytes)]
351#[repr(u8)]
352pub enum RingOrderStatus {
353 New = 0,
355 PartiallyFilled = 1,
357 Filled = 2,
359 Canceled = 3,
361 Rejected = 4,
363}
364
365#[derive(Debug, Clone, Archive, RkyvSerialize, RkyvDeserialize)]
367#[archive(check_bytes)]
368pub struct RingString {
369 pub data: [u8; 64],
371 pub len: u8,
373}
374
375impl RingString {
376 pub fn empty() -> Self {
378 Self {
379 data: [0; 64],
380 len: 0,
381 }
382 }
383
384 pub fn from_string(s: &str) -> Self {
386 let bytes = s.as_bytes();
387 let len = bytes.len().min(63) as u8;
388 let mut data = [0u8; 64];
389 data[..len as usize].copy_from_slice(&bytes[..len as usize]);
390 Self { data, len }
391 }
392
393 pub fn as_str(&self) -> &str {
395 std::str::from_utf8(&self.data[..self.len as usize]).unwrap_or("")
396 }
397}
398
399impl Default for RingString {
400 fn default() -> Self {
401 Self::empty()
402 }
403}
404
405#[cfg(test)]
406mod tests {
407 use super::*;
408
409 #[test]
410 fn test_submit_order_ring() {
411 let msg = SubmitOrderRing::limit(
412 1,
413 100,
414 Side::Buy,
415 Price::from_f64(100.0),
416 Quantity::from_f64(10.0),
417 1000,
418 0,
419 );
420 assert_eq!(msg.order_id, 1);
421 assert_eq!(msg.symbol_id, 100);
422 assert_eq!(msg.side, RingSide::Buy);
423 }
424
425 #[test]
426 fn test_ring_string() {
427 let s = RingString::from_string("Hello, World!");
428 assert_eq!(s.as_str(), "Hello, World!");
429 assert_eq!(s.len, 13);
430 }
431
432 #[test]
433 fn test_ring_string_truncation() {
434 let long = "a".repeat(100);
435 let s = RingString::from_string(&long);
436 assert_eq!(s.len, 63);
437 }
438}