#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers use crate::ffi::OsString; use crate::num::NonZero; use crate::ops::Try; use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; use crate::sys::os_str::Buf; use crate::sys::pal::abi::usercalls::alloc; use crate::sys::pal::abi::usercalls::raw::ByteBuffer; use crate::sys_common::FromInner; 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: Atomic = AtomicUsize::new(0); type ArgsStore = Vec; #[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::(); ARGS.store(Box::into_raw(Box::new(args)) as _, Ordering::Relaxed); } } pub fn args() -> Args { let args = unsafe { (ARGS.load(Ordering::Relaxed) as *const ArgsStore).as_ref() }; let slice = args.map(|args| args.as_slice()).unwrap_or(&[]); Args { iter: slice.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 { self.iter.next().cloned() } #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } #[inline] fn count(self) -> usize { self.iter.len() } fn last(self) -> Option { self.iter.last().cloned() } #[inline] fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { self.iter.advance_by(n) } fn try_fold(&mut self, init: B, f: F) -> R where F: FnMut(B, Self::Item) -> R, R: Try, { self.iter.by_ref().cloned().try_fold(init, f) } fn fold(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 { self.iter.next_back().cloned() } #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { 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() } }