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