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

use crate::wad::{Lump, RawLumpSliceIter, Wad};

use core::iter::FusedIterator;
use oct::IntoOcts;

/// An iterator over WAD lumps.
#[must_use = "iterators are lasy"]
#[derive(Clone, Debug, Default)]
pub struct Lumps<'a> {
	/// The raw file buffer.
	buf: &'a [u8],

	/// The WAD directory.
	directory: RawLumpSliceIter<'a>,
}

impl<'a> Lumps<'a> {
	/// Constructs a new lump iterator.
	pub(in super) fn new(wad: &'a Wad) -> Self {
		let buf       = wad.as_bytes();
		let directory = wad.directory().iter();

		Self { buf, directory }
	}

	/// Counts the combined data lengths of all lumps.
	#[must_use]
	pub fn count_data_len(self) -> usize {
		self.map(|Lump { data, .. }| data.len()).sum()
	}

	/// Counts the amount of patches for the specified
	/// lump name.
	///
	/// Note that also the first instance of the lump
	/// counts as a patch.
	#[must_use]
	pub fn count_patches(self, name: &str) -> usize {
		self.filter(|l| l.raw_name().as_octs() == name.as_bytes()).count()
	}
}

impl DoubleEndedIterator for Lumps<'_> {
	fn next_back(&mut self) -> Option<Self::Item> {
		let raw = self.directory.next_back()?;

		let lump = Lump::from_raw(self.buf, raw);
		Some(lump)
	}
}

impl ExactSizeIterator for Lumps<'_> {}

impl FusedIterator for Lumps<'_> {}

impl<'a> Iterator for Lumps<'a> {
	type Item = Lump<'a>;

	fn next(&mut self) -> Option<Self::Item> {
		let raw = self.directory.next()?;

		let lump = Lump::from_raw(self.buf, raw);
		Some(lump)
	}

	#[inline]
	fn size_hint(&self) -> (usize, Option<usize>) {
		self.directory.size_hint()
	}
}