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 [`RawLumpSliceIter`] iterator type.

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

use core::iter::FusedIterator;
use core::slice;

/// An immutable iterator to a raw lump slice.
///
/// See also [`RawLumpSlice`].
///
/// [`RawLumpSlice`]: crate::wad::RawLumpSlice
#[derive(Clone, Debug, Default)]
#[must_use]
pub(super) struct RawLumpSliceIter<'a>(Inner<'a>);

impl<'a> From<slice::Iter<'a, doom::filelump_t>> for RawLumpSliceIter<'a> {
	#[inline(always)]
	fn from(value: slice::Iter<'a, doom::filelump_t>) -> Self {
		let inner = Inner::Wad(value);
		Self(inner)
	}
}

impl<'a> From<slice::Iter<'a, halflife::lumpinfo_t>> for RawLumpSliceIter<'a> {
	#[inline(always)]
	fn from(value: slice::Iter<'a, halflife::lumpinfo_t>) -> Self {
		let inner = Inner::Wad3(value);
		Self(inner)
	}
}

impl<'a> From<slice::Iter<'a, quake::lumpinfo_t>> for RawLumpSliceIter<'a> {
	#[inline(always)]
	fn from(value: slice::Iter<'a, quake::lumpinfo_t>) -> Self {
		let inner = Inner::Wad2(value);
		Self(inner)
	}
}

impl DoubleEndedIterator for RawLumpSliceIter<'_> {
	fn next_back(&mut self) -> Option<Self::Item> {
		match self.0 {
			Inner::Wad(ref mut iter) => {
				iter.next_back().map(Into::into)
			}

			Inner::Wad2(ref mut iter) => {
				iter.next_back().map(Into::into)
			}

			Inner::Wad3(ref mut iter) => {
				iter.next_back().map(Into::into)
			}
		}
	}
}

impl ExactSizeIterator for RawLumpSliceIter<'_> {}

impl FusedIterator for RawLumpSliceIter<'_> {}

impl<'a> Iterator for RawLumpSliceIter<'a> {
	type Item = RawLump<'a>;

	#[inline]
	fn next(&mut self) -> Option<Self::Item> {
		match self.0 {
			Inner::Wad(ref mut iter) => {
				iter.next().map(Into::into)
			}

			Inner::Wad2(ref mut iter) => {
				iter.next().map(Into::into)
			}

			Inner::Wad3(ref mut iter) => {
				iter.next().map(Into::into)
			}
		}
	}

	#[inline]
	fn size_hint(&self) -> (usize, Option<usize>) {
		match self.0 {
			Inner::Wad(ref iter) => {
				iter.size_hint()
			}

			Inner::Wad2(ref iter) => {
				iter.size_hint()
			}

			Inner::Wad3(ref iter) => {
				iter.size_hint()
			}
		}
	}
}

/// See [`RawLumpSliceIter`].
#[repr(u8)]
#[derive(Clone, Debug)]
enum Inner<'a> {
	/// A DOOM WAD lump slice iterator.
	Wad(slice::Iter<'a, doom::filelump_t>) = Tag::Wad as u8,

	/// A WAD2 lump slice iterator.
	Wad2(slice::Iter<'a, quake::lumpinfo_t>) = Tag::Wad2 as u8,

	/// A WAD3 lump slice iterator.
	Wad3(slice::Iter<'a, halflife::lumpinfo_t>) = Tag::Wad3 as u8,
}

impl Default for Inner<'_> {
	#[inline]
	fn default() -> Self {
		Self::Wad(Default::default())
	}
}