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 [`Tag`] enumeration.

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

use core::hint::unreachable_unchecked;
use oct::IntoOcts;

/// Denotes a WAD version.
///
/// To be used internally by unions that can contain
/// WAD, WAD2, and WAD3 data structures.
#[repr(u8)]
#[derive(
	Clone,
	Copy,
	Debug,
	Eq,
	PartialEq,
)]
pub(super) enum Tag {
	/// The DOOM WAD format.
	Wad = 1,

	/// The WAD2 format.
	Wad2 = 2,

	/// The WAD3 format.
	Wad3 = 3,
}

impl Tag {
	/// Determines the tag from file magic.
	///
	/// # Errors
	///
	/// If the provided magic does not match a known
	/// value for the WAD header's `identification`
	/// field, this constructor will yield an [`Err`]
	/// instance.
	#[allow(dead_code)]
	#[inline]
	pub fn from_magic(magic: [i8; 4]) -> Result<Self, DecodeError> {
		match magic.as_octs() {
			| b"IWAD"
			| b"DAWI"
			| b"PWAD"
			| b"DAWP"
			=> Ok(Self::Wad),

			| b"WAD2"
			| b"2DAW"
			=> Ok(Self::Wad2),

			b"WAD3" => Ok(Self::Wad3),

			_ => Err(DecodeError::unknown_magic(magic)),
		}
	}

	/// Determines the tag from file magic.
	///
	/// # Errors
	///
	/// If the provided magic does not match a known
	/// value for the WAD header's `identification`
	/// field, this constructor will yield an [`Err`]
	/// instance.
	#[inline]
	pub unsafe fn from_magic_unchecked(magic: [i8; 4]) -> Self {
		match magic.as_octs() {
			| b"IWAD"
			| b"DAWI"
			| b"PWAD"
			| b"DAWP"
			=> Self::Wad,

			| b"WAD2"
			| b"2DAW"
			=> Self::Wad2,

			b"WAD3" => Self::Wad3,

			_ => unsafe { unreachable_unchecked() },
		}
	}

	/// Determines the size of the header from the tag.
	#[inline]
	#[must_use]
	pub fn header_size(self) -> usize {
		match self {
			Self::Wad  => size_of::<doom::wadinfo_t>(),
			Self::Wad2 => size_of::<quake::wadinfo_t>(),
			Self::Wad3 => size_of::<halflife::wadinfo_t>(),
		}
	}

	/// Determines the size of a lump from the tag.
	#[inline]
	#[must_use]
	pub fn lump_size(self) -> usize {
		match self {
			Self::Wad  => size_of::<doom::filelump_t>(),
			Self::Wad2 => size_of::<quake::lumpinfo_t>(),
			Self::Wad3 => size_of::<halflife::lumpinfo_t>(),
		}
	}
}