|
| 1 | +use core::cell::SyncUnsafeCell; |
| 2 | +use core::ptr::NonNull; |
| 3 | + |
1 | 4 | use crate::ffi::OsString;
|
2 | 5 | use crate::fmt;
|
| 6 | +use crate::mem::MaybeUninit; |
| 7 | + |
| 8 | +#[derive(Debug, Clone, Copy)] |
| 9 | +pub(super) struct RawArgs { |
| 10 | + pub(super) args: NonNull<[(NonNull<u8>, usize)]>, |
| 11 | +} |
| 12 | + |
| 13 | +impl RawArgs { |
| 14 | + fn len(&self) -> usize { |
| 15 | + unsafe { (*self.args.as_ptr()).len() } |
| 16 | + } |
3 | 17 |
|
4 |
| -pub struct Args {} |
| 18 | + fn get(&self, index: usize) -> Option<&'static str> { |
| 19 | + unsafe { |
| 20 | + let args = &*self.args.as_ptr(); |
| 21 | + let (ptr, len) = args.get(index)?; |
| 22 | + Some(core::str::from_utf8_unchecked(core::slice::from_raw_parts(ptr.as_ptr(), *len))) |
| 23 | + } |
| 24 | + } |
| 25 | +} |
| 26 | + |
| 27 | +unsafe impl Sync for RawArgs {} |
| 28 | + |
| 29 | +pub(super) static RAW_ARGS: SyncUnsafeCell<MaybeUninit<Option<RawArgs>>> = |
| 30 | + SyncUnsafeCell::new(MaybeUninit::uninit()); |
| 31 | +pub struct Args { |
| 32 | + raw_args: Option<RawArgs>, |
| 33 | + index: usize, |
| 34 | +} |
5 | 35 |
|
6 | 36 | pub fn args() -> Args {
|
7 |
| - Args {} |
| 37 | + Args { raw_args: unsafe { (*RAW_ARGS.get()).assume_init() }, index: 0 } |
8 | 38 | }
|
9 | 39 |
|
10 | 40 | impl fmt::Debug for Args {
|
11 | 41 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
12 |
| - f.debug_list().finish() |
| 42 | + let mut list = f.debug_list(); |
| 43 | + let len = self.len(); |
| 44 | + for i in 0..len { |
| 45 | + // safe because index is always in len and raw_args is initialized (otherwise len is going to be 0) |
| 46 | + let arg = unsafe { self.raw_args.unwrap_unchecked().get(i).unwrap_unchecked() }; |
| 47 | + list.entry(&arg); |
| 48 | + } |
| 49 | + list.finish() |
13 | 50 | }
|
14 | 51 | }
|
15 | 52 |
|
16 | 53 | impl Iterator for Args {
|
17 | 54 | type Item = OsString;
|
18 | 55 | fn next(&mut self) -> Option<OsString> {
|
19 |
| - None |
| 56 | + if self.index >= self.len() { |
| 57 | + return None; |
| 58 | + } |
| 59 | + // it is gruanted that the raw_args is initialized if len > 0 |
| 60 | + let raw_args = unsafe { self.raw_args.unwrap_unchecked() }; |
| 61 | + let results = raw_args.get(self.index).map(|arg| OsString::from(arg)); |
| 62 | + self.index += 1; |
| 63 | + results |
20 | 64 | }
|
21 | 65 | fn size_hint(&self) -> (usize, Option<usize>) {
|
22 |
| - (0, Some(0)) |
| 66 | + let len = self.len(); |
| 67 | + |
| 68 | + if len == 0 { |
| 69 | + (0, Some(0)) |
| 70 | + } else { |
| 71 | + let left = len - self.index; |
| 72 | + (left, Some(left)) |
| 73 | + } |
23 | 74 | }
|
24 | 75 | }
|
25 | 76 |
|
26 | 77 | impl ExactSizeIterator for Args {
|
27 | 78 | fn len(&self) -> usize {
|
28 |
| - 0 |
| 79 | + self.raw_args.map(|s| s.len()).unwrap_or(0) |
29 | 80 | }
|
30 | 81 | }
|
31 | 82 |
|
32 | 83 | impl DoubleEndedIterator for Args {
|
33 | 84 | fn next_back(&mut self) -> Option<OsString> {
|
34 |
| - None |
| 85 | + todo!("next_back on Args is not implemented yet") |
35 | 86 | }
|
36 | 87 | }
|
0 commit comments