wow_world_messages/world/vanilla/
cmsg_send_mail.rs1use std::io::{Read, Write};
2
3use crate::Guid;
4use crate::shared::gold_vanilla_tbc_wrath::Gold;
5
6#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
23pub struct CMSG_SEND_MAIL {
24 pub mailbox: Guid,
25 pub receiver: String,
26 pub subject: String,
27 pub body: String,
28 pub unknown1: u32,
30 pub unknown2: u32,
32 pub item: Guid,
33 pub money: Gold,
34 pub cash_on_delivery_amount: u32,
35 pub unknown3: u32,
37 pub unknown4: u32,
39}
40
41impl crate::private::Sealed for CMSG_SEND_MAIL {}
42impl CMSG_SEND_MAIL {
43 fn read_inner(mut r: &mut &[u8], body_size: u32) -> Result<Self, crate::errors::ParseErrorKind> {
44 if !(43..=808).contains(&body_size) {
45 return Err(crate::errors::ParseErrorKind::InvalidSize);
46 }
47
48 let mailbox = crate::util::read_guid(&mut r)?;
50
51 let receiver = {
53 let receiver = crate::util::read_c_string_to_vec(&mut r)?;
54 String::from_utf8(receiver)?
55 };
56
57 let subject = {
59 let subject = crate::util::read_c_string_to_vec(&mut r)?;
60 String::from_utf8(subject)?
61 };
62
63 let body = {
65 let body = crate::util::read_c_string_to_vec(&mut r)?;
66 String::from_utf8(body)?
67 };
68
69 let unknown1 = crate::util::read_u32_le(&mut r)?;
71
72 let unknown2 = crate::util::read_u32_le(&mut r)?;
74
75 let item = crate::util::read_guid(&mut r)?;
77
78 let money = Gold::new(crate::util::read_u32_le(&mut r)?);
80
81 let cash_on_delivery_amount = crate::util::read_u32_le(&mut r)?;
83
84 let unknown3 = crate::util::read_u32_le(&mut r)?;
86
87 let unknown4 = crate::util::read_u32_le(&mut r)?;
89
90 Ok(Self {
91 mailbox,
92 receiver,
93 subject,
94 body,
95 unknown1,
96 unknown2,
97 item,
98 money,
99 cash_on_delivery_amount,
100 unknown3,
101 unknown4,
102 })
103 }
104
105}
106
107impl crate::Message for CMSG_SEND_MAIL {
108 const OPCODE: u32 = 0x0238;
109
110 #[cfg(feature = "print-testcase")]
111 fn message_name(&self) -> &'static str {
112 "CMSG_SEND_MAIL"
113 }
114
115 #[cfg(feature = "print-testcase")]
116 fn to_test_case_string(&self) -> Option<String> {
117 use std::fmt::Write;
118 use crate::traits::Message;
119
120 let mut s = String::new();
121
122 writeln!(s, "test CMSG_SEND_MAIL {{").unwrap();
123 writeln!(s, " mailbox = {};", self.mailbox.guid()).unwrap();
125 writeln!(s, " receiver = \"{}\";", self.receiver).unwrap();
126 writeln!(s, " subject = \"{}\";", self.subject).unwrap();
127 writeln!(s, " body = \"{}\";", self.body).unwrap();
128 writeln!(s, " unknown1 = {};", self.unknown1).unwrap();
129 writeln!(s, " unknown2 = {};", self.unknown2).unwrap();
130 writeln!(s, " item = {};", self.item.guid()).unwrap();
131 writeln!(s, " money = {};", self.money.as_int()).unwrap();
132 writeln!(s, " cash_on_delivery_amount = {};", self.cash_on_delivery_amount).unwrap();
133 writeln!(s, " unknown3 = {};", self.unknown3).unwrap();
134 writeln!(s, " unknown4 = {};", self.unknown4).unwrap();
135
136 writeln!(s, "}} [").unwrap();
137
138 let [a, b] = (u16::try_from(self.size() + 4).unwrap()).to_be_bytes();
139 writeln!(s, " {a:#04X}, {b:#04X}, /* size */").unwrap();
140 let [a, b, c, d] = 568_u32.to_le_bytes();
141 writeln!(s, " {a:#04X}, {b:#04X}, {c:#04X}, {d:#04X}, /* opcode */").unwrap();
142 let mut bytes: Vec<u8> = Vec::new();
143 self.write_into_vec(&mut bytes).unwrap();
144 let mut bytes = bytes.into_iter();
145
146 crate::util::write_bytes(&mut s, &mut bytes, 8, "mailbox", " ");
147 crate::util::write_bytes(&mut s, &mut bytes, self.receiver.len() + 1, "receiver", " ");
148 crate::util::write_bytes(&mut s, &mut bytes, self.subject.len() + 1, "subject", " ");
149 crate::util::write_bytes(&mut s, &mut bytes, self.body.len() + 1, "body", " ");
150 crate::util::write_bytes(&mut s, &mut bytes, 4, "unknown1", " ");
151 crate::util::write_bytes(&mut s, &mut bytes, 4, "unknown2", " ");
152 crate::util::write_bytes(&mut s, &mut bytes, 8, "item", " ");
153 crate::util::write_bytes(&mut s, &mut bytes, 4, "money", " ");
154 crate::util::write_bytes(&mut s, &mut bytes, 4, "cash_on_delivery_amount", " ");
155 crate::util::write_bytes(&mut s, &mut bytes, 4, "unknown3", " ");
156 crate::util::write_bytes(&mut s, &mut bytes, 4, "unknown4", " ");
157
158
159 writeln!(s, "] {{").unwrap();
160 writeln!(s, " versions = \"{}\";", std::env::var("WOWM_TEST_CASE_WORLD_VERSION").unwrap_or("1".to_string())).unwrap();
161 writeln!(s, "}}\n").unwrap();
162
163 Some(s)
164 }
165
166 fn size_without_header(&self) -> u32 {
167 self.size() as u32
168 }
169
170 fn write_into_vec(&self, mut w: impl Write) -> Result<(), std::io::Error> {
171 w.write_all(&self.mailbox.guid().to_le_bytes())?;
173
174 assert_ne!(self.receiver.as_bytes().iter().next_back(), Some(&0_u8), "String `receiver` must not be null-terminated.");
177 w.write_all(self.receiver.as_bytes())?;
178 w.write_all(&[0])?;
180
181 assert_ne!(self.subject.as_bytes().iter().next_back(), Some(&0_u8), "String `subject` must not be null-terminated.");
184 w.write_all(self.subject.as_bytes())?;
185 w.write_all(&[0])?;
187
188 assert_ne!(self.body.as_bytes().iter().next_back(), Some(&0_u8), "String `body` must not be null-terminated.");
191 w.write_all(self.body.as_bytes())?;
192 w.write_all(&[0])?;
194
195 w.write_all(&self.unknown1.to_le_bytes())?;
197
198 w.write_all(&self.unknown2.to_le_bytes())?;
200
201 w.write_all(&self.item.guid().to_le_bytes())?;
203
204 w.write_all((self.money.as_int()).to_le_bytes().as_slice())?;
206
207 w.write_all(&self.cash_on_delivery_amount.to_le_bytes())?;
209
210 w.write_all(&self.unknown3.to_le_bytes())?;
212
213 w.write_all(&self.unknown4.to_le_bytes())?;
215
216 Ok(())
217 }
218
219 fn read_body<S: crate::private::Sealed>(r: &mut &[u8], body_size: u32) -> Result<Self, crate::errors::ParseError> {
220 Self::read_inner(r, body_size).map_err(|a| crate::errors::ParseError::new(568, "CMSG_SEND_MAIL", body_size, a))
221 }
222
223}
224
225#[cfg(feature = "vanilla")]
226impl crate::vanilla::ClientMessage for CMSG_SEND_MAIL {}
227
228impl CMSG_SEND_MAIL {
229 pub(crate) fn size(&self) -> usize {
230 8 + self.receiver.len() + 1 + self.subject.len() + 1 + self.body.len() + 1 + 4 + 4 + 8 + 4 + 4 + 4 + 4 }
242}
243