1use crate::Message;
2use crate::ServerMessage;
3use std::io::{Read, Write};
4
5use crate::logon::version_8::Realm;
6
7#[derive(Debug, Clone, PartialEq, PartialOrd, Default)]
18pub struct CMD_REALM_LIST_Server {
19 pub realms: Vec<Realm>,
20}
21
22impl CMD_REALM_LIST_Server {
23 pub const HEADER_PADDING_VALUE: u32 = 0x00;
33
34 pub const FOOTER_PADDING_VALUE: u16 = 0x00;
44
45}
46
47impl CMD_REALM_LIST_Server {
48 pub(crate) fn write_into_vec(&self, mut w: impl Write) -> Result<(), std::io::Error> {
49 w.write_all(&Self::OPCODE.to_le_bytes())?;
51
52 w.write_all(&((self.size() - 2) as u16).to_le_bytes())?;
54
55 w.write_all(&Self::HEADER_PADDING_VALUE.to_le_bytes())?;
57
58 w.write_all(&(self.realms.len() as u16).to_le_bytes())?;
60
61 for i in self.realms.iter() {
63 i.write_into_vec(&mut w)?;
64 }
65
66 w.write_all(&Self::FOOTER_PADDING_VALUE.to_le_bytes())?;
68
69 Ok(())
70 }
71}
72
73impl crate::private::Sealed for CMD_REALM_LIST_Server {}
74
75impl CMD_REALM_LIST_Server {
76 #[cfg(feature = "sync")]
77 fn read_inner<R: std::io::Read>(mut r: R) -> Result<Self, crate::errors::ParseErrorKind> {
78 let _size = crate::util::read_u16_le(&mut r)?;
80 let _header_padding = crate::util::read_u32_le(&mut r)?;
84 let number_of_realms = crate::util::read_u16_le(&mut r)?;
88
89 let realms = {
91 let mut realms = Vec::with_capacity(number_of_realms as usize);
92 for _ in 0..number_of_realms {
93 realms.push(Realm::read(&mut r)?);
94 }
95 realms
96 };
97
98 let _footer_padding = crate::util::read_u16_le(&mut r)?;
100 Ok(Self {
103 realms,
104 })
105 }
106
107 #[cfg(feature = "tokio")]
108 async fn tokio_read_inner<R: tokio::io::AsyncReadExt + Unpin + Send>(mut r: R) -> Result<Self, crate::errors::ParseErrorKind> {
109 let _size = crate::util::tokio_read_u16_le(&mut r).await?;
111 let _header_padding = crate::util::tokio_read_u32_le(&mut r).await?;
115 let number_of_realms = crate::util::tokio_read_u16_le(&mut r).await?;
119
120 let realms = {
122 let mut realms = Vec::with_capacity(number_of_realms as usize);
123 for _ in 0..number_of_realms {
124 realms.push(Realm::tokio_read(&mut r).await?);
125 }
126 realms
127 };
128
129 let _footer_padding = crate::util::tokio_read_u16_le(&mut r).await?;
131 Ok(Self {
134 realms,
135 })
136 }
137
138 #[cfg(feature = "async-std")]
139 async fn astd_read_inner<R: async_std::io::ReadExt + Unpin + Send>(mut r: R) -> Result<Self, crate::errors::ParseErrorKind> {
140 let _size = crate::util::astd_read_u16_le(&mut r).await?;
142 let _header_padding = crate::util::astd_read_u32_le(&mut r).await?;
146 let number_of_realms = crate::util::astd_read_u16_le(&mut r).await?;
150
151 let realms = {
153 let mut realms = Vec::with_capacity(number_of_realms as usize);
154 for _ in 0..number_of_realms {
155 realms.push(Realm::astd_read(&mut r).await?);
156 }
157 realms
158 };
159
160 let _footer_padding = crate::util::astd_read_u16_le(&mut r).await?;
162 Ok(Self {
165 realms,
166 })
167 }
168
169}
170
171impl Message for CMD_REALM_LIST_Server {
172 const OPCODE: u8 = 0x10;
173
174 #[cfg(feature = "sync")]
175 fn read<R: std::io::Read, I: crate::private::Sealed>(r: R) -> Result<Self, crate::errors::ParseError> {
176 Self::read_inner(r).map_err(|kind| crate::errors::ParseError::new(16, "CMD_REALM_LIST_Server", kind))
177 }
178
179 #[cfg(feature = "sync")]
180 fn write<W: std::io::Write>(&self, mut w: W) -> Result<(), std::io::Error> {
181 let mut v = Vec::with_capacity(self.size() + 1);
182 self.write_into_vec(&mut v)?;
183 w.write_all(&v)
184 }
185
186 #[cfg(feature = "tokio")]
187 fn tokio_read<'async_trait, R, I: crate::private::Sealed>(
188 r: R,
189 ) -> core::pin::Pin<Box<
190 dyn core::future::Future<Output = Result<Self, crate::errors::ParseError>>
191 + Send + 'async_trait,
192 >> where
193 R: 'async_trait + tokio::io::AsyncReadExt + Unpin + Send,
194 Self: 'async_trait,
195 {
196 Box::pin(async move {Self::tokio_read_inner(r).await.map_err(|kind| crate::errors::ParseError::new(16, "CMD_REALM_LIST_Server", kind))})
197 }
198
199 #[cfg(feature = "tokio")]
200 fn tokio_write<'life0, 'async_trait, W>(
201 &'life0 self,
202 mut w: W,
203 ) -> core::pin::Pin<Box<
204 dyn core::future::Future<Output = Result<(), std::io::Error>>
205 + Send + 'async_trait
206 >> where
207 W: 'async_trait + tokio::io::AsyncWriteExt + Unpin + Send,
208 'life0: 'async_trait,
209 Self: 'async_trait,
210 {
211 Box::pin(async move {
212 let mut v = Vec::with_capacity(self.size() + 1);
213 self.write_into_vec(&mut v)?;
214 w.write_all(&v).await
215 })
216 }
217
218 #[cfg(feature = "async-std")]
219 fn astd_read<'async_trait, R, I: crate::private::Sealed>(
220 r: R,
221 ) -> core::pin::Pin<Box<
222 dyn core::future::Future<Output = Result<Self, crate::errors::ParseError>>
223 + Send + 'async_trait,
224 >> where
225 R: 'async_trait + async_std::io::ReadExt + Unpin + Send,
226 Self: 'async_trait,
227 {
228 Box::pin(async move {Self::astd_read_inner(r).await.map_err(|kind| crate::errors::ParseError::new(16, "CMD_REALM_LIST_Server", kind))})
229 }
230
231 #[cfg(feature = "async-std")]
232 fn astd_write<'life0, 'async_trait, W>(
233 &'life0 self,
234 mut w: W,
235 ) -> core::pin::Pin<Box<
236 dyn core::future::Future<Output = Result<(), std::io::Error>>
237 + Send + 'async_trait
238 >> where
239 W: 'async_trait + async_std::io::WriteExt + Unpin + Send,
240 'life0: 'async_trait,
241 Self: 'async_trait,
242 {
243 Box::pin(async move {
244 let mut v = Vec::with_capacity(self.size() + 1);
245 self.write_into_vec(&mut v)?;
246 w.write_all(&v).await
247 })
248 }
249
250}
251
252impl ServerMessage for CMD_REALM_LIST_Server {}
253impl CMD_REALM_LIST_Server {
254 pub(crate) fn size(&self) -> usize {
255 2 + 4 + 2 + self.realms.iter().fold(0, |acc, x| acc + x.size()) + 2 }
261}
262
263#[cfg(test)]
264mod test {
265 #![allow(clippy::missing_const_for_fn)]
266 use super::CMD_REALM_LIST_Server;
267 use crate::all::*;
268 use super::*;
269 use super::super::*;
270 use crate::logon::version_8::opcodes::ServerOpcodeMessage;
271
272 const HEADER_SIZE: usize = 1;
273 const RAW0: [u8; 25] = [ 0x10, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
274 0x00, 0x00, 0x03, 0x41, 0x00, 0x41, 0x00, 0x00, 0x00, 0xC8, 0x43, 0x01,
275 0x00, 0x02, 0x00, 0x00, ];
276
277 pub(crate) fn expected0() -> CMD_REALM_LIST_Server {
278 CMD_REALM_LIST_Server {
279 realms: vec![
280 Realm {
281 realm_type: RealmType::PlayerVsEnvironment,
282 locked: false,
283 flag: Realm_RealmFlag::empty()
284 .set_invalid()
285 .set_offline()
286 ,
287 name: String::from("A"),
288 address: String::from("A"),
289 population: Population::RedFull,
290 number_of_characters_on_realm: 0x1,
291 category: RealmCategory::Default,
292 realm_id: 0x2,
293 },
294 ],
295 }
296
297 }
298
299 #[cfg(feature = "sync")]
301 #[cfg_attr(feature = "sync", test)]
302 fn cmd_realm_list_server0() {
303 let expected = expected0();
304 let t = ServerOpcodeMessage::read(&mut std::io::Cursor::new(&RAW0)).unwrap();
305 let t = match t {
306 ServerOpcodeMessage::CMD_REALM_LIST(t) => t,
307 opcode => panic!("incorrect opcode. Expected CMD_REALM_LIST, got {opcode:#?}"),
308 };
309
310 assert_eq!(&t, &expected);
311 assert_eq!(t.size() + HEADER_SIZE, RAW0.len());
312
313 let mut dest = Vec::with_capacity(RAW0.len());
314 expected.write(&mut std::io::Cursor::new(&mut dest)).unwrap();
315
316 assert_eq!(dest, RAW0);
317 }
318
319 #[cfg(feature = "tokio")]
321 #[cfg_attr(feature = "tokio", tokio::test)]
322 async fn tokio_cmd_realm_list_server0() {
323 let expected = expected0();
324 let t = ServerOpcodeMessage::tokio_read(&mut std::io::Cursor::new(&RAW0)).await.unwrap();
325 let t = match t {
326 ServerOpcodeMessage::CMD_REALM_LIST(t) => t,
327 opcode => panic!("incorrect opcode. Expected CMD_REALM_LIST, got {opcode:#?}"),
328 };
329
330 assert_eq!(&t, &expected);
331 assert_eq!(t.size() + HEADER_SIZE, RAW0.len());
332
333 let mut dest = Vec::with_capacity(RAW0.len());
334 expected.tokio_write(&mut std::io::Cursor::new(&mut dest)).await.unwrap();
335
336 assert_eq!(dest, RAW0);
337 }
338
339 #[cfg(feature = "async-std")]
341 #[cfg_attr(feature = "async-std", async_std::test)]
342 async fn astd_cmd_realm_list_server0() {
343 let expected = expected0();
344 let t = ServerOpcodeMessage::astd_read(&mut async_std::io::Cursor::new(&RAW0)).await.unwrap();
345 let t = match t {
346 ServerOpcodeMessage::CMD_REALM_LIST(t) => t,
347 opcode => panic!("incorrect opcode. Expected CMD_REALM_LIST, got {opcode:#?}"),
348 };
349
350 assert_eq!(&t, &expected);
351 assert_eq!(t.size() + HEADER_SIZE, RAW0.len());
352
353 let mut dest = Vec::with_capacity(RAW0.len());
354 expected.astd_write(&mut async_std::io::Cursor::new(&mut dest)).await.unwrap();
355
356 assert_eq!(dest, RAW0);
357 }
358
359 const RAW1: [u8; 30] = [ 0x10, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
360 0x00, 0x00, 0x04, 0x41, 0x00, 0x41, 0x00, 0x00, 0x00, 0xC8, 0x43, 0x01,
361 0x00, 0x02, 0x01, 0x0C, 0x01, 0xF3, 0x16, 0x00, 0x00, ];
362
363 pub(crate) fn expected1() -> CMD_REALM_LIST_Server {
364 CMD_REALM_LIST_Server {
365 realms: vec![
366 Realm {
367 realm_type: RealmType::PlayerVsEnvironment,
368 locked: false,
369 flag: Realm_RealmFlag::empty()
370 .set_specify_build(Realm_RealmFlag_SpecifyBuild {
371 version: Version {
372 major: 0x1,
373 minor: 0xC,
374 patch: 0x1,
375 build: 0x16F3,
376 },
377 })
378 ,
379 name: String::from("A"),
380 address: String::from("A"),
381 population: Population::RedFull,
382 number_of_characters_on_realm: 0x1,
383 category: RealmCategory::Default,
384 realm_id: 0x2,
385 },
386 ],
387 }
388
389 }
390
391 #[cfg(feature = "sync")]
393 #[cfg_attr(feature = "sync", test)]
394 fn cmd_realm_list_server1() {
395 let expected = expected1();
396 let t = ServerOpcodeMessage::read(&mut std::io::Cursor::new(&RAW1)).unwrap();
397 let t = match t {
398 ServerOpcodeMessage::CMD_REALM_LIST(t) => t,
399 opcode => panic!("incorrect opcode. Expected CMD_REALM_LIST, got {opcode:#?}"),
400 };
401
402 assert_eq!(&t, &expected);
403 assert_eq!(t.size() + HEADER_SIZE, RAW1.len());
404
405 let mut dest = Vec::with_capacity(RAW1.len());
406 expected.write(&mut std::io::Cursor::new(&mut dest)).unwrap();
407
408 assert_eq!(dest, RAW1);
409 }
410
411 #[cfg(feature = "tokio")]
413 #[cfg_attr(feature = "tokio", tokio::test)]
414 async fn tokio_cmd_realm_list_server1() {
415 let expected = expected1();
416 let t = ServerOpcodeMessage::tokio_read(&mut std::io::Cursor::new(&RAW1)).await.unwrap();
417 let t = match t {
418 ServerOpcodeMessage::CMD_REALM_LIST(t) => t,
419 opcode => panic!("incorrect opcode. Expected CMD_REALM_LIST, got {opcode:#?}"),
420 };
421
422 assert_eq!(&t, &expected);
423 assert_eq!(t.size() + HEADER_SIZE, RAW1.len());
424
425 let mut dest = Vec::with_capacity(RAW1.len());
426 expected.tokio_write(&mut std::io::Cursor::new(&mut dest)).await.unwrap();
427
428 assert_eq!(dest, RAW1);
429 }
430
431 #[cfg(feature = "async-std")]
433 #[cfg_attr(feature = "async-std", async_std::test)]
434 async fn astd_cmd_realm_list_server1() {
435 let expected = expected1();
436 let t = ServerOpcodeMessage::astd_read(&mut async_std::io::Cursor::new(&RAW1)).await.unwrap();
437 let t = match t {
438 ServerOpcodeMessage::CMD_REALM_LIST(t) => t,
439 opcode => panic!("incorrect opcode. Expected CMD_REALM_LIST, got {opcode:#?}"),
440 };
441
442 assert_eq!(&t, &expected);
443 assert_eq!(t.size() + HEADER_SIZE, RAW1.len());
444
445 let mut dest = Vec::with_capacity(RAW1.len());
446 expected.astd_write(&mut async_std::io::Cursor::new(&mut dest)).await.unwrap();
447
448 assert_eq!(dest, RAW1);
449 }
450
451}
452