blob: d26bf1eaff91f94fc07ac393c17639f8dd07eceb [file] [log] [blame]
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()
}
}