wow_world_messages/world/wrath/
smsg_server_message.rs

1use std::io::{Read, Write};
2
3use crate::wrath::ServerMessageType;
4
5/// Auto generated from the original `wowm` in file [`wow_message_parser/wowm/world/chat/smsg_server_message.wowm:32`](https://github.com/gtker/wow_messages/tree/main/wow_message_parser/wowm/world/chat/smsg_server_message.wowm#L32):
6/// ```text
7/// smsg SMSG_SERVER_MESSAGE = 0x0291 {
8///     ServerMessageType message_type;
9///     CString message;
10/// }
11/// ```
12#[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        // message_type: ServerMessageType
26        let message_type = crate::util::read_u32_le(&mut r)?.try_into()?;
27
28        // message: CString
29        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        // Members
59        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        // message_type: ServerMessageType
89        w.write_all(&(self.message_type.as_int().to_le_bytes()))?;
90
91        // message: CString
92        // TODO: Guard against strings that are already null-terminated
93        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        // Null terminator
96        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 // message_type: ServerMessageType
113        + self.message.len() + 1 // message: CString
114    }
115}
116