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