use crate::ffi::{c_char, CStr, OsString}; use crate::fmt; use crate::os::unix::ffi::OsStringExt; use crate::ptr; use crate::sync::atomic::{ AtomicIsize, AtomicPtr, Ordering::{Acquire, Relaxed, Release}, }; use crate::vec; static ARGC: AtomicIsize = AtomicIsize::new(0); static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut()); /// One-time global initialization. pub unsafe fn init(argc: isize, argv: *const *const u8) { ARGC.store(argc, Relaxed); // Use release ordering here to broadcast writes by the OS. ARGV.store(argv as *mut *const u8, Release); } /// Returns the command line arguments pub fn args() -> Args { // Synchronize with the store above. let argv = ARGV.load(Acquire); // If argv has not been initialized yet, do not return any arguments. let argc = if argv.is_null() { 0 } else { ARGC.load(Relaxed) }; let args: Vec = (0..argc) .map(|i| unsafe { let cstr = CStr::from_ptr(*argv.offset(i) as *const c_char); OsStringExt::from_vec(cstr.to_bytes().to_vec()) }) .collect(); Args { iter: args.into_iter() } } pub struct Args { iter: vec::IntoIter, } impl fmt::Debug for Args { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.iter.as_slice().fmt(f) } } impl !Send for Args {} impl !Sync for Args {} impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { self.iter.next() } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } impl ExactSizeIterator for Args { fn len(&self) -> usize { self.iter.len() } } impl DoubleEndedIterator for Args { fn next_back(&mut self) -> Option { self.iter.next_back() } }