Skip to main content

pop_common/
build.rs

1// SPDX-License-Identifier: GPL-3.0
2
3use serde::Serialize;
4use std::{
5	fmt,
6	path::{Path, PathBuf},
7};
8use strum::{EnumMessage as _, VariantArray as _};
9use strum_macros::{AsRefStr, EnumMessage, EnumString, VariantArray};
10
11/// Enum representing a build profile.
12#[derive(
13	AsRefStr,
14	Copy,
15	Clone,
16	Default,
17	Debug,
18	EnumString,
19	EnumMessage,
20	VariantArray,
21	Eq,
22	PartialEq,
23	Serialize,
24	clap::ValueEnum,
25)]
26pub enum Profile {
27	/// Debug profile, optimized for debugging.
28	#[strum(serialize = "debug", message = "Debug", detailed_message = "Optimized for debugging.")]
29	Debug,
30	/// Release profile, optimized without any debugging functionality.
31	#[default]
32	#[strum(
33		serialize = "release",
34		message = "Release",
35		detailed_message = "Optimized without any debugging functionality."
36	)]
37	Release,
38	/// Production profile, optimized for ultimate performance.
39	#[strum(
40		serialize = "production",
41		message = "Production",
42		detailed_message = "Optimized for ultimate performance."
43	)]
44	Production,
45}
46
47impl Profile {
48	/// Returns the corresponding path to the target directory.
49	pub fn target_directory(&self, path: &Path) -> PathBuf {
50		match self {
51			Profile::Release => path.join("target/release"),
52			Profile::Debug => path.join("target/debug"),
53			Profile::Production => path.join("target/production"),
54		}
55	}
56
57	/// Returns the variants of the enum.
58	pub fn get_variants() -> Vec<(String, String)> {
59		Profile::VARIANTS
60			.iter()
61			.map(|profile| {
62				(
63					profile.get_message().unwrap_or(profile.as_ref()).to_string(),
64					profile.get_detailed_message().unwrap_or_default().to_string(),
65				)
66			})
67			.collect()
68	}
69}
70
71impl From<Profile> for bool {
72	fn from(value: Profile) -> Self {
73		value != Profile::Debug
74	}
75}
76
77impl From<bool> for Profile {
78	fn from(value: bool) -> Self {
79		if value { Profile::Release } else { Profile::Debug }
80	}
81}
82
83impl fmt::Display for Profile {
84	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85		match self {
86			Self::Debug => write!(f, "debug"),
87			Self::Release => write!(f, "release"),
88			Self::Production => write!(f, "production"),
89		}
90	}
91}
92
93#[cfg(test)]
94mod tests {
95	use super::*;
96	use std::path::Path;
97	use strum::EnumMessage;
98
99	#[test]
100	fn profile_from_string() {
101		assert_eq!("debug".parse::<Profile>().unwrap(), Profile::Debug);
102		assert_eq!("release".parse::<Profile>().unwrap(), Profile::Release);
103		assert_eq!("production".parse::<Profile>().unwrap(), Profile::Production);
104	}
105
106	#[test]
107	fn profile_detailed_message() {
108		assert_eq!(Profile::Debug.get_detailed_message(), Some("Optimized for debugging."));
109		assert_eq!(
110			Profile::Release.get_detailed_message(),
111			Some("Optimized without any debugging functionality.")
112		);
113		assert_eq!(
114			Profile::Production.get_detailed_message(),
115			Some("Optimized for ultimate performance.")
116		);
117	}
118
119	#[test]
120	fn profile_target_directory() {
121		let base_path = Path::new("/example/path");
122
123		assert_eq!(
124			Profile::Debug.target_directory(base_path),
125			Path::new("/example/path/target/debug")
126		);
127		assert_eq!(
128			Profile::Release.target_directory(base_path),
129			Path::new("/example/path/target/release")
130		);
131		assert_eq!(
132			Profile::Production.target_directory(base_path),
133			Path::new("/example/path/target/production")
134		);
135	}
136
137	#[test]
138	fn profile_default() {
139		let default_profile = Profile::default();
140		assert_eq!(default_profile, Profile::Release);
141	}
142
143	#[test]
144	fn profile_from_bool() {
145		assert_eq!(Profile::from(true), Profile::Release);
146		assert_eq!(Profile::from(false), Profile::Debug);
147	}
148
149	#[test]
150	fn profile_into_bool() {
151		assert!(!bool::from(Profile::Debug));
152		assert!(bool::from(Profile::Release));
153		assert!(bool::from(Profile::Production));
154	}
155}