wow_alchemy_data/
utils.rs

1use 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}