goldforge 0.8.1

Library for handling file formats used by GoldSrc and related engines.
Documentation
// Copyright 2025-2026 Gabriel Bjørnager Jensen.
//
// This Source Code Form is subject to the terms of
// the Mozilla Public License, v. 2.0. If a copy of
// the MPL was not distributed with this file, you
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.

//! The [`RawHeader`] type.

use crate::wad::Tag;
use crate::wad::ffi::{doom, halflife, quake};

use core::fmt::{self, Debug, Formatter};

/// An immutable, fat reference to a raw header.
///
/// Fundamentally, this type reference either a WAD,
/// WAD2, or a WAD3 header, allowing the abstraction
/// of these. Do note that these three formats have
/// the same representation, so this is a bit of an
/// unncessary abstraction.
#[derive(Clone, Copy)]
pub(super) struct RawHeader<'a>(Inner<'a>);

impl<'a> RawHeader<'a> {

	/// Retrieves the `identification` field.
	#[inline(always)]
	#[must_use]
	pub fn identification(self) -> [i8; 4] {
		#[expect(clippy::match_same_arms)]
		match self.0 {
			Inner::Wad(&doom::wadinfo_t { identification, .. })      => identification,
			Inner::Wad2(&quake::wadinfo_t { identification, .. })    => identification,
			Inner::Wad3(&halflife::wadinfo_t { identification, .. }) => identification,
		}
	}

	/// Retrieves the `numlumps` field.
	#[inline(always)]
	#[must_use]
	pub fn numlumps(self) -> i32 {
		#[expect(clippy::match_same_arms)]
		match self.0 {
			Inner::Wad(&doom::wadinfo_t { numlumps, .. })      => numlumps,
			Inner::Wad2(&quake::wadinfo_t { numlumps, .. })    => numlumps,
			Inner::Wad3(&halflife::wadinfo_t { numlumps, .. }) => numlumps,
		}
	}

	/// Retrieves the `infotableofs` field.
	#[inline(always)]
	#[must_use]
	pub fn infotableofs(self) -> i32 {
		#[expect(clippy::match_same_arms)]
		match self.0 {
			Inner::Wad(&doom::wadinfo_t { infotableofs, .. })      => infotableofs,
			Inner::Wad2(&quake::wadinfo_t { infotableofs, .. })    => infotableofs,
			Inner::Wad3(&halflife::wadinfo_t { infotableofs, .. }) => infotableofs,
		}
	}
}

impl Debug for RawHeader<'_> {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		Debug::fmt(&self.0, f)
	}
}

impl<'a> From<&'a doom::wadinfo_t> for RawHeader<'a> {
	#[inline(always)]
	fn from(value: &'a doom::wadinfo_t) -> Self {
		let inner = Inner::Wad(value);
		Self(inner)
	}
}

impl<'a> From<&'a halflife::wadinfo_t> for RawHeader<'a> {
	#[inline(always)]
	fn from(value: &'a halflife::wadinfo_t) -> Self {
		let inner = Inner::Wad3(value);
		Self(inner)
	}
}

impl<'a> From<&'a quake::wadinfo_t> for RawHeader<'a> {
	#[inline(always)]
	fn from(value: &'a quake::wadinfo_t) -> Self {
		let inner = Inner::Wad2(value);
		Self(inner)
	}
}

/// See [`RawHeader`].
#[repr(i8)]
#[derive(Clone, Copy)]
enum Inner<'a> {
	/// A DOOM WAD header.
	Wad(&'a doom::wadinfo_t) = Tag::Wad as i8,

	/// A WAD2 header.
	Wad2(&'a quake::wadinfo_t) = Tag::Wad2 as i8,

	/// A WAD3 header.
	Wad3(&'a halflife::wadinfo_t) = Tag::Wad3 as i8,
}

impl Debug for Inner<'_> {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		match *self {
			Self::Wad( ref inner) => Debug::fmt(inner, f),
			Self::Wad2(ref inner) => Debug::fmt(inner, f),
			Self::Wad3(ref inner) => Debug::fmt(inner, f),
		}
	}
}