looklook 0.6.0

Descriptive signal synthesiser.
// Copyright 2026 Gabriel Bjørnager Jensen.
//
// This file is part of LOOKLOOK.
//
// LOOKLOOK is free software: you can redistribute
// it and/or modify it under the terms of the GNU
// Affero General Public License as published by
// the Free Software Foundation, either version 3
// of the License, or (at your option) any later
// version.
//
// LOOKLOOK is distributed in the hope that it will
// be useful, but WITHOUT ANY WARRANTY; without
// even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Af-
// fero General Public License along with LOOKLOOK.
// If not, see <https://www.gnu.org/licenses/>.

//! The [`config::Builder`] type.
//!
//! [`config::Builder`]: Builder

use crate::config::{Config, Format};

/// A config builder.
#[must_use]
#[derive(Debug)]
#[derive_const(Clone, Default)]
pub struct Builder {
	/// The sampling depth.
	pub sample_depth: Option<u32>,

	/// The amount of channels.
	pub channel_count: Option<u32>,

	/// The frame height.
	pub width: Option<u32>,

	/// The frame height.
	pub height: Option<u32>,

	/// The total count of frames.
	pub frame_count: Option<u32>,

	/// The frame rate.
	pub frame_rate: Option<u32>,

	/// The output format.
	pub format: Option<Format>,
}

impl Builder {
	/// Constructs a new config builder.
	#[inline]
	pub const fn new() -> Self {
		Default::default()
	}

	/// Specifies the sampling depth.
	///
	/// # Panics
	///
	/// This method will panic if the depth is already
	/// specified.
	#[inline]
	pub const fn sample_depth(mut self, sample_depth: u32) -> Self {
		assert!(
			self.sample_depth.is_none(),
			"sampling depth is already specified",
		);

		self.sample_depth = Some(sample_depth);
		self
	}

	/// Specifies the channel count.
	///
	/// # Panics
	///
	/// This method will panic if the channel count is
	/// already specified.
	#[inline]
	pub const fn channel_count(mut self, channel_count: u32) -> Self {
		assert!(
			self.channel_count.is_none(),
			"channel count is already specified",
		);

		self.channel_count = Some(channel_count);
		self
	}

	/// Specifies the frame width.
	///
	/// For non-video renders, this value should be `1`.
	///
	/// # Panics
	///
	/// This method will panic if the frame width is
	/// already specified.
	#[inline]
	pub const fn width(mut self, width: u32) -> Self {
		assert!(
			self.width.is_none(),
			"frame width is already specified",
		);

		self.width = Some(width);
		self
	}

	/// Specifies the frame height.
	///
	/// For non-video renders, this value should be `1`.
	///
	/// # Panics
	///
	/// This method will panic if the frame height is
	/// already specified.
	#[inline]
	pub const fn height(mut self, height: u32) -> Self {
		assert!(
			self.height.is_none(),
			"frame height is already specified",
		);

		self.height = Some(height);
		self
	}

	/// Specifies the render frame count.
	///
	/// The provided value is measured in count of
	/// frames. For non-video renders, this should
	/// simply be the total sample count.
	///
	/// # Panics
	///
	/// This method will panic if the frame count is
	/// already specified.
	#[inline]
	pub const fn frame_count(mut self, frame_count: u32) -> Self {
		assert!(
			self.frame_count.is_none(),
			"frame_count is already specified",
		);

		self.frame_count = Some(frame_count);
		self
	}

	/// Specifies the frame rate.
	///
	/// # Panics
	///
	/// This method will panic if the frame rate is
	/// already specified.
	#[inline]
	pub const fn frame_rate(mut self, frame_rate: u32) -> Self {
		assert!(
			self.frame_rate.is_none(),
			"frame rate is already specified",
		);

		self.frame_rate = Some(frame_rate);
		self
	}

	/// Specifies the output format.
	///
	/// # Panics
	///
	/// This method will panic if the format is already
	/// specified.
	#[inline]
	pub const fn format(mut self, format: Format) -> Self {
		assert!(
			self.format.is_none(),
			"output format is already specified",
		);

		self.format = Some(format);
		self
	}

	/// Builds the config.
	#[inline]
	#[must_use]
	pub fn build(self) -> Config {
		Config::from_builder(self)
	}
}