summaryrefslogtreecommitdiffstats
path: root/library/std/src/sys/hermit/args.rs
blob: afcae6c90ee02ffad8839d69688ac3ee2c859324 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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<OsString> = (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<OsString>,
}

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<OsString> {
        self.iter.next()
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        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<OsString> {
        self.iter.next_back()
    }
}