| use crate::ffi::{OsStr, OsString}; | |
| use crate::num::NonZero; | |
| use crate::sync::OnceLock; | |
| use crate::sys::pal::{WORD_SIZE, abi}; | |
| use crate::{fmt, ptr, slice}; | |
| pub fn args() -> Args { | |
| Args { iter: ARGS.get_or_init(|| get_args()).iter() } | |
| } | |
| fn get_args() -> Vec<&'static OsStr> { | |
| let argc = unsafe { abi::sys_argc() }; | |
| let mut args = Vec::with_capacity(argc); | |
| for i in 0..argc { | |
| // Get the size of the argument then the data. | |
| let arg_len = unsafe { abi::sys_argv(ptr::null_mut(), 0, i) }; | |
| let arg_len_words = (arg_len + WORD_SIZE - 1) / WORD_SIZE; | |
| let words = unsafe { abi::sys_alloc_words(arg_len_words) }; | |
| let arg_len2 = unsafe { abi::sys_argv(words, arg_len_words, i) }; | |
| debug_assert_eq!(arg_len, arg_len2); | |
| let arg_bytes = unsafe { slice::from_raw_parts(words.cast(), arg_len) }; | |
| args.push(unsafe { OsStr::from_encoded_bytes_unchecked(arg_bytes) }); | |
| } | |
| args | |
| } | |
| static ARGS: OnceLock<Vec<&'static OsStr>> = OnceLock::new(); | |
| pub struct Args { | |
| iter: slice::Iter<'static, &'static OsStr>, | |
| } | |
| impl !Send for Args {} | |
| impl !Sync for Args {} | |
| impl fmt::Debug for Args { | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| self.iter.as_slice().fmt(f) | |
| } | |
| } | |
| impl Iterator for Args { | |
| type Item = OsString; | |
| fn next(&mut self) -> Option<OsString> { | |
| self.iter.next().map(|arg| arg.to_os_string()) | |
| } | |
| #[inline] | |
| fn size_hint(&self) -> (usize, Option<usize>) { | |
| self.iter.size_hint() | |
| } | |
| #[inline] | |
| fn count(self) -> usize { | |
| self.iter.len() | |
| } | |
| fn last(self) -> Option<OsString> { | |
| self.iter.last().map(|arg| arg.to_os_string()) | |
| } | |
| #[inline] | |
| fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { | |
| self.iter.advance_by(n) | |
| } | |
| } | |
| impl DoubleEndedIterator for Args { | |
| fn next_back(&mut self) -> Option<OsString> { | |
| self.iter.next_back().map(|arg| arg.to_os_string()) | |
| } | |
| #[inline] | |
| fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { | |
| self.iter.advance_back_by(n) | |
| } | |
| } | |
| impl ExactSizeIterator for Args { | |
| #[inline] | |
| fn len(&self) -> usize { | |
| self.iter.len() | |
| } | |
| #[inline] | |
| fn is_empty(&self) -> bool { | |
| self.iter.is_empty() | |
| } | |
| } |