task/
environment_variable.rs1use alloc::{ffi::CString, format};
2use core::fmt::Debug;
3use synchronization::Arc;
4
5#[derive(Clone, Eq, PartialEq, Hash)]
6pub struct EnvironmentVariable(Arc<CString>, usize);
7
8impl Debug for EnvironmentVariable {
9 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
10 formatter
11 .debug_struct("EnvironmentVariable")
12 .field("Name", &self.get_name())
13 .field("Value", &self.get_value())
14 .finish()
15 }
16}
17
18impl EnvironmentVariable {
19 pub fn new(name: &str, value: &str) -> Self {
21 let environment_variable = CString::new(format!("{name}={value}")).unwrap();
22 Self(Arc::new(environment_variable), name.len())
23 }
24
25 pub fn get_name(&self) -> &str {
37 self.0.to_str().unwrap()[..self.1].trim_end_matches('\0')
38 }
39
40 pub fn get_value(&self) -> &str {
52 self.0.to_str().unwrap()[self.1 + 1..].trim_end_matches('\0')
53 }
54
55 pub fn get_raw(&self) -> &CString {
57 &self.0
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn test_environment_variable_creation() {
67 let env_var = EnvironmentVariable::new("PATH", "/usr/bin:/bin");
68
69 assert_eq!(env_var.get_name(), "PATH");
70 assert_eq!(env_var.get_value(), "/usr/bin:/bin");
71 }
72
73 #[test]
74 fn test_environment_variable_empty_name() {
75 let env_var = EnvironmentVariable::new("", "some_value");
76
77 assert_eq!(env_var.get_name(), "");
78 assert_eq!(env_var.get_value(), "some_value");
79 }
80
81 #[test]
82 fn test_environment_variable_empty_value() {
83 let env_var = EnvironmentVariable::new("EMPTY_VAR", "");
84
85 assert_eq!(env_var.get_name(), "EMPTY_VAR");
86 assert_eq!(env_var.get_value(), "");
87 }
88
89 #[test]
90 fn test_environment_variable_both_empty() {
91 let env_var = EnvironmentVariable::new("", "");
92
93 assert_eq!(env_var.get_name(), "");
94 assert_eq!(env_var.get_value(), "");
95 }
96
97 #[test]
98 fn test_environment_variable_special_characters() {
99 let name = "TEST_VAR";
100 let value = "value with spaces and !@#$%^&*()";
101 let env_var = EnvironmentVariable::new(name, value);
102
103 assert_eq!(env_var.get_name(), name);
104 assert_eq!(env_var.get_value(), value);
105 }
106
107 #[test]
108 fn test_environment_variable_equals_in_value() {
109 let name = "CONFIG";
110 let value = "key=value=another=part";
111 let env_var = EnvironmentVariable::new(name, value);
112
113 assert_eq!(env_var.get_name(), name);
114 assert_eq!(env_var.get_value(), value);
115 }
116
117 #[test]
118 fn test_environment_variable_unicode() {
119 let name = "UNICODE_VAR";
120 let value = "🦀 Rust is awesome! 䏿–‡æµ‹è¯•";
121 let env_var = EnvironmentVariable::new(name, value);
122
123 assert_eq!(env_var.get_name(), name);
124 assert_eq!(env_var.get_value(), value);
125 }
126
127 #[test]
128 fn test_environment_variable_clone() {
129 let env_var1 = EnvironmentVariable::new("HOME", "/home/user");
130 let env_var2 = env_var1.clone();
131
132 assert_eq!(env_var1.get_name(), env_var2.get_name());
133 assert_eq!(env_var1.get_value(), env_var2.get_value());
134 assert_eq!(env_var1, env_var2);
135 }
136
137 #[test]
138 fn test_environment_variable_equality() {
139 let env_var1 = EnvironmentVariable::new("USER", "alice");
140 let env_var2 = EnvironmentVariable::new("USER", "alice");
141 let env_var3 = EnvironmentVariable::new("USER", "bob");
142 let env_var4 = EnvironmentVariable::new("HOME", "alice");
143
144 assert_eq!(env_var1, env_var2);
145 assert_ne!(env_var1, env_var3);
146 assert_ne!(env_var1, env_var4);
147 }
148
149 #[test]
150 fn test_environment_variable_hash() {
151 use std::collections::HashMap;
152
153 let env_var1 = EnvironmentVariable::new("PATH", "/usr/bin");
154 let env_var2 = EnvironmentVariable::new("HOME", "/home/user");
155 let env_var3 = EnvironmentVariable::new("PATH", "/usr/bin"); let mut map = HashMap::new();
158 map.insert(env_var1.clone(), "first");
159 map.insert(env_var2.clone(), "second");
160
161 map.insert(env_var3.clone(), "third");
163
164 assert_eq!(map.len(), 2);
165 assert_eq!(map.get(&env_var1), Some(&"third")); assert_eq!(map.get(&env_var2), Some(&"second"));
167 assert_eq!(map.get(&env_var3), Some(&"third"));
168 }
169
170 #[test]
171 fn test_environment_variable_debug_format() {
172 let env_var = EnvironmentVariable::new("DEBUG_VAR", "debug_value");
173 let debug_string = format!("{env_var:?}");
174
175 assert!(debug_string.contains("EnvironmentVariable"));
176 assert!(debug_string.contains("DEBUG_VAR"));
177 assert!(debug_string.contains("debug_value"));
178 }
179
180 #[test]
181 fn test_environment_variable_get_raw() {
182 let name = "RAW_TEST";
183 let value = "raw_value";
184 let env_var = EnvironmentVariable::new(name, value);
185 let raw_cstring = env_var.get_raw();
186
187 assert_eq!(raw_cstring.to_str().unwrap(), "RAW_TEST=raw_value");
188 }
189
190 #[test]
191 fn test_environment_variable_long_name_and_value() {
192 let long_name = "A".repeat(1000);
193 let long_value = "B".repeat(2000);
194 let env_var = EnvironmentVariable::new(&long_name, &long_value);
195
196 assert_eq!(env_var.get_name(), long_name);
197 assert_eq!(env_var.get_value(), long_value);
198 }
199
200 #[test]
201 fn test_environment_variable_single_character() {
202 let env_var = EnvironmentVariable::new("A", "B");
203
204 assert_eq!(env_var.get_name(), "A");
205 assert_eq!(env_var.get_value(), "B");
206 }
207
208 #[test]
209 fn test_environment_variable_newlines_and_tabs() {
210 let name = "MULTILINE";
211 let value = "line1\nline2\tvalue";
212 let env_var = EnvironmentVariable::new(name, value);
213
214 assert_eq!(env_var.get_name(), name);
215 assert_eq!(env_var.get_value(), value);
216 }
217
218 #[test]
219 fn test_environment_variable_arc_sharing() {
220 let env_var1 = EnvironmentVariable::new("SHARED", "value");
221 let env_var2 = env_var1.clone();
222
223 assert_eq!(Arc::as_ptr(&env_var1.0), Arc::as_ptr(&env_var2.0));
225
226 assert_eq!(env_var1.get_name(), env_var2.get_name());
228 assert_eq!(env_var1.get_value(), env_var2.get_value());
229 }
230}