task/
environment_variable.rs

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