blob: 6750cf33d7686e06afef72fe93d8a8715e97f001 [file] [edit]
use crate::ffi::OsString;
use crate::num::NonZero;
use crate::ops::Try;
use crate::sync::OnceLock;
use crate::sys::FromInner;
use crate::sys::os_str::Buf;
use crate::sys::pal::abi::usercalls::alloc;
use crate::sys::pal::abi::usercalls::raw::ByteBuffer;
use crate::{fmt, slice};
// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
#[cfg_attr(test, linkage = "available_externally")]
#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE")]
static ARGS: OnceLock<Vec<OsString>> = OnceLock::new();
#[cfg_attr(test, allow(dead_code))]
pub unsafe fn init(argc: isize, argv: *const *const u8) {
if argc != 0 {
let args = unsafe { alloc::User::<[ByteBuffer]>::from_raw_parts(argv as _, argc as _) };
let args = args
.iter()
.map(|a| OsString::from_inner(Buf { inner: a.copy_user_buffer() }))
.collect::<Vec<_>>();
if let Err(_) = ARGS.set(args) {
rtabort!("init called twice");
}
}
}
pub fn args() -> Args {
Args { iter: ARGS.get().map_or_default(|args| args.iter()) }
}
pub struct Args {
iter: slice::Iter<'static, OsString>,
}
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().cloned()
}
#[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().cloned()
}
#[inline]
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
self.iter.advance_by(n)
}
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
where
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
self.iter.by_ref().cloned().try_fold(init, f)
}
fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
self.iter.cloned().fold(init, f)
}
}
impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
self.iter.next_back().cloned()
}
#[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()
}
}