ygopro_data/message/
utils.rs1use std::fmt::Debug;
7use binrw::BinRead;
8use binrw::BinWrite;
9
10use crate::constants::MasterRule;
11use crate::constants::Rule;
12
13pub trait PureMessage: 'static {}
14
15pub trait Message: PureMessage + Debug {
16 fn message_type() -> crate::message::all::MessageType where Self: Sized;
17}
18
19#[derive(BinRead, BinWrite, Clone, Debug)]
20#[repr(C)]
21pub struct HostInfo {
22 pub lflist: u32,
23 pub rule: Rule,
24 pub mode: crate::constants::Mode,
25 pub duel_rule: crate::constants::MasterRule,
26 #[br(map=|v:u8| v>0)]
27 #[bw(map=|v| if *v {1u8} else {0u8})]
28 pub no_check_deck: bool,
29 #[br(map=|v:u8| v>0)]
30 #[bw(map=|v| if *v {1u8} else {0u8})]
31 #[brw(pad_after=3)]
32 pub no_shuffle_deck: bool,
33 pub start_lp: u32,
34 pub start_hand: u8,
35 pub draw_count: u8,
36 pub time_limit: u16
37}
38
39impl Default for HostInfo {
40 fn default() -> Self {
41 Self {
42 lflist: 0,
43 rule: Rule::OCG,
44 mode: crate::constants::Mode::Match,
45 duel_rule: MasterRule::MasterRule2020,
46 no_check_deck: false,
47 no_shuffle_deck: false,
48 start_lp: 8000,
49 start_hand: 5,
50 draw_count: 1,
51 time_limit: 180
52 }
53 }
54}
55
56#[derive(thiserror::Error, Debug)]
57pub enum Error {
58 #[error("Something wrong when io")]
59 IO(std::io::Error),
60 #[error("Custom error")]
61 Custom(String),
62 #[error("Try to serialize a component over its design size")]
63 Oversize,
64 #[error("Deserialize finished, but remain some bytes")]
65 Remain(Vec<u8>),
66 #[error("Try to deserialize a seq without limit.")]
67 Unlimited,
68 #[error("Some error happened when unwrap the writer.")]
69 UnwrapWriter,
70 #[error("Try to deserialize to a wrong type.")]
71 WrongType,
72 #[error("Try to deserialize an unknown type message.")]
73 UnknownType,
74 #[error("Try to change full message to wrong status.")]
75 WrongStatus,
76}
77
78#[macro_export]
79macro_rules! generate_enum {
80 ($($message_name:ident=$message_flag:literal),*) => {
81 #[derive(binrw::BinRead, binrw::BinWrite, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
82 #[brw(repr=u8)]
83 #[repr(u8)]
84 pub enum MessageType {
85 Unknown(u8),
86 $($message_name=$message_flag),*
87 }
88
89 impl std::convert::From<u8> for MessageType {
90 fn from(value: u8) -> Self {
91 match value {
92 $($message_flag => Self::$message_name,)*
93 _ => Self::Unknown(value)
94 }
95 }
96 }
97
98 impl std::convert::From<MessageType> for u8 {
99 fn from(value: MessageType) -> Self {
100 match value {
101 $(MessageType::$message_name => $message_flag,)*
102 MessageType::Unknown(v) => v
103 }
104 }
105 }
106
107 impl std::convert::From<&MessageType> for u8 {
108 fn from(value: &MessageType) -> Self {
109 match *value {
110 $(MessageType::$message_name => $message_flag,)*
111 MessageType::Unknown(v) => v
112 }
113 }
114 }
115
116 #[derive(binrw::BinRead, binrw::BinWrite, Clone, Debug)]
117 pub enum Message {
118 $(#[brw(magic($message_flag))]
119 $message_name($message_name)),*
120 }
121
122 impl crate::message::PureMessage for Message {}
123
124 impl From<&Message> for MessageType {
125 fn from(value: &Message) -> Self {
126 match value {
127 $(Message::$message_name(_) => MessageType::$message_name),*
128 }
129 }
130 }
131
132 $(
133 impl TryFrom<Message> for $message_name {
134 type Error = crate::message::Error;
135
136 fn try_from(value: Message) -> Result<Self, Self::Error> {
137 match value {
138 Message::$message_name(v) => Ok(v),
139 _ => Err(crate::message::Error::WrongType)
140 }
141 }
142 }
143
144 impl<'m> TryFrom<&'m Message> for &'m $message_name {
145 type Error = crate::message::Error;
146
147 fn try_from(value: &'m Message) -> Result<Self, Self::Error> {
148 match value {
149 Message::$message_name(v) => Ok(v),
150 _ => Err(crate::message::Error::WrongType)
151 }
152 }
153 }
154
155 impl From<$message_name> for Message {
156 fn from(value: $message_name) -> Self {
157 Message::$message_name(value)
158 }
159 }
160
161 impl $message_name {
162 pub fn into_message(self) -> Message {
163 self.into()
164 }
165 }
166 )*
167 };
168}
169
170mod test {
171 #![allow(unused_imports)]
172
173 use std::io::Cursor;
174 use binrw::BinRead;
175 use binrw::BinWrite;
176
177 use crate::message::client_to_server::HandResult;
178 use crate::message::client_to_server::JoinGame;
179 use crate::message::client_to_server::MessageType;
180 use crate::message::client_to_server::Message;
181
182 #[test]
183 fn test_message_type_basic() {
184 let message_type = MessageType::CreateGame;
185 let mut vec = Cursor::new(Vec::<u8>::new());
186 message_type.write_le(&mut vec).unwrap();
187 assert_eq!(vec.into_inner(), [17]);
188
189 let mut vec = Cursor::new(vec![127]);
190 let message_type = MessageType::read_le(&mut vec).unwrap();
191 assert_eq!(message_type, MessageType::Unknown(127));
192 }
193
194 #[test]
195 fn test_message_enum_basic() {
196 let message_enum = Message::HandResult(HandResult {
197 res: crate::constants::Hand::Paper
198 });
199 let mut vec = Cursor::new(Vec::<u8>::new());
200 message_enum.write_le(&mut vec).unwrap();
201 println!("{:?}", vec.into_inner());
202 }
203}