use std::collections::HashMap;
use std::hint::cold_path;
use crate::prelude::*;
use crate::wad::elem::texture_page_item::TexturePageItem;
use crate::wad::parse::reader::DataReader;
use crate::wad::reference::GMRef;
impl DataReader<'_> {
pub fn read_gm_string(&mut self) -> Result<GMRef<String>> {
let occurrence_position = self.read_u32()?;
if occurrence_position == 0 {
return Ok(GMRef::none());
}
let map: &HashMap<u32, GMRef<String>> = &self.string_occurrences;
if let Some(&strg_ref) = map.get(&occurrence_position) {
return Ok(strg_ref);
}
cold_path();
Err(err!(
"Could not read string with occurrence position {} at pointer position {} because it \
doesn't exist in the occurrence map with {} items",
occurrence_position,
self.cur_pos - 4,
map.len(),
))
}
pub fn read_gm_texture(&mut self) -> Result<GMRef<TexturePageItem>> {
let occurrence_position = self.read_u32()?;
if occurrence_position == 0 {
return Ok(GMRef::none());
}
let map: &HashMap<u32, GMRef<TexturePageItem>> = &self.texture_page_item_occurrences;
if let Some(&tpag_ref) = map.get(&occurrence_position) {
return Ok(tpag_ref);
}
cold_path();
Err(err!(
"Could not read texture page item with occurrence position {} at pointer position {} \
because it doesn't exist in the occurrence map with {} items",
occurrence_position,
self.cur_pos - 4,
map.len(),
))
}
pub fn read_resource_by_id<T>(&mut self) -> Result<GMRef<T>> {
let number = self.read_i32()?;
if number == -1 {
return Ok(GMRef::none());
}
check_resource_limit(number as u32).ctx("parsing resource by id")?;
Ok(GMRef::new(number))
}
}
fn check_resource_limit(number: u32) -> Result<()> {
const FAILSAFE_COUNT: u32 = 500_000;
if number < FAILSAFE_COUNT {
return Ok(());
}
let signed = number as i32;
let comment = if signed < 0 {
format!(" (presumably {signed} as signed integer)")
} else {
String::new()
};
bail!("Resource ID {number}{comment} exceeds failsafe limit of {FAILSAFE_COUNT}");
}