nstd_sys/env.rs
1//! Process environment management.
2use crate::{
3 alloc::NSTD_ALLOCATOR,
4 core::{
5 alloc::NSTDAllocError::NSTD_ALLOC_ERROR_NONE, optional::NSTDOptional, result::NSTDResult,
6 str::NSTDStr,
7 },
8 io::{NSTDIOError, NSTDIOStringResult},
9 string::{NSTDOptionalString, NSTDString},
10 vec::{nstd_vec_new, nstd_vec_push, NSTDVec},
11};
12use core::ptr::addr_of;
13use nstdapi::nstdapi;
14use std::env::VarError;
15
16/// Returns a complete path to the process's current working directory.
17///
18/// # Returns
19///
20/// `NSTDIOStringResult working_dir` - A path to the current working directory on success, or the
21/// I/O operation error code on failure.
22#[nstdapi]
23pub fn nstd_env_current_dir() -> NSTDIOStringResult<'static> {
24 match std::env::current_dir() {
25 Ok(dir) => dir.to_str().map_or(
26 NSTDResult::Err(NSTDIOError::NSTD_IO_ERROR_INVALID_DATA),
27 |dir| NSTDResult::Ok(NSTDString::from_string(dir.into())),
28 ),
29 Err(err) => NSTDResult::Err(NSTDIOError::from_err(err.kind())),
30 }
31}
32
33/// Returns a complete path to the process executable.
34///
35/// # Note
36///
37/// Please see Rust's documentation for information about the security of this function
38/// <https://doc.rust-lang.org/std/env/fn.current_exe.html>.
39///
40/// # Returns
41///
42/// `NSTDIOStringResult exe` - A complete path to process executable on success, or the I/O
43/// operation error code on failure.
44#[nstdapi]
45pub fn nstd_env_current_exe() -> NSTDIOStringResult<'static> {
46 match std::env::current_exe() {
47 Ok(exe) => exe.to_str().map_or(
48 NSTDResult::Err(NSTDIOError::NSTD_IO_ERROR_INVALID_DATA),
49 |exe| NSTDResult::Ok(NSTDString::from_string(exe.into())),
50 ),
51 Err(err) => NSTDResult::Err(NSTDIOError::from_err(err.kind())),
52 }
53}
54
55/// Returns a complete path to a temporary directory.
56///
57/// # Returns
58///
59/// `NSTDOptionalString temp` - A path to the temporary directory.
60#[nstdapi]
61pub fn nstd_env_temp_dir() -> NSTDOptionalString<'static> {
62 std::env::temp_dir()
63 .to_str()
64 .map_or(NSTDOptional::None, |temp| {
65 NSTDOptional::Some(NSTDString::from_string(temp.into()))
66 })
67}
68
69/// Sets the current working directory for the process.
70///
71/// # Parameters:
72///
73/// - `const NSTDStr *path` - The directory to set as the process working directory.
74///
75/// # Returns
76///
77/// `NSTDIOError errc` - The I/O operation error code.
78///
79/// # Safety
80///
81/// The user of this function must ensure that `path` is valid for reads.
82#[nstdapi]
83pub unsafe fn nstd_env_set_current_dir(path: &NSTDStr) -> NSTDIOError {
84 match std::env::set_current_dir(path.as_str()) {
85 Err(err) => NSTDIOError::from_err(err.kind()),
86 _ => NSTDIOError::NSTD_IO_ERROR_NONE,
87 }
88}
89
90/// Retrieves a variable from the process environment.
91///
92/// # Parameters:
93///
94/// - `const NSTDStr *key` - The variable's key.
95///
96/// # Returns
97///
98/// `NSTDIOStringResult var` - The value of the environment variable, or the I/O operation error
99/// code on failure. This will return as `NSTD_IO_ERROR_NOT_FOUND` if they variable cannot be found,
100/// and `NSTD_IO_ERROR_INVALID_DATA` if the variable isn't valid Unicode.
101///
102/// # Safety
103///
104/// The user of this function must ensure that `key` is valid for reads.
105#[nstdapi]
106pub unsafe fn nstd_env_var(key: &NSTDStr) -> NSTDIOStringResult<'_> {
107 match std::env::var(key.as_str()) {
108 Ok(var) => NSTDResult::Ok(NSTDString::from_string(var)),
109 Err(VarError::NotPresent) => NSTDResult::Err(NSTDIOError::NSTD_IO_ERROR_NOT_FOUND),
110 Err(VarError::NotUnicode(_)) => NSTDResult::Err(NSTDIOError::NSTD_IO_ERROR_INVALID_DATA),
111 }
112}
113
114/// Sets an environment variable for the current process.
115///
116/// # Parameters:
117///
118/// - `const NSTDStr *key` - The environment variable's identification key.
119///
120/// - `const NSTDStr *value` - The environment variable's value.
121///
122/// # Panics
123///
124/// This operation will panic in the following situations:
125///
126/// - `key` is empty or contains either of the following ASCII characters: `'='` or `'\0'`.
127///
128/// - `value` contains the ASCII null character `'\0'`.
129///
130/// # Safety
131///
132/// The user of this function must ensure that both `key` and `value` are valid for reads.
133#[inline]
134#[nstdapi]
135pub unsafe fn nstd_env_set_var(key: &NSTDStr, value: &NSTDStr) {
136 std::env::set_var(key.as_str(), value.as_str());
137}
138
139/// Removes an environment variable from the current process.
140///
141/// # Parameters:
142///
143/// - `const NSTDStr *key` - The environment variable's identification key.
144///
145/// # Panics
146///
147/// This operation will panic in the following situations:
148///
149/// - `key` is empty or contains either of the following ASCII characters: `'='` or `'\0'`.
150///
151/// - The environment variable's value contains the ASCII null character `'\0'`.
152///
153/// # Safety
154///
155/// The user of this function must ensure that `key` is valid for reads.
156#[inline]
157#[nstdapi]
158pub unsafe fn nstd_env_remove_var(key: &NSTDStr) {
159 std::env::remove_var(key.as_str());
160}
161
162/// Returns an `NSTDVec` of `NSTDString`s that each represent an argument received at program start.
163///
164/// # Returns
165///
166/// `NSTDVec args` - The `NSTDString` arguments that the program was started with.
167///
168/// # Panics
169///
170/// This operation will panic if any program arguments contain invalid Unicode.
171#[nstdapi]
172pub fn nstd_env_args() -> NSTDVec<'static> {
173 let size = core::mem::size_of::<NSTDString<'_>>();
174 let align = core::mem::align_of::<NSTDString<'_>>();
175 let mut args = nstd_vec_new(&NSTD_ALLOCATOR, size, align);
176 for arg in std::env::args() {
177 let arg = NSTDString::from_string(arg);
178 // SAFETY: `arg` is stored on the stack.
179 let errc = unsafe { nstd_vec_push(&mut args, addr_of!(arg).cast()) };
180 if errc == NSTD_ALLOC_ERROR_NONE {
181 core::mem::forget(arg);
182 }
183 }
184 args
185}
186
187/// Returns an `NSTDVec` of `NSTDString[2]` which each represent an environment variable from the
188/// current process.
189///
190/// # Returns
191///
192/// `NSTDVec vars` - A list of the process environment variables.
193///
194/// # Panics
195///
196/// This operation will panic if any environment variables contain invalid Unicode.
197#[nstdapi]
198pub fn nstd_env_vars() -> NSTDVec<'static> {
199 let size = core::mem::size_of::<[NSTDString<'_>; 2]>();
200 let align = core::mem::align_of::<[NSTDString<'_>; 2]>();
201 let mut vars = nstd_vec_new(&NSTD_ALLOCATOR, size, align);
202 for (k, v) in std::env::vars() {
203 let var = [NSTDString::from_string(k), NSTDString::from_string(v)];
204 // SAFETY: `var` is stored on the stack.
205 let errc = unsafe { nstd_vec_push(&mut vars, addr_of!(var).cast()) };
206 if errc == NSTD_ALLOC_ERROR_NONE {
207 core::mem::forget(var);
208 }
209 }
210 vars
211}