1use 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#[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 #[strum(serialize = "debug", message = "Debug", detailed_message = "Optimized for debugging.")]
28 Debug,
29 #[default]
31 #[strum(
32 serialize = "release",
33 message = "Release",
34 detailed_message = "Optimized without any debugging functionality."
35 )]
36 Release,
37 #[strum(
39 serialize = "production",
40 message = "Production",
41 detailed_message = "Optimized for ultimate performance."
42 )]
43 Production,
44}
45
46impl Profile {
47 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 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}