serde_gff/index.rs
1//! Содержит описание структур-индексов различных данных в GFF файле
2
3use std::ops::Add;
4
5use crate::header::Header;
6
7/// Типаж, реализуемый специальными структурами, хранящими индексы на записи в GFF-файле,
8/// позволяющий преобразовать их в реальное смещение для чтения информации из файла.
9pub trait Index {
10 /// Получает смещение от начала GFF-файла, в котором находятся индексируемые данные
11 fn offset(&self, header: &Header) -> u64;
12}
13
14/// Макрос для объявления типизированной обертки над числом (или числами),
15/// представляющем(ими) индекс одной из структур данных в файле.
16///
17/// # Параметры 1
18/// - `$name`: Имя генерируемой структуры.
19/// - `$field`: Имя поля в заголовке, хранящее базовое смещение для структур,
20/// к которым производится доступ по данному индексу
21///
22/// # Параметры 2
23/// - `$name`: Имя генерируемой структуры. Структура реализует типаж `From` для
24/// конструирования из `u32`
25/// - `$field`: Имя поля в заголовке, хранящее базовое смещение для структур,
26/// к которым производится доступ по данному индексу
27/// - `$multiplier`: множитель для индекса, переводящий его в смещение в байтах
28macro_rules! index {
29 ($(#[$attrs:meta])* $name:ident, $field:ident) => (
30 $(#[$attrs])*
31 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
32 pub struct $name(pub(crate) u32, pub(crate) u32);
33
34 impl Index for $name {
35 #[inline]
36 fn offset(&self, header: &Header) -> u64 {
37 let start = header.$field.offset as u64;
38 let offset = self.0 as u64 + self.1 as u64 * 4;
39
40 start + offset
41 }
42 }
43 impl Add<u32> for $name {
44 type Output = Self;
45
46 fn add(self, rhs: u32) -> Self {
47 $name(self.0, self.1 + rhs)
48 }
49 }
50 );
51
52 ($(#[$attrs:meta])* $name:ident, $field:ident, $multiplier:expr) => (
53 $(#[$attrs])*
54 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
55 pub struct $name(pub(crate) u32);
56 impl Index for $name {
57 #[inline]
58 fn offset(&self, header: &Header) -> u64 {
59 let start = header.$field.offset as u64;
60 let offset = self.0 as u64 * $multiplier;
61
62 start + offset
63 }
64 }
65 impl From<u32> for $name {
66 fn from(value: u32) -> Self { $name(value) }
67 }
68 );
69}
70
71index!(
72 /// Номер структуры в файле
73 StructIndex, structs, 3*4
74);
75index!(
76 /// Номер поля в массиве полей GFF файла. Каждая структура в файле состоит из набора полей,
77 /// на которые ссылается по этим индексам.
78 FieldIndex, fields, 3*4
79);
80index!(
81 /// Номер метки для поля в общем массиве меток, хранящихся в GFF файле
82 LabelIndex, labels, 16
83);
84index!(
85 /// Двойной индекс -- номера списка с полями структуры структуры и номер поля в этом списке.
86 /// Используется для указания на поля структуры, когда структура содержит несколько полей.
87 FieldIndicesIndex, field_indices
88);
89index!(
90 /// Двойной индекс -- номера списка элементов и номер элемента в этом списке.
91 /// Используется для представления списков.
92 ListIndicesIndex, list_indices
93);
94
95index!(
96 /// Смещение в файле, по которому расположены данные поля типа `Dword64`
97 U64Index, field_data, 1
98);
99index!(
100 /// Смещение в файле, по которому расположены данные поля типа `Int64`
101 I64Index, field_data, 1
102);
103index!(
104 /// Смещение в файле, по которому расположены данные поля типа `Double64`
105 F64Index, field_data, 1
106);
107index!(
108 /// Смещение в файле, по которому расположены данные поля типа `String`
109 StringIndex, field_data, 1
110);
111index!(
112 /// Смещение в файле, по которому расположены данные поля типа `ResRef`
113 ResRefIndex, field_data, 1
114);
115index!(
116 /// Смещение в файле, по которому расположены данные поля типа `LocString`
117 LocStringIndex, field_data, 1
118);
119index!(
120 /// Смещение в файле, по которому расположены данные поля типа `Void`
121 BinaryIndex, field_data, 1
122);