1use super::{Entry, EntryOffset, Head};
2use crate::{BinParseError, BinParseResult, TextParseError};
3use io::{Read, Seek, SeekFrom};
4use std::io;
5use std::mem::size_of;
6use std::string::String;
7
8use crate::qmap;
9use qmap::QuakeMap;
10
11#[derive(Debug)]
12pub struct Parser<'a, Reader: Seek + Read> {
13 cursor: &'a mut Reader,
14 start: u64,
15 header: Head,
16}
17
18impl<'a, Reader: Seek + Read> Parser<'a, Reader> {
19 pub fn new(cursor: &'a mut Reader) -> BinParseResult<Self> {
20 let start = cursor.stream_position()?;
21 let mut header_bytes = [0u8; size_of::<Head>()];
22 cursor.read_exact(&mut header_bytes[..])?;
23 let header = header_bytes.try_into()?;
24
25 Ok(Self {
26 cursor,
27 start,
28 header,
29 })
30 }
31
32 pub fn version(&self) -> u32 {
33 self.header.version()
34 }
35
36 pub fn lump_reader(
37 &mut self,
38 entry_offset: EntryOffset,
39 ) -> BinParseResult<std::io::Take<&mut Reader>> {
40 let Entry { offset, length } = self.header.entry(entry_offset);
41 let length = length.into();
42
43 let abs_offset = self
44 .start
45 .checked_add(offset.into())
46 .ok_or(BinParseError::Parse(String::from("Bad offset")))?;
47
48 self.cursor.seek(SeekFrom::Start(abs_offset))?;
49
50 Ok(self.cursor.take(length))
51 }
52
53 pub fn lump_empty(&self, offset: EntryOffset) -> bool {
54 let length = self.header.entry(offset).length;
55 length == 0
56 }
57
58 pub fn parse_entities(&mut self) -> BinParseResult<QuakeMap> {
59 let lump = self.lump_reader(EntryOffset::Entities)?;
60 let byte_iter = lump.bytes().take_while(|b| match b {
61 Ok(byte) => byte != &0,
62 _ => true,
63 });
64
65 qmap::parse(&mut IterReader::new(byte_iter)).map_err(|e| match e {
66 TextParseError::Io(ioe) => ioe.into(),
67 err => BinParseError::Parse(format!("{err}")),
68 })
69 }
70}
71
72struct IterReader<I>
73where
74 I: Iterator<Item = Result<u8, io::Error>>,
75{
76 iter: I,
77}
78
79impl<I> IterReader<I>
80where
81 I: Iterator<Item = Result<u8, io::Error>>,
82{
83 pub fn new(iter: I) -> Self {
84 IterReader { iter }
85 }
86}
87
88impl<I> Read for IterReader<I>
89where
90 I: Iterator<Item = Result<u8, io::Error>>,
91{
92 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
93 let count = buf.len();
94 let mut i = 0;
95
96 while i < count {
97 let b = self.iter.next();
98
99 match b {
100 None => {
101 return Ok(i);
102 }
103 Some(Err(e)) => {
104 return Err(e);
105 }
106 Some(Ok(byte)) => {
107 buf[i] = byte;
108 }
109 }
110
111 i += 1;
112 }
113
114 Ok(i)
115 }
116}