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 clap::ValueEnum,
25)]
26pub enum Profile {
27 #[strum(serialize = "debug", message = "Debug", detailed_message = "Optimized for debugging.")]
29 Debug,
30 #[default]
32 #[strum(
33 serialize = "release",
34 message = "Release",
35 detailed_message = "Optimized without any debugging functionality."
36 )]
37 Release,
38 #[strum(
40 serialize = "production",
41 message = "Production",
42 detailed_message = "Optimized for ultimate performance."
43 )]
44 Production,
45}
46
47impl Profile {
48 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 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}