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

#![cfg(feature = "alloc")]

mod test;

mod dump;
mod flatten;
mod inner;
mod with_lump;

use inner::Inner;

use crate::wad::Wad;

use alloc::vec;
use alloc::boxed::Box;
use alloc::vec::Vec;

/// A WAD file encode.
#[must_use = "constructing `Builder` does nothing in and of itself"]
#[derive(Clone, Debug)]
pub struct Builder {
	/// The combined lump data.
	data: Vec<u8>,

	/// Conditional WAD data.
	inner: Inner,
}

impl Builder {
	/// Constructs a new internal WAD encoder.
	pub fn new_iwad() -> Self {
		Self {
			data: Vec::new(),

			inner: Inner::Wad {
				is_pwad:   false,
				directory: Vec::new(),
			},
		}
	}

	/// Constructs a new patch WAD encoder.
	pub fn new_pwad() -> Self {
		Self {
			data: Vec::new(),

			inner: Inner::Wad {
				is_pwad:   true,
				directory: Vec::new(),
			},
		}
	}

	/// Constructs a new WAD2 encoder.
	pub fn new_wad2() -> Self {
		Self {
			data: Vec::new(),

			inner: Inner::Wad2 {
				directory: Vec::new(),
			},
		}
	}

	/// Constructs a new WAD3 encoder.
	pub fn new_wad3() -> Self {
		Self {
			data: Vec::new(),

			inner: Inner::Wad3 {
				directory: Vec::new(),
			},
		}
	}

	/// Calculates the minimum buffer size usable for the WAD file.
	#[must_use]
	pub fn buf_size(&self) -> usize {
		let mut size = 0;

		size += self.inner.tag().header_size();
		size += size_of_val(self.data.as_slice());

		match self.inner {
			Inner::Wad { ref directory, .. } => {
				size += size_of_val(directory.as_slice());
			}

			Inner::Wad2 { ref directory, .. } => {
				size += size_of_val(directory.as_slice());
			}

			Inner::Wad3 { ref directory, .. } => {
				size += size_of_val(directory.as_slice());
			}
		}

		size
	}

	/// Builds the WAD file.
	///
	/// To avoid extraneous allocations, users should
	/// consider using the [`dump`] method instead.
	///
	/// [`dump`]: Self::dump
	pub fn build(&self) -> Box<Wad> {
		let mut buf = vec![0; self.buf_size()].into_boxed_slice();
		self.dump(&mut buf);

		// SAFETY: `with_lump` guarantees validity.
		unsafe { Wad::from_boxed_bytes_unchecked(buf) }
	}
}

impl Drop for Builder {
	#[inline]
	fn drop(&mut self) {}
}