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::dump`] method.

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

use oct::IntoOcts;

impl Builder {
	/// Dumps the WAD file directly into a byte buffer.
	///
	/// This method may be preferred over [`build`] as
	/// it does not reallocate
	///
	/// [`build`]: Self::build
	///
	/// # Panics
	///
	/// If the provided buffer cannot contain the entire
	/// WAD file, this function will panic. Thus,
	/// callers should use [`buf_size`] to correctly
	/// handle the buffer size.
	///
	/// [`buf_size`]: Self::buf_size
	pub fn dump(&self, buf: &mut [u8]) {
		let mut cursor = 0;

		let mut write = |data: &[u8]| {
			let slot_end = cursor + data.len();

			let slot = &mut buf[cursor..slot_end];
			slot.copy_from_slice(data);

			cursor += data.len();
		};

		let identification = self.inner.magic();

		// NOTE: This cast is guaranteed to be valid by
		// `push_lump`.
		let numlumps = self.inner.lump_count().try_into().unwrap();

		#[expect(clippy::cast_possible_truncation)]
		#[expect(clippy::cast_possible_wrap)]
		let infotableofs = (self.inner.tag().header_size() + self.data.len()) as i32;

		match self.inner.tag() {
			Tag::Wad => {
				let header = doom::wadinfo_t {
					identification,
					numlumps,
					infotableofs,
				};

				write(header.as_octs());
			}

			Tag::Wad2 => {
				let header = quake::wadinfo_t {
					identification,
					numlumps,
					infotableofs,
				};

				write(header.as_octs());
			}

			Tag::Wad3 => {
				let header = halflife::wadinfo_t {
					identification,
					numlumps,
					infotableofs,
				};

				write(header.as_octs());
			}
		};

		write(&self.data);

		write(self.inner.directory().inner_as_bytes());
	}
}