quake_util/bsp/
parser.rs

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}