wow_world_messages/world/wrath/
smsg_server_message.rs1use std::io::{Read, Write};
2
3use crate::wrath::ServerMessageType;
4
5#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
13pub struct SMSG_SERVER_MESSAGE {
14 pub message_type: ServerMessageType,
15 pub message: String,
16}
17
18impl crate::private::Sealed for SMSG_SERVER_MESSAGE {}
19impl SMSG_SERVER_MESSAGE {
20 fn read_inner(mut r: &mut &[u8], body_size: u32) -> Result<Self, crate::errors::ParseErrorKind> {
21 if !(5..=260).contains(&body_size) {
22 return Err(crate::errors::ParseErrorKind::InvalidSize);
23 }
24
25 let message_type = crate::util::read_u32_le(&mut r)?.try_into()?;
27
28 let message = {
30 let message = crate::util::read_c_string_to_vec(&mut r)?;
31 String::from_utf8(message)?
32 };
33
34 Ok(Self {
35 message_type,
36 message,
37 })
38 }
39
40}
41
42impl crate::Message for SMSG_SERVER_MESSAGE {
43 const OPCODE: u32 = 0x0291;
44
45 #[cfg(feature = "print-testcase")]
46 fn message_name(&self) -> &'static str {
47 "SMSG_SERVER_MESSAGE"
48 }
49
50 #[cfg(feature = "print-testcase")]
51 fn to_test_case_string(&self) -> Option<String> {
52 use std::fmt::Write;
53 use crate::traits::Message;
54
55 let mut s = String::new();
56
57 writeln!(s, "test SMSG_SERVER_MESSAGE {{").unwrap();
58 writeln!(s, " message_type = {};", self.message_type.as_test_case_value()).unwrap();
60 writeln!(s, " message = \"{}\";", self.message).unwrap();
61
62 writeln!(s, "}} [").unwrap();
63
64 let [a, b] = (u16::try_from(self.size() + 2).unwrap()).to_be_bytes();
65 writeln!(s, " {a:#04X}, {b:#04X}, /* size */").unwrap();
66 let [a, b] = 657_u16.to_le_bytes();
67 writeln!(s, " {a:#04X}, {b:#04X}, /* opcode */").unwrap();
68 let mut bytes: Vec<u8> = Vec::new();
69 self.write_into_vec(&mut bytes).unwrap();
70 let mut bytes = bytes.into_iter();
71
72 crate::util::write_bytes(&mut s, &mut bytes, 4, "message_type", " ");
73 crate::util::write_bytes(&mut s, &mut bytes, self.message.len() + 1, "message", " ");
74
75
76 writeln!(s, "] {{").unwrap();
77 writeln!(s, " versions = \"{}\";", std::env::var("WOWM_TEST_CASE_WORLD_VERSION").unwrap_or("3.3.5".to_string())).unwrap();
78 writeln!(s, "}}\n").unwrap();
79
80 Some(s)
81 }
82
83 fn size_without_header(&self) -> u32 {
84 self.size() as u32
85 }
86
87 fn write_into_vec(&self, mut w: impl Write) -> Result<(), std::io::Error> {
88 w.write_all(&(self.message_type.as_int().to_le_bytes()))?;
90
91 assert_ne!(self.message.as_bytes().iter().next_back(), Some(&0_u8), "String `message` must not be null-terminated.");
94 w.write_all(self.message.as_bytes())?;
95 w.write_all(&[0])?;
97
98 Ok(())
99 }
100
101 fn read_body<S: crate::private::Sealed>(r: &mut &[u8], body_size: u32) -> Result<Self, crate::errors::ParseError> {
102 Self::read_inner(r, body_size).map_err(|a| crate::errors::ParseError::new(657, "SMSG_SERVER_MESSAGE", body_size, a))
103 }
104
105}
106
107#[cfg(feature = "wrath")]
108impl crate::wrath::ServerMessage for SMSG_SERVER_MESSAGE {}
109
110impl SMSG_SERVER_MESSAGE {
111 pub(crate) fn size(&self) -> usize {
112 4 + self.message.len() + 1 }
115}
116