1use std::fmt;
5use std::io::{Cursor, Read, Seek, SeekFrom, Write, Result};
6use byteorder::{LE, ReadBytesExt, WriteBytesExt};
7
8use crate::header::Header;
9use crate::Label;
10
11#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
13#[repr(u32)]
14pub enum FieldType {
15 Byte,
17 Char,
19 Word,
21 Short,
23 Dword,
25 Int,
27 Dword64,
29 Int64,
31 Float,
33 Double,
35 String,
45 ResRef,
47 LocString,
49 Void,
51 Struct,
53 List,
55}
56impl FieldType {
57 #[inline]
63 pub fn is_complex(&self) -> bool {
64 use self::FieldType::*;
65
66 match *self {
67 Dword64 | Int64 | Double | String | ResRef | LocString | Void => true,
68 _ => false
69 }
70 }
71 #[inline]
75 pub fn is_simple(&self) -> bool {
76 !self.is_complex() && *self != FieldType::Struct && *self != FieldType::List
77 }
78 #[inline]
80 fn from_u32(value: u32) -> Option<Self> {
81 use self::FieldType::*;
82
83 Some(match value {
84 0 => Byte,
85 1 => Char,
86 2 => Word,
87 3 => Short,
88 4 => Dword,
89 5 => Int,
90 6 => Dword64,
91 7 => Int64,
92 8 => Float,
93 9 => Double,
94 10 => String,
95 11 => ResRef,
96 12 => LocString,
97 13 => Void,
98 14 => Struct,
99 15 => List,
100 _ => return None,
101 })
102 }
103}
104
105#[cfg(nightly)]
106impl TryFrom<u32> for FieldType {
107 type Error = NoneError;
108
109 #[inline]
110 fn try_from(value: u32) -> Result<Self, Self::Error> {
111 Ok(self.from_u32(value)?)
112 }
113}
114
115pub struct Struct {
117 pub tag: u32,
120 pub offset: u32,
122 pub fields: u32,
124}
125impl Struct {
126 #[inline]
128 pub fn read<R: Read>(reader: &mut R) -> Result<Self> {
129 Ok(Struct {
130 tag: reader.read_u32::<LE>()?,
131 offset: reader.read_u32::<LE>()?,
132 fields: reader.read_u32::<LE>()?,
133 })
134 }
135 #[inline]
137 pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
138 writer.write_u32::<LE>(self.tag)?;
139 writer.write_u32::<LE>(self.offset)?;
140 writer.write_u32::<LE>(self.fields)?;
141 Ok(())
142 }
143}
144impl fmt::Debug for Struct {
145 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146 write!(f, "Struct {{ tag: {:?}, offset: {:?}, fields: {:?} }}", self.tag, self.offset, self.fields)
147 }
148}
149
150pub struct Field {
152 pub tag: u32,
154 pub label: u32,
156 pub data: [u8; 4],
161}
162impl Field {
163 #[inline]
165 pub fn read<R: Read>(reader: &mut R) -> Result<Self> {
166 let tag = reader.read_u32::<LE>()?;
167 let label = reader.read_u32::<LE>()?;
168 let mut data = [0u8; 4];
169 reader.read_exact(&mut data)?;
170
171 Ok(Field { tag, label, data })
172 }
173 #[inline]
175 pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
176 writer.write_u32::<LE>(self.tag as u32)?;
177 writer.write_u32::<LE>(self.label)?;
178 writer.write_all(&self.data)?;
179 Ok(())
180 }
181}
182impl fmt::Debug for Field {
183 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
184 write!(f, "Field {{ tag: {:?}, label: {:?}, data: {:?} }}", self.tag, self.label, self.data)
185 }
186}
187
188struct FieldData<'a>(&'a [u8]);
192impl<'a> fmt::Debug for FieldData<'a> {
193 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
194 write!(f, "{:?}", self.0)
195 }
196}
197#[derive(Debug)]
199struct DebugFieldData<'a> {
200 by_field: Vec<FieldData<'a>>,
202 raw: &'a [u8],
204}
205
206struct FieldIndex<'a>(&'a [u32]);
210impl<'a> fmt::Debug for FieldIndex<'a> {
211 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
212 write!(f, "{:?}", self.0)
213 }
214}
215#[derive(Debug)]
217struct DebugFieldIndex<'a> {
218 by_struct: Vec<FieldIndex<'a>>,
220 raw: &'a [u32],
222}
223
224struct ListIndex<'a>(&'a [u32]);
228impl<'a> fmt::Debug for ListIndex<'a> {
229 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
230 write!(f, "{:?}", self.0)
231 }
232}
233#[derive(Debug)]
235struct DebugListIndex<'a> {
236 by_list: Vec<ListIndex<'a>>,
238 raw: &'a [u32],
240}
241
242pub struct Gff {
244 pub header: Header,
247 pub structs: Vec<Struct>,
253 pub fields: Vec<Field>,
258 pub labels: Vec<Label>,
262 pub field_data: Vec<u8>,
265 pub field_indices: Vec<u32>,
270 pub list_indices: Vec<u32>,
277}
278
279macro_rules! read_exact {
280 ($reader:expr, $section:expr, $type:ident) => ({
281 $reader.seek(SeekFrom::Start($section.offset as u64))?;
282 let mut vec = Vec::with_capacity($section.count as usize);
283 for _ in 0..$section.count {
284 vec.push($type::read($reader)?);
285 }
286 vec
287 });
288}
289
290macro_rules! read_into {
291 ($reader:expr, $section:expr) => ({
292 $reader.seek(SeekFrom::Start($section.offset as u64))?;
293 let mut vec = Vec::with_capacity($section.count as usize);
294 unsafe { vec.set_len(($section.count / 4) as usize); }
295 $reader.read_u32_into::<LE>(&mut vec[..])?;
296 vec
297 });
298}
299
300macro_rules! write_all {
301 ($writer:expr, $list:expr) => (
302 for elem in &$list {
303 elem.write($writer)?;
304 }
305 );
306 ($writer:expr, $list:expr, LE) => (
307 for elem in &$list {
308 $writer.write_u32::<LE>(*elem)?;
309 }
310 );
311}
312
313impl Gff {
314 pub fn read<R: Read + Seek>(reader: &mut R) -> Result<Gff> {
316 let header = Header::read(reader)?;
317 let structs = read_exact!(reader, header.structs, Struct);
318 let fields = read_exact!(reader, header.fields , Field);
319
320 reader.seek(SeekFrom::Start(header.labels.offset as u64))?;
321 let mut labels = Vec::with_capacity(header.labels.count as usize);
322 for _ in 0..header.labels.count {
323 let mut label = [0u8; 16];
324 reader.read_exact(&mut label)?;
325 labels.push(label.into());
326 }
327
328 reader.seek(SeekFrom::Start(header.field_data.offset as u64))?;
329 let mut field_data = Vec::with_capacity(header.field_data.count as usize);
330 unsafe { field_data.set_len(header.field_data.count as usize); }
331 reader.read_exact(&mut field_data[..])?;
332
333 let field_indices = read_into!(reader, header.field_indices);
334 let list_indices = read_into!(reader, header.list_indices);
335
336 Ok(Gff { header, structs, fields, labels, field_data, field_indices, list_indices })
337 }
338 pub fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
340 self.header.write(writer)?;
341 write_all!(writer, self.structs);
342 write_all!(writer, self.fields);
343 for label in &self.labels {
344 writer.write_all(label.as_ref())?;
345 }
346 writer.write_all(&self.field_data)?;
347 write_all!(writer, self.field_indices, LE);
348 write_all!(writer, self.list_indices, LE);
349 Ok(())
350 }
351
352 fn split_data<'a>(data: &'a [u8], offsets: &[u32]) -> DebugFieldData<'a> {
356 let it1 = offsets.iter();
357 let it2 = offsets.iter().skip(1);
358
359 let mut vec = Vec::with_capacity(offsets.len() - 1);
360 for (s, e) in it1.zip(it2) {
361 vec.push(FieldData(&data[*s as usize .. *e as usize]));
362 }
363 DebugFieldData { by_field: vec, raw: data }
364 }
365 fn split_fields<'a>(data: &'a [u32], offsets: &[(u32, u32)]) -> DebugFieldIndex<'a> {
369 let mut vec = Vec::with_capacity(offsets.len() - 1);
370 for (s, cnt) in offsets {
371 vec.push(FieldIndex(&data[*s as usize .. (*s + cnt) as usize]));
372 }
373 DebugFieldIndex { by_struct: vec, raw: data }
374 }
375 fn split_lists<'a>(data: &'a [u32]) -> DebugListIndex<'a> {
378 let mut vec = Vec::new();
379 let mut it = data.iter().enumerate();
380 while let Some((i, cnt)) = it.next() {
381 let from = i + 1;
382 let to = from + *cnt as usize;
383 vec.push(ListIndex(&data[from..to]));
384 while let Some((j, _)) = it.next() {
385 if j >= to { break; }
386 }
387 }
388 DebugListIndex { by_list: vec, raw: data }
389 }
390}
391
392impl fmt::Debug for Gff {
393 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
394 let data_offsets: Vec<_> = self.fields.iter()
395 .filter(|f| FieldType::from_u32(f.tag).as_ref().map(FieldType::is_complex).unwrap_or(false))
397 .map(|f| Cursor::new(f.data).read_u32::<LE>().unwrap())
398 .collect();
399 let field_offsets: Vec<_> = self.structs.iter()
400 .filter(|s| s.fields > 1)
402 .map(|s| (s.offset / 4, s.fields))
404 .collect();
405
406 f.debug_struct("Gff")
407 .field("header", &self.header)
408 .field("structs", &self.structs)
409 .field("fields", &self.fields)
410 .field("labels", &self.labels)
411 .field("field_data", &Self::split_data(&self.field_data, &data_offsets))
412 .field("field_indices", &Self::split_fields(&self.field_indices, &field_offsets))
413 .field("list_indices", &Self::split_lists(&self.list_indices))
414 .finish()
415 }
416}