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

use crate::config::FormatFromStrError;

use std::fmt::{self, Display, Formatter};
use std::str::FromStr;

/// An audio format.
#[non_exhaustive]
#[repr(u8)]
#[derive(Copy, Debug)]
#[derive_const(Clone, Default, Eq, PartialEq)]
pub enum Format {
	/// The [Portable Network Graphics](PNG) format.
	///
	/// [PNG]: <https://en.wikipedia.org/wiki/PNG>
	///
	/// File extension: `png`
	Png,

	/// Our own, raw format.
	///
	/// File extension: `zlk`
	#[default]
	Raw,

	/// The [Waveform Audio File Format](WAVE).
	///
	/// [WAVE]: <https://en.wikipedia.org/wiki/WAV>
	///
	/// File extension: `wav`
	Wave,

	/// The [WebP] format.
	///
	/// [WebP]: <https://en.wikipedia.org/wiki/WebP>
	///
	/// File extension: `webp`
	Webp,
}

impl Format {
	/// Retrieves an identifier for the format.
	#[inline]
	#[must_use]
	pub const fn as_str(self) -> &'static str {
		match self {
			Self::Png  => "png",
			Self::Raw  => "raw",
			Self::Wave => "wave",
			Self::Webp => "webp",
		}
	}

	/// Retrieves the file extension for the format.
	#[inline]
	#[must_use]
	pub const fn file_extension(self) -> &'static str {
		match self {
			Self::Png  => ".png",
			Self::Raw  => ".zlk",
			Self::Wave => ".wave",
			Self::Webp => ".webp",
		}
	}
}

impl Display for Format {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		f.write_str(self.as_str())
	}
}

const impl FromStr for Format {
	type Err = FormatFromStrError;

	fn from_str(s: &str) -> Result<Self, Self::Err> {
		if s.eq_ignore_ascii_case("png") {
			return Ok(Self::Png);
		}

		if s.eq_ignore_ascii_case("raw") {
			return Ok(Self::Raw);
		}

		if s.eq_ignore_ascii_case("wave") {
			return Ok(Self::Wave);
		}

		if s.eq_ignore_ascii_case("webp") {
			return Ok(Self::Webp);
		}

		Err(FormatFromStrError(()))
	}
}