wow_alchemy_data/
utils.rs1use crate::types::MagicStr;
2
3#[macro_export]
4macro_rules! wow_collection {
5 ($reader:ident, $header:expr, |$local_reader:ident, $item_header:ident| $constructor:expr) => {{
6 let mut iter = $header.new_iterator($local_reader)?;
7 let mut vec = Vec::with_capacity($header.count as usize);
8 loop {
9 match iter.next(|$local_reader, temp_header| {
10 let $item_header = match temp_header {
11 Some(item) => item,
12 None => $local_reader.wow_read()?,
13 };
14 vec.push($constructor);
15 Ok(())
16 }) {
17 Ok(is_active) => {
18 if !is_active {
19 break;
20 }
21 }
22 Err(err) => return Err(err.into()),
23 }
24 }
25 vec
26 }};
27}
28
29#[macro_export]
30macro_rules! v_wow_collection {
31 ($reader:ident, $version:expr, $header:expr, |$local_reader:ident, $item_header:ident| $constructor:expr) => {{
32 let mut iter = $header.new_iterator($local_reader, $version)?;
33 let mut vec = Vec::with_capacity($header.count as usize);
34 loop {
35 match iter.next(|$local_reader, temp_header| {
36 let $item_header = match temp_header {
37 Some(item) => item,
38 None => $local_reader.wow_read_versioned($version)?,
39 };
40 vec.push($constructor);
41 Ok(())
42 }) {
43 Ok(is_active) => {
44 if !is_active {
45 break;
46 }
47 }
48 Err(err) => return Err(err.into()),
49 }
50 }
51 vec
52 }};
53}
54
55#[macro_export]
56macro_rules! read_chunk_items {
57 ($reader:ident, $chunk_header:ident, $type:ty) => {{
58 let first: $type = $reader.wow_read()?;
59 let item_size = first.wow_size();
60 let items = $chunk_header.bytes as usize / item_size;
61
62 let rest = $chunk_header.bytes as usize % item_size;
63 if rest > 0 {
64 dbg!(format!(
65 "chunk items size mismatch: chunk={} item_size={}, items={}, rest={}",
66 String::from_utf8_lossy(&$chunk_header.magic),
67 item_size,
68 items,
69 rest
70 ));
71 }
72
73 let mut vec = Vec::<$type>::with_capacity(items);
74 vec.push(first);
75
76 for _ in 1..items {
77 vec.push($reader.wow_read()?);
78 }
79
80 $reader.seek_relative(rest as i64)?;
81
82 vec
83 }};
84}
85
86#[macro_export]
87macro_rules! v_read_chunk_items {
88 ($reader:ident, $version:ident, $chunk_header:ident, $type:ty) => {{
89 let first: $type = $reader.wow_read_versioned($version)?;
90 let item_size = first.wow_size();
91 let items = $chunk_header.bytes as usize / item_size;
92
93 let rest = $chunk_header.bytes as usize % item_size;
94 if rest > 0 {
95 dbg!(format!(
96 "chunk items size mismatch: chunk={} item_size={}, items={}, rest={}",
97 String::from_utf8_lossy(&$chunk_header.magic),
98 item_size,
99 items,
100 rest
101 ));
102 }
103
104 let mut vec = Vec::<$type>::with_capacity(items);
105 vec.push(first);
106
107 for _ in 1..items {
108 vec.push($reader.wow_read_versioned($version)?);
109 }
110
111 $reader.seek_relative(rest as i64)?;
112
113 vec
114 }};
115}
116
117pub fn magic_to_string(magic: &MagicStr) -> String {
118 String::from_utf8_lossy(magic).into()
119}
120
121pub fn magic_to_inverted_string(magic: &MagicStr) -> String {
122 String::from_utf8_lossy(magic).chars().rev().collect()
123}
124
125pub const fn string_to_magic(bytes_vec: &str) -> MagicStr {
126 if bytes_vec.len() != 4 {
127 panic!("magic must have len() == 4")
128 }
129 let ptr = bytes_vec.as_ptr();
130 unsafe { [*ptr, *(ptr.add(1)), *(ptr.add(2)), *(ptr.add(3))] }
131}
132
133pub const fn string_to_inverted_magic(bytes_vec: &str) -> MagicStr {
134 let res = string_to_magic(bytes_vec);
135 [res[3], res[2], res[1], res[0]]
136}